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) {
return cmd.Help()
}
logger := logging.New(cmd.OutOrStdout()).(*logrus.Logger)
var logger logging.Logger
switch v := strings.ToLower(c.config.GetString(optionNameVerbosity)); v {
case "0", "silent":
logger.SetOutput(ioutil.Discard)
logger = logging.New(ioutil.Discard, 0)
case "1", "error":
logger.SetLevel(logrus.ErrorLevel)
logger = logging.New(cmd.OutOrStdout(), logrus.ErrorLevel)
case "2", "warn":
logger.SetLevel(logrus.WarnLevel)
logger = logging.New(cmd.OutOrStdout(), logrus.WarnLevel)
case "3", "info":
logger.SetLevel(logrus.InfoLevel)
logger = logging.New(cmd.OutOrStdout(), logrus.InfoLevel)
case "4", "debug":
logger.SetLevel(logrus.DebugLevel)
logger = logging.New(cmd.OutOrStdout(), logrus.DebugLevel)
case "5", "trace":
logger.SetLevel(logrus.TraceLevel)
logger = logging.New(cmd.OutOrStdout(), logrus.TraceLevel)
default:
return fmt.Errorf("unknown verbosity level %q", v)
}
......
......@@ -8,13 +8,13 @@ import (
"net/http"
"github.com/ethersphere/bee/pkg/logging"
m "github.com/ethersphere/bee/pkg/metrics"
"github.com/ethersphere/bee/pkg/pingpong"
"github.com/prometheus/client_golang/prometheus"
)
type Service interface {
http.Handler
Metrics() (cs []prometheus.Collector)
m.Collector
}
type server struct {
......
......@@ -24,7 +24,7 @@ type testServerOptions struct {
func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) {
s := api.New(api.Options{
Pingpong: o.Pingpong,
Logger: logging.New(ioutil.Discard),
Logger: logging.New(ioutil.Discard, 0),
})
ts := httptest.NewServer(s)
cleanup = ts.Close
......
......@@ -7,8 +7,8 @@ package debugapi
import (
"net/http"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/prometheus/client_golang/prometheus"
)
......
......@@ -24,7 +24,7 @@ type testServerOptions struct {
func newTestServer(t *testing.T, o testServerOptions) (client *http.Client, cleanup func()) {
s := debugapi.New(debugapi.Options{
P2P: o.P2P,
Logger: logging.New(ioutil.Discard),
Logger: logging.New(ioutil.Discard, 0),
})
ts := httptest.NewServer(s)
cleanup = ts.Close
......
......@@ -21,17 +21,27 @@ type Logger interface {
Warning(args ...interface{})
Errorf(format string, args ...interface{})
Error(args ...interface{})
SetOutput(io.Writer)
SetLevel(logrus.Level)
WithField(key string, value interface{}) *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.SetOutput(w)
l.SetLevel(level)
l.Formatter = &logrus.TextFormatter{
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 (
"github.com/prometheus/client_golang/prometheus"
)
type Collector interface {
Metrics() []prometheus.Collector
}
func PrometheusCollectorsFromFields(i interface{}) (cs []prometheus.Collector) {
v := reflect.Indirect(reflect.ValueOf(i))
for i := 0; i < v.NumField(); i++ {
......
......@@ -17,6 +17,8 @@ import (
"github.com/ethersphere/bee/pkg/api"
"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/pingpong"
)
......@@ -33,7 +35,7 @@ type Options struct {
APIAddr string
DebugAPIAddr string
LibP2POptions libp2p.Options
Logger *logrus.Logger
Logger logging.Logger
}
func NewBee(o Options) (*Bee, error) {
......@@ -113,6 +115,9 @@ func NewBee(o Options) (*Bee, error) {
if apiService != nil {
debugAPIService.MustRegisterMetrics(apiService.Metrics()...)
}
if l, ok := logger.(metrics.Collector); ok {
debugAPIService.MustRegisterMetrics(l.Metrics()...)
}
debugAPIListener, err := net.Listen("tcp", o.DebugAPIAddr)
if err != nil {
......
......@@ -43,7 +43,7 @@ func (s *StreamMock) Close() error {
}
func TestHandshake(t *testing.T) {
logger := logging.New(ioutil.Discard)
logger := logging.New(ioutil.Discard, 0)
info := Info{
Address: "node1",
NetworkID: 0,
......@@ -118,7 +118,7 @@ func TestHandle(t *testing.T) {
Light: false,
}
logger := logging.New(ioutil.Discard)
logger := logging.New(ioutil.Discard, 0)
handshakeService := New(nodeInfo.Address, nodeInfo.NetworkID, logger)
t.Run("OK", func(t *testing.T) {
......
......@@ -22,7 +22,7 @@ import (
)
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
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