Skip to content

otel: add options to configure log level and span error status (WithLevel, WithErrorStatusLevel) - #25

Open
thaJeztah wants to merge 2 commits into
containerd:mainfrom
thaJeztah:integrate_tracing_improve
Open

otel: add options to configure log level and span error status (WithLevel, WithErrorStatusLevel)#25
thaJeztah wants to merge 2 commits into
containerd:mainfrom
thaJeztah:integrate_tracing_improve

Conversation

@thaJeztah

@thaJeztah thaJeztah commented Aug 23, 2026

Copy link
Copy Markdown
Member

otel: add options to configure log level and span error status

These options make the containerd hook flexible enough to replace otellogrus (https://pkg.go.dev/github.com/uptrace/opentelemetry-go-extra/otellogrus) for consumers that currently use it for Logrus/OpenTelemetry integration combined with containerd/log. Callers can preserve their existing log-level filtering and span error-status behavior without needing a second tracing hook implementation.

otel: add option to configure log level

Add WithLevel to configure the minimum log level handled by the
OpenTelemetry hook.

This allows callers to limit which log entries are recorded as span
events, reducing trace noise and overhead when lower-severity logs are
not useful for tracing.

By default, the hook continues to handle all log levels, preserving
the existing behavior.

otel: add option to set span error status

Add WithErrorStatusLevel to configure the minimum log level that marks
an active span with an error status.

This allows callers to reflect sufficiently severe log entries in the
span status while keeping the behavior independent from attached error
fields.

By default, log entries continue to leave the span status unchanged.

@thaJeztah
thaJeztah force-pushed the integrate_tracing_improve branch 4 times, most recently from 0ae6429 to 15f4ac3 Compare August 23, 2026 15:49
@thaJeztah
thaJeztah force-pushed the integrate_tracing_improve branch 2 times, most recently from 042c0c7 to 07d754d Compare August 27, 2026 22:31
@thaJeztah
thaJeztah marked this pull request as ready for review August 27, 2026 22:31
@thaJeztah
thaJeztah requested a lite review from Copilot August 27, 2026 22:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds configurability to the otel logrus hook so consumers can (1) filter which log levels become span events and (2) optionally mark spans as error based on log severity, aligning behavior with common logrus/OpenTelemetry integration expectations.

Changes:

  • Add WithLevel(log.Level) to restrict which log levels the hook handles.
  • Add WithErrorStatusLevel(log.Level) to set span status to codes.Error for sufficiently severe log entries.
  • Add tests covering default vs configured hook levels and span error-status behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
otel/log.go Adds hook options for level filtering and error-status behavior, and updates Levels()/Fire() accordingly
otel/log_test.go Adds unit tests for WithLevel and WithErrorStatusLevel using a minimal test span
Suppressed comments (1)

otel/log.go:98

  • Levels() returns internal slices (either h.levels or the package-level allLevels) directly. Since slices are mutable, callers can accidentally modify the hook's configuration (and currently, modify allLevels globally). Return a defensive copy instead.
	if h.levels == nil {
		return allLevels
	}
	return h.levels
}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread otel/log.go
Comment on lines +64 to +69
for i, l := range allLevels {
if l == level {
h.levels = allLevels[:i+1]
return
}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, this could be a h.levels = slices.Clone(allLevels[:i+1]), but even that won't prevent Hook.Levels() from returning the slice and it being mutable unless every hook "fire" would return a clone.

This is a wider pattern than just this one; Logrus itself has an even worse case, where AllLevels is an exported var; https://github.com/sirupsen/logrus/blob/6d6a132bc03324d4ceb78e1b927f995d014cda20/logrus.go#L87-L95

// AllLevels exposing all logging levels.
var AllLevels = []Level{
	PanicLevel,
	FatalLevel,
	ErrorLevel,
	WarnLevel,
	InfoLevel,
	DebugLevel,
	TraceLevel,
}

Which usually is included directly in hooks;
https://github.com/sirupsen/logrus/blob/6d6a132bc03324d4ceb78e1b927f995d014cda20/hooks/syslog/syslog.go#L60-L62

unc (hook *SyslogHook) Levels() []logrus.Level {
	return logrus.AllLevels
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a slices.Clone

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread otel/log.go
@thaJeztah
thaJeztah force-pushed the integrate_tracing_improve branch 2 times, most recently from 39586c7 to 9feadfd Compare August 27, 2026 23:05
@thaJeztah
thaJeztah requested a lite review from Copilot August 27, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread otel/log.go
Comment on lines 97 to 100
// Levels returns the logrus levels that this hook is interested in.
func (h *LogrusHook) Levels() []log.Level {
return allLevels
return h.levels
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alright, alright, I'll add it back, but 😠 don't come back to comment "you should not return allLevels without cloning!

Add WithLevel to configure the minimum log level handled by the
OpenTelemetry hook.

This allows callers to limit which log entries are recorded as span
events, reducing trace noise and overhead when lower-severity logs are
not useful for tracing.

By default, the hook continues to handle all log levels, preserving
the existing behavior.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Add WithErrorStatusLevel to configure the minimum log level that marks
an active span with an error status.

This allows callers to reflect sufficiently severe log entries in the
span status while keeping the behavior independent from attached error
fields.

By default, log entries continue to leave the span status unchanged.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread otel/log_test.go

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
span := &testSpan{}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, you're in nit-picking mode now, right?

It's a test, CoPilot; the test panicking in that case is a feature - it means that a refactor reveals non-implemented things; which is better than silently swallowing by some stub.

@thaJeztah

Copy link
Copy Markdown
Member Author

@mxpv @dmcgowan this one should also be ready for review (I'm giving up on CoPilot; it's in nit-picking mode now)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants