mirror of
https://github.com/fleetdm/fleet
synced 2026-05-10 10:40:46 +00:00
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #38607 Contributor docs update: https://github.com/fleetdm/fleet/pull/39285/changes Another contributor docs update: https://github.com/fleetdm/fleet/pull/39402/changes Also: - renamed OtelHandler to OtelTracingHandler - made "opentelemetry" be the default when tracing is enabled - updated OTEL dependencies # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## New Fleet configuration settings - [x] Setting(s) is/are explicitly excluded from GitOps <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added OpenTelemetry log export capability, enabling logs to be sent to OpenTelemetry collectors. * New configuration option `logging.otel_logs_enabled` (requires tracing to be enabled). * **Chores** * Updated OpenTelemetry dependencies to v1.40.0 with latest OTLP exporters and logging support. * Updated dependencies including gRPC (v1.78.0), Google libraries, and cryptography packages. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
61 lines
1.7 KiB
Go
61 lines
1.7 KiB
Go
package logging
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"log/slog"
|
|
)
|
|
|
|
// MultiHandler sends log records to multiple handlers.
|
|
type MultiHandler struct {
|
|
handlers []slog.Handler
|
|
}
|
|
|
|
func NewMultiHandler(handlers ...slog.Handler) *MultiHandler {
|
|
return &MultiHandler{handlers: handlers}
|
|
}
|
|
|
|
// Enabled reports whether any handler handles records at the given level.
|
|
func (h *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
|
for _, handler := range h.handlers {
|
|
if handler.Enabled(ctx, level) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Handle sends the record to all enabled handlers.
|
|
// It continues processing all handlers even if one fails, and returns
|
|
// a combined error of all failures using errors.Join.
|
|
func (h *MultiHandler) Handle(ctx context.Context, r slog.Record) error {
|
|
var errs []error
|
|
for _, handler := range h.handlers {
|
|
if handler.Enabled(ctx, r.Level) {
|
|
if err := handler.Handle(ctx, r.Clone()); err != nil {
|
|
errs = append(errs, err)
|
|
}
|
|
}
|
|
}
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
// WithAttrs returns a new MultiHandler with the given attributes added to all handlers.
|
|
func (h *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|
handlers := make([]slog.Handler, len(h.handlers))
|
|
for i, handler := range h.handlers {
|
|
handlers[i] = handler.WithAttrs(attrs)
|
|
}
|
|
return &MultiHandler{handlers: handlers}
|
|
}
|
|
|
|
// WithGroup returns a new MultiHandler with the given group name applied to all handlers.
|
|
func (h *MultiHandler) WithGroup(name string) slog.Handler {
|
|
handlers := make([]slog.Handler, len(h.handlers))
|
|
for i, handler := range h.handlers {
|
|
handlers[i] = handler.WithGroup(name)
|
|
}
|
|
return &MultiHandler{handlers: handlers}
|
|
}
|
|
|
|
var _ slog.Handler = (*MultiHandler)(nil)
|