-
Notifications
You must be signed in to change notification settings - Fork 435
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
ddtrace/tracer: runtime metrics v2 (exclude from release notes) #2772
base: main
Are you sure you want to change the base?
Changes from 4 commits
a7e5c8d
0f5b5f6
fdd5e08
1276984
b070f10
2b9ebd0
160885f
17d94f1
535a60a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package tracer | ||
|
||
import ( | ||
"context" | ||
"log/slog" | ||
"strings" | ||
|
||
"gopkg.in/DataDog/dd-trace-go.v1/internal/log" | ||
) | ||
|
||
// slogHandler implements the slog.Handler interface to dispatch messages to our | ||
// internal logger. | ||
type slogHandler struct { | ||
attrs []string | ||
groups []string | ||
} | ||
|
||
func (h slogHandler) Enabled(ctx context.Context, lvl slog.Level) bool { | ||
if lvl <= slog.LevelDebug { | ||
return log.DebugEnabled() | ||
} | ||
// TODO(fg): Implement generic log level checking in the internal logger. | ||
// But we're we're not concerned with slog perf, so this is okay for now. | ||
return true | ||
} | ||
|
||
func (h slogHandler) Handle(ctx context.Context, r slog.Record) error { | ||
parts := make([]string, 0, 1+len(h.attrs)+r.NumAttrs()) | ||
parts = append(parts, r.Message) | ||
parts = append(parts, h.attrs...) | ||
r.Attrs(func(a slog.Attr) bool { | ||
parts = append(parts, formatAttr(a, h.groups)) | ||
return true | ||
}) | ||
|
||
msg := strings.Join(parts, " ") | ||
switch r.Level { | ||
case slog.LevelDebug: | ||
log.Debug(msg) | ||
case slog.LevelInfo: | ||
log.Info(msg) | ||
case slog.LevelWarn: | ||
log.Warn(msg) | ||
case slog.LevelError: | ||
log.Error(msg) | ||
} | ||
return nil | ||
} | ||
|
||
func (h slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { | ||
for _, a := range attrs { | ||
h.attrs = append(h.attrs, formatAttr(a, h.groups)) | ||
} | ||
return h | ||
} | ||
|
||
func (h slogHandler) WithGroup(name string) slog.Handler { | ||
h.groups = append(h.groups, name) | ||
return h | ||
} | ||
|
||
func formatAttr(a slog.Attr, groups []string) string { | ||
return strings.Join(append(groups, a.String()), ".") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package tracer | ||
|
||
import ( | ||
"log/slog" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"gopkg.in/DataDog/dd-trace-go.v1/internal/log" | ||
) | ||
|
||
func Test_slogHandler(t *testing.T) { | ||
// Create a record logger to capture the logs and restore the original | ||
// logger at the end. | ||
rl := &log.RecordLogger{} | ||
defer log.UseLogger(rl)() | ||
|
||
// Log a few messages at different levels. The debug message gets discarded | ||
// because the internal logger does not have debug enabled by default. | ||
l := slog.New(slogHandler{}) | ||
l = l.With("foo", "bar") | ||
l = l.WithGroup("a").WithGroup("b") | ||
l.Debug("debug test", "n", 0) | ||
l.Info("info test", "n", 1) | ||
l.Warn("warn test", "n", 2) | ||
l.Error("error test", "n", 3) | ||
log.Flush() // needed to get the error log flushed | ||
|
||
// Check that the logs were written correctly. | ||
require.Len(t, rl.Logs(), 3) | ||
require.Contains(t, rl.Logs()[0], "info test foo=bar a.b.n=1") | ||
require.Contains(t, rl.Logs()[1], "warn test foo=bar a.b.n=2") | ||
require.Contains(t, rl.Logs()[2], "error test foo=bar a.b.n=3") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,10 @@ func (tg *TestStatsdClient) Gauge(name string, value float64, tags []string, rat | |
}) | ||
} | ||
|
||
func (tg *TestStatsdClient) GaugeWithTimestamp(name string, value float64, tags []string, rate float64, timestamp time.Time) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
panic("not implemented yet") | ||
} | ||
|
||
func (tg *TestStatsdClient) Incr(name string, tags []string, rate float64) error { | ||
tg.addCount(name, 1) | ||
return tg.addMetric(callTypeIncr, tags, TestStatsdCall{ | ||
|
@@ -81,6 +85,10 @@ func (tg *TestStatsdClient) Count(name string, value int64, tags []string, rate | |
}) | ||
} | ||
|
||
func (tg *TestStatsdClient) CountWithTimestamp(name string, value int64, tags []string, rate float64, timestamp time.Time) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
panic("not implemented yet") | ||
} | ||
|
||
func (tg *TestStatsdClient) Timing(name string, value time.Duration, tags []string, rate float64) error { | ||
return tg.addMetric(callTypeTiming, tags, TestStatsdCall{ | ||
name: name, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: I think we also have a startup logging thing somewhere that tries to log all the config values. check if we need to log runtimeMetricsV2 there as well.