Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

contrib/sirupsen/logrus: Add context logging hook #1240

Merged
merged 11 commits into from May 4, 2022
29 changes: 29 additions & 0 deletions contrib/sirupsen/logrus/example_test.go
@@ -0,0 +1,29 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2022 Datadog, Inc.

package logrus

import (
"context"

"github.com/sirupsen/logrus"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
)

func ExampleHook() {
//Setup logrus, do this once at the beginning of your program
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.AddHook(&DDContextLogHook{})

span, sctx := tracer.StartSpanFromContext(context.Background(), "mySpan")

//Pass the current context to the logger
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
cLog := logrus.WithContext(sctx)
//Log as desired using the context-aware logger
cLog.Info("Completed some work!")
Copy link
Contributor

@gbbr gbbr Apr 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use // Output: here? (https://go.dev/blog/examples)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh neat! I've never used // Output: before.

It seems to make the example a bit more clunky as it means that the output has to be set to stdout and the time overridden to a fixed value. I've pushed up the change with the Output validation, let me know if you think it's not worth the extra couple lines of complexity. I'm leaning towards it's not worth it given there's a unit test that validates the Hook method already and my hope for the example was it's mostly copy/paste for users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is great actually. But frankly I was expecting the comment to be just below the log call that causes it. But perhaps I don't fully understand how Output: works. Disclaimer: I've never used it.


span.Finish()
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
}
32 changes: 32 additions & 0 deletions contrib/sirupsen/logrus/logrus.go
@@ -0,0 +1,32 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2022 Datadog, Inc.

// Package logrus provides a log/span correlation hook for the sirupsen/logrus package (https://github.com/sirupsen/logrus).
package logrus

import (
"github.com/sirupsen/logrus"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

// DDContextLogHook logs any span in the log context by implementing the logrus.Hook interface
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
type DDContextLogHook struct{}

// Levels implements logrus.Hook interface, this hook applies to all defined levels
func (d *DDContextLogHook) Levels() []logrus.Level {
return []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel, logrus.InfoLevel, logrus.DebugLevel, logrus.TraceLevel}
}

// Fire implements logrus.Hook interface, attaches trace and span details found in entry context
func (d *DDContextLogHook) Fire(e *logrus.Entry) error {
span, found := tracer.SpanFromContext(e.Context)
if !found {
return nil
}
e.Data["dd.trace_id"] = span.Context().TraceID()
e.Data["dd.span_id"] = span.Context().SpanID()
return nil
}
31 changes: 31 additions & 0 deletions contrib/sirupsen/logrus/logrus_test.go
@@ -0,0 +1,31 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2022 Datadog, Inc.

package logrus

import (
"context"
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"

"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
ajgajg1134 marked this conversation as resolved.
Show resolved Hide resolved
)

func TestFire(t *testing.T) {
tracer.Start()
defer tracer.Stop()
_, sctx := tracer.StartSpanFromContext(context.Background(), "testSpan", tracer.WithSpanID(1234))

hook := &DDContextLogHook{}
e := logrus.NewEntry(logrus.New())
e.Context = sctx
err := hook.Fire(e)

assert.NoError(t, err)
assert.Equal(t, uint64(1234), e.Data["dd.trace_id"])
assert.Equal(t, uint64(1234), e.Data["dd.span_id"])
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -74,7 +74,7 @@ require (
github.com/philhofer/fwd v1.1.1 // indirect
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
github.com/segmentio/kafka-go v0.4.29
github.com/stretchr/objx v0.2.0 // indirect
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.0
github.com/tidwall/btree v1.1.0 // indirect
Expand Down