Add telemetry
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user