82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package telemetry
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
otellog "go.opentelemetry.io/otel/log"
|
|
sdklog "go.opentelemetry.io/otel/sdk/log"
|
|
)
|
|
|
|
// LogBridge implements io.Writer and forwards zerolog JSON lines to the
|
|
// OTel LoggerProvider. It is used as an extra writer in zerolog's MultiWriter
|
|
// so that logs go to both file and OTLP.
|
|
type LogBridge struct {
|
|
provider *sdklog.LoggerProvider
|
|
}
|
|
|
|
func (b *LogBridge) Write(p []byte) (n int, err error) {
|
|
var entry map[string]interface{}
|
|
if err := json.Unmarshal(p, &entry); err != nil {
|
|
return len(p), nil // skip malformed lines
|
|
}
|
|
|
|
logger := b.provider.Logger("zerolog")
|
|
|
|
var rec otellog.Record
|
|
rec.SetTimestamp(time.Now())
|
|
|
|
if msg, ok := entry["message"].(string); ok {
|
|
rec.SetBody(otellog.StringValue(msg))
|
|
}
|
|
|
|
if lvl, ok := entry["level"].(string); ok {
|
|
rec.SetSeverity(mapSeverity(lvl))
|
|
}
|
|
|
|
// Forward all fields as attributes
|
|
attrs := make([]otellog.KeyValue, 0, len(entry))
|
|
for k, v := range entry {
|
|
if k == "message" || k == "level" || k == "time" {
|
|
continue
|
|
}
|
|
switch val := v.(type) {
|
|
case string:
|
|
attrs = append(attrs, otellog.String(k, val))
|
|
case float64:
|
|
attrs = append(attrs, otellog.Float64(k, val))
|
|
case bool:
|
|
attrs = append(attrs, otellog.Bool(k, val))
|
|
default:
|
|
b, _ := json.Marshal(val)
|
|
attrs = append(attrs, otellog.String(k, string(b)))
|
|
}
|
|
}
|
|
rec.AddAttributes(attrs...)
|
|
|
|
logger.Emit(context.Background(), rec)
|
|
return len(p), nil
|
|
}
|
|
|
|
func mapSeverity(level string) otellog.Severity {
|
|
switch level {
|
|
case "trace":
|
|
return otellog.SeverityTrace
|
|
case "debug":
|
|
return otellog.SeverityDebug
|
|
case "info":
|
|
return otellog.SeverityInfo
|
|
case "warn", "warning":
|
|
return otellog.SeverityWarn
|
|
case "error":
|
|
return otellog.SeverityError
|
|
case "fatal":
|
|
return otellog.SeverityFatal
|
|
case "panic":
|
|
return otellog.SeverityFatal2
|
|
default:
|
|
return otellog.SeverityInfo
|
|
}
|
|
}
|