Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Severity to be emitted as metrics is configurable now #5

Merged
merged 2 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: go
go:
- 1.14.x

script:
- go test
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# promlog

[![GoDoc Widget]][GoDoc]

---
[forked klog](https://github.com/practo/klog) hook to expose the number of log messages as Prometheus metrics:
```
log_messages_total{severity="ERROR"} 0
Expand All @@ -23,7 +27,7 @@ import (

func main() {
// Create the Prometheus hook:
hook := promlog.MustNewPrometheusHook("")
hook := promlog.MustNewPrometheusHook("", klog.InfoSeverityLevel)

// Configure klog to use the Prometheus hook:
klog.AddHook(hook)
Expand Down Expand Up @@ -75,3 +79,6 @@ E0624 13:27:29.698964 51237 promlog_test.go:61] this is at error level!
PASS
ok github.com/practo/promlog 0.237s
```

[GoDoc]: https://godoc.org/github.com/practo/promlog
[GoDoc Widget]: https://godoc.org/github.com/practo/k8s-worker-pod-autoscaler?status.svg
2 changes: 1 addition & 1 deletion example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func main() {
// Create the Prometheus hook:
hook := promlog.MustNewPrometheusHook("")
hook := promlog.MustNewPrometheusHook("", klog.InfoSeverityLevel)

// Configure klog to use the Prometheus hook:
klog.AddHook(hook)
Expand Down
55 changes: 47 additions & 8 deletions promlog.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package promlog

import (
"fmt"
"github.com/practo/klog/v2"
"github.com/prometheus/client_golang/prometheus"
)

// supportedSeverityLevels are the level of severities supported
var supportedSeverityLevels = []string{
klog.InfoSeverityLevel,
klog.WarningSeverityLevel,
Expand All @@ -13,7 +15,10 @@ var supportedSeverityLevels = []string{

// PrometheusHook exposes Prometheus counters for each of klog severity levels.
type PrometheusHook struct {
counterVec *prometheus.CounterVec
// severityLevel specifies the required level for the log metrics
// that must be emitted as prometheus metric
severityLevel string
counterVec *prometheus.CounterVec
}

// NewPrometheusHook creates a new instance of PrometheusHook
Expand All @@ -22,15 +27,43 @@ type PrometheusHook struct {
// caller in case of issue.
// Use NewPrometheusHook if you want more control.
// Use MustNewPrometheusHook if you want a less verbose hook creation.
func NewPrometheusHook(metricPrefix string) (*PrometheusHook, error) {
func NewPrometheusHook(
metricPrefix string, severityLevel string) (*PrometheusHook, error) {

counterVec := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metricPrefix + "log_messages_total",
Name: metricPrefix + "log_messages_total",
Help: "Total number of log messages.",
}, []string{"severity"})

var severityLevels []string

switch severityLevel {
case klog.InfoSeverityLevel:
severityLevels = []string{
klog.InfoSeverityLevel,
klog.WarningSeverityLevel,
klog.ErrorSeverityLevel,
}
case klog.WarningSeverityLevel:
severityLevels = []string{
klog.WarningSeverityLevel,
klog.ErrorSeverityLevel,
}
case klog.ErrorSeverityLevel:
severityLevels = []string{
klog.ErrorSeverityLevel,
}
default:
return nil, fmt.Errorf(
"only following severity levels are supported: %v",
supportedSeverityLevels)
}

// Initialise counters for all supported severity:
for _, severity := range supportedSeverityLevels {
for _, severity := range severityLevels {
counterVec.WithLabelValues(severity)
}

// Try to unregister the counter vector,
// in case already registered for some reason,
// e.g. double initialisation/configuration
Expand All @@ -41,8 +74,10 @@ func NewPrometheusHook(metricPrefix string) (*PrometheusHook, error) {
if err != nil {
return nil, err
}

return &PrometheusHook{
counterVec: counterVec,
severityLevel: severityLevel,
counterVec: counterVec,
}, nil
}

Expand All @@ -52,23 +87,27 @@ func NewPrometheusHook(metricPrefix string) (*PrometheusHook, error) {
// any error to the caller, but panics instead.
// Use MustNewPrometheusHook if you want a less verbose
// hook creation. Use NewPrometheusHook if you want more control.
func MustNewPrometheusHook(metricPrefix string) *PrometheusHook {
hook, err := NewPrometheusHook(metricPrefix)
func MustNewPrometheusHook(
metricPrefix string, severityLevel string) *PrometheusHook {

hook, err := NewPrometheusHook(metricPrefix, severityLevel)
if err != nil {
panic(err)
}

return hook
}

// Fire increments the appropriate Prometheus counter
func (hook *PrometheusHook) Fire(s string, args ...interface{}) error {
hook.counterVec.WithLabelValues(s).Inc()

return nil
}

// SeverityLevel can be "INFO", "WARNING", "ERROR" or "FATAL"
// Hook will be fired in all the cases when severity is greater than
// or equal to the severity level
func (hook *PrometheusHook) SeverityLevel() string {
return klog.InfoSeverityLevel
return hook.severityLevel
}
18 changes: 13 additions & 5 deletions promlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import (
)

const (
addr string = ":8080"
endpoint string = "/metrics"
testPrefix string = "promlog"
addr string = ":8080"
endpoint string = "/metrics"
testSeverityLevel string = "INFO"
testPrefix string = "promlog"
)

func getSeverityForLine(line string) string {
Expand All @@ -36,7 +37,7 @@ func getSeverityForLine(line string) string {

func TestExposeAndQueryKlogCounters(t *testing.T) {
// Create Prometheus hook and configure klog to use it:
hook := promlog.MustNewPrometheusHook(testPrefix)
hook := promlog.MustNewPrometheusHook(testPrefix, testSeverityLevel)
klog.AddHook(hook)

server := httpServePrometheusMetrics(t)
Expand Down Expand Up @@ -67,6 +68,13 @@ func TestExposeAndQueryKlogCounters(t *testing.T) {
server.Close()
}

func TestInvalidSeverityLevel(t *testing.T) {
_, err := promlog.NewPrometheusHook(testPrefix, "PANIC")
if err == nil {
t.Error("expected invalid severity error")
}
}

// httpServePrometheusMetrics exposes the Prometheus metrics
// over HTTP, in a different go routine.
func httpServePrometheusMetrics(t *testing.T) *http.Server {
Expand Down Expand Up @@ -107,7 +115,7 @@ func countFor(t *testing.T, severity string, lines []string) int {
// # TYPE test_debug counter
// test_debug 0
metric := fmt.Sprintf(
testPrefix + "log_messages_total{severity=\"%v\"}", severity)
testPrefix+"log_messages_total{severity=\"%v\"}", severity)
for _, line := range lines {
items := strings.Split(line, " ")
if len(items) != 2 { // e.g. {"test_debug", "0"}
Expand Down