Commit 4bd2060a authored by Janos Guljas's avatar Janos Guljas

add metrics for log messages categorized by their level

parent f02789a2
...@@ -50,20 +50,20 @@ func (c *command) initStartCmd() (err error) { ...@@ -50,20 +50,20 @@ func (c *command) initStartCmd() (err error) {
return cmd.Help() return cmd.Help()
} }
logger := logging.New(cmd.OutOrStdout()).(*logrus.Logger) var logger logging.Logger
switch v := strings.ToLower(c.config.GetString(optionNameVerbosity)); v { switch v := strings.ToLower(c.config.GetString(optionNameVerbosity)); v {
case "0", "silent": case "0", "silent":
logger.SetOutput(ioutil.Discard) logger = logging.New(ioutil.Discard, 0)
case "1", "error": case "1", "error":
logger.SetLevel(logrus.ErrorLevel) logger = logging.New(cmd.OutOrStdout(), logrus.ErrorLevel)
case "2", "warn": case "2", "warn":
logger.SetLevel(logrus.WarnLevel) logger = logging.New(cmd.OutOrStdout(), logrus.WarnLevel)
case "3", "info": case "3", "info":
logger.SetLevel(logrus.InfoLevel) logger = logging.New(cmd.OutOrStdout(), logrus.InfoLevel)
case "4", "debug": case "4", "debug":
logger.SetLevel(logrus.DebugLevel) logger = logging.New(cmd.OutOrStdout(), logrus.DebugLevel)
case "5", "trace": case "5", "trace":
logger.SetLevel(logrus.TraceLevel) logger = logging.New(cmd.OutOrStdout(), logrus.TraceLevel)
default: default:
return fmt.Errorf("unknown verbosity level %q", v) return fmt.Errorf("unknown verbosity level %q", v)
} }
......
...@@ -8,13 +8,13 @@ import ( ...@@ -8,13 +8,13 @@ import (
"net/http" "net/http"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
m "github.com/ethersphere/bee/pkg/metrics"
"github.com/ethersphere/bee/pkg/pingpong" "github.com/ethersphere/bee/pkg/pingpong"
"github.com/prometheus/client_golang/prometheus"
) )
type Service interface { type Service interface {
http.Handler http.Handler
Metrics() (cs []prometheus.Collector) m.Collector
} }
type server struct { type server struct {
......
...@@ -24,7 +24,7 @@ type testServerOptions struct { ...@@ -24,7 +24,7 @@ type testServerOptions struct {
func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) { func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) {
s := api.New(api.Options{ s := api.New(api.Options{
Pingpong: o.Pingpong, Pingpong: o.Pingpong,
Logger: logging.New(ioutil.Discard), Logger: logging.New(ioutil.Discard, 0),
}) })
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
cleanup = ts.Close cleanup = ts.Close
......
...@@ -7,8 +7,8 @@ package debugapi ...@@ -7,8 +7,8 @@ package debugapi
import ( import (
"net/http" "net/http"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
......
...@@ -24,7 +24,7 @@ type testServerOptions struct { ...@@ -24,7 +24,7 @@ type testServerOptions struct {
func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) { func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) {
s := debugapi.New(debugapi.Options{ s := debugapi.New(debugapi.Options{
P2P: o.P2P, P2P: o.P2P,
Logger: logging.New(ioutil.Discard), Logger: logging.New(ioutil.Discard, 0),
}) })
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
cleanup = ts.Close cleanup = ts.Close
......
...@@ -21,17 +21,27 @@ type Logger interface { ...@@ -21,17 +21,27 @@ type Logger interface {
Warning(args ...interface{}) Warning(args ...interface{})
Errorf(format string, args ...interface{}) Errorf(format string, args ...interface{})
Error(args ...interface{}) Error(args ...interface{})
SetOutput(io.Writer)
SetLevel(logrus.Level)
WithField(key string, value interface{}) *logrus.Entry WithField(key string, value interface{}) *logrus.Entry
WithFields(fields logrus.Fields) *logrus.Entry WithFields(fields logrus.Fields) *logrus.Entry
WriterLevel(logrus.Level) *io.PipeWriter
} }
func New(w io.Writer) Logger { type logger struct {
*logrus.Logger
metrics metrics
}
func New(w io.Writer, level logrus.Level) Logger {
l := logrus.New() l := logrus.New()
l.SetOutput(w) l.SetOutput(w)
l.SetLevel(level)
l.Formatter = &logrus.TextFormatter{ l.Formatter = &logrus.TextFormatter{
FullTimestamp: true, FullTimestamp: true,
} }
return l metrics := newMetrics()
l.AddHook(metrics)
return &logger{
Logger: l,
metrics: metrics,
}
} }
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package logging
import (
m "github.com/ethersphere/bee/pkg/metrics"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
)
type metrics struct {
// all metrics fields must be exported
// to be able to return them by Metrics()
// using reflection
ErrorCount prometheus.Counter
WarnCount prometheus.Counter
InfoCount prometheus.Counter
DebugCount prometheus.Counter
TraceCount prometheus.Counter
}
func newMetrics() (m metrics) {
return metrics{
ErrorCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "log_error_count",
Help: "Number ERROR log messages.",
}),
WarnCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "log_warn_count",
Help: "Number WARN log messages.",
}),
InfoCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "log_info_count",
Help: "Number INFO log messages.",
}),
DebugCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "log_debug_count",
Help: "Number DEBUG log messages.",
}),
TraceCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "log_trace_count",
Help: "Number TRACE log messages.",
}),
}
}
func (l *logger) Metrics() []prometheus.Collector {
return m.PrometheusCollectorsFromFields(l.metrics)
}
func (m metrics) Levels() []logrus.Level {
return []logrus.Level{
logrus.ErrorLevel,
logrus.WarnLevel,
logrus.InfoLevel,
logrus.DebugLevel,
logrus.TraceLevel,
}
}
func (m metrics) Fire(e *logrus.Entry) error {
switch e.Level {
case logrus.ErrorLevel:
m.ErrorCount.Inc()
case logrus.WarnLevel:
m.WarnCount.Inc()
case logrus.InfoLevel:
m.InfoCount.Inc()
case logrus.DebugLevel:
m.DebugCount.Inc()
case logrus.TraceLevel:
m.TraceCount.Inc()
}
return nil
}
...@@ -10,6 +10,10 @@ import ( ...@@ -10,6 +10,10 @@ import (
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
type Collector interface {
Metrics() []prometheus.Collector
}
func PrometheusCollectorsFromFields(i interface{}) (cs []prometheus.Collector) { func PrometheusCollectorsFromFields(i interface{}) (cs []prometheus.Collector) {
v := reflect.Indirect(reflect.ValueOf(i)) v := reflect.Indirect(reflect.ValueOf(i))
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
......
...@@ -17,6 +17,8 @@ import ( ...@@ -17,6 +17,8 @@ import (
"github.com/ethersphere/bee/pkg/api" "github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/debugapi" "github.com/ethersphere/bee/pkg/debugapi"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/metrics"
"github.com/ethersphere/bee/pkg/p2p/libp2p" "github.com/ethersphere/bee/pkg/p2p/libp2p"
"github.com/ethersphere/bee/pkg/pingpong" "github.com/ethersphere/bee/pkg/pingpong"
) )
...@@ -33,7 +35,7 @@ type Options struct { ...@@ -33,7 +35,7 @@ type Options struct {
APIAddr string APIAddr string
DebugAPIAddr string DebugAPIAddr string
LibP2POptions libp2p.Options LibP2POptions libp2p.Options
Logger *logrus.Logger Logger logging.Logger
} }
func NewBee(o Options) (*Bee, error) { func NewBee(o Options) (*Bee, error) {
...@@ -113,6 +115,9 @@ func NewBee(o Options) (*Bee, error) { ...@@ -113,6 +115,9 @@ func NewBee(o Options) (*Bee, error) {
if apiService != nil { if apiService != nil {
debugAPIService.MustRegisterMetrics(apiService.Metrics()...) debugAPIService.MustRegisterMetrics(apiService.Metrics()...)
} }
if l, ok := logger.(metrics.Collector); ok {
debugAPIService.MustRegisterMetrics(l.Metrics()...)
}
debugAPIListener, err := net.Listen("tcp", o.DebugAPIAddr) debugAPIListener, err := net.Listen("tcp", o.DebugAPIAddr)
if err != nil { if err != nil {
......
...@@ -43,7 +43,7 @@ func (s *StreamMock) Close() error { ...@@ -43,7 +43,7 @@ func (s *StreamMock) Close() error {
} }
func TestHandshake(t *testing.T) { func TestHandshake(t *testing.T) {
logger := logging.New(ioutil.Discard) logger := logging.New(ioutil.Discard, 0)
info := Info{ info := Info{
Address: "node1", Address: "node1",
NetworkID: 0, NetworkID: 0,
...@@ -118,7 +118,7 @@ func TestHandle(t *testing.T) { ...@@ -118,7 +118,7 @@ func TestHandle(t *testing.T) {
Light: false, Light: false,
} }
logger := logging.New(ioutil.Discard) logger := logging.New(ioutil.Discard, 0)
handshakeService := New(nodeInfo.Address, nodeInfo.NetworkID, logger) handshakeService := New(nodeInfo.Address, nodeInfo.NetworkID, logger)
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
......
...@@ -22,7 +22,7 @@ import ( ...@@ -22,7 +22,7 @@ import (
) )
func TestPing(t *testing.T) { func TestPing(t *testing.T) {
logger := logging.New(ioutil.Discard) logger := logging.New(ioutil.Discard, 0)
// create a pingpong server that handles the incoming stream // create a pingpong server that handles the incoming stream
server := pingpong.New(pingpong.Options{ server := pingpong.New(pingpong.Options{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment