feat(instrumentation): adopt slog (#6907)

### Summary

feat(instrumentation): adopt slog
This commit is contained in:
Vibhu Pandey 2025-01-24 14:53:02 +05:30 committed by GitHub
parent b544a54c40
commit 001122db2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 329 additions and 138 deletions

View File

@ -6,14 +6,10 @@
##################### Instrumentation #####################
instrumentation:
logs:
# The log level to use.
level: info
enabled: false
processors:
batch:
exporter:
otlp:
endpoint: localhost:4317
traces:
# Whether to enable tracing.
enabled: false
processors:
batch:
@ -21,6 +17,7 @@ instrumentation:
otlp:
endpoint: localhost:4317
metrics:
# Whether to enable metrics.
enabled: true
readers:
pull:

20
go.mod
View File

@ -39,29 +39,28 @@ require (
github.com/opentracing/opentracing-go v1.2.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.20.4
github.com/prometheus/common v0.60.0
github.com/prometheus/prometheus v2.5.0+incompatible
github.com/rs/cors v1.11.1
github.com/russellhaering/gosaml2 v0.9.0
github.com/russellhaering/goxmldsig v1.2.0
github.com/samber/lo v1.38.1
github.com/samber/lo v1.47.0
github.com/sethvargo/go-password v0.2.0
github.com/smartystreets/goconvey v1.8.1
github.com/soheilhy/cmux v0.1.5
github.com/srikanthccv/ClickHouse-go-mock v0.9.0
github.com/stretchr/testify v1.9.0
github.com/stretchr/testify v1.10.0
github.com/uptrace/bun v1.2.8
github.com/uptrace/bun/dialect/sqlitedialect v1.2.8
go.opentelemetry.io/collector/confmap v1.17.0
go.opentelemetry.io/collector/pdata v1.17.0
go.opentelemetry.io/collector/processor v0.111.0
go.opentelemetry.io/contrib/bridges/otelzap v0.0.0-20240820072021-3fab5f5f20fb
go.opentelemetry.io/contrib/config v0.10.0
go.opentelemetry.io/otel v1.30.0
go.opentelemetry.io/otel/log v0.6.0
go.opentelemetry.io/otel/metric v1.30.0
go.opentelemetry.io/otel/sdk v1.30.0
go.opentelemetry.io/otel/trace v1.30.0
go.opentelemetry.io/otel v1.34.0
go.opentelemetry.io/otel/metric v1.34.0
go.opentelemetry.io/otel/sdk v1.34.0
go.opentelemetry.io/otel/trace v1.34.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.31.0
@ -151,7 +150,6 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
github.com/prometheus/client_golang v1.20.4 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
@ -175,6 +173,7 @@ require (
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/collector v0.111.0 // indirect
go.opentelemetry.io/collector/component v0.111.0 // indirect
go.opentelemetry.io/collector/component/componentprofiles v0.111.0 // indirect
@ -216,7 +215,8 @@ require (
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.6.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0 // indirect
go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect
go.opentelemetry.io/otel/log v0.10.0 // indirect
go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.30.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/atomic v1.11.0 // indirect

39
go.sum
View File

@ -673,8 +673,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4PfRmVOIk=
@ -685,8 +685,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@ -737,8 +737,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
@ -788,6 +789,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/collector v0.111.0 h1:D3LJTYrrK2ac94E2PXPSbVkArqxbklbCLsE4MAJQdRo=
go.opentelemetry.io/collector v0.111.0/go.mod h1:eZi4Z1DmHy+sVqbUI8dZNvhrH7HZIlX+0AKorOtv6nE=
go.opentelemetry.io/collector/client v1.17.0 h1:eJB4r4nPY0WrQ6IQEEbOPCOfQU7N15yzZud9y5fKfms=
@ -872,8 +875,6 @@ go.opentelemetry.io/collector/semconv v0.111.0 h1:ELleMtLBzeZ3xhfhYPmFcLc0hJMqRx
go.opentelemetry.io/collector/semconv v0.111.0/go.mod h1:zCJ5njhWpejR+A40kiEoeFm1xq1uzyZwMnRNX6/D82A=
go.opentelemetry.io/collector/service v0.111.0 h1:6yGjjbZvlYbir+vzi/9ACF965m8i96ScPTjpVvki3ms=
go.opentelemetry.io/collector/service v0.111.0/go.mod h1:tti8TAosPuRj51/bbrSvf6OIJoSyTkywEvTdY/fAuwY=
go.opentelemetry.io/contrib/bridges/otelzap v0.0.0-20240820072021-3fab5f5f20fb h1:ZqncifxU0B1q64FRbhKxsJugRsrEToakmYUsgQ5tGbY=
go.opentelemetry.io/contrib/bridges/otelzap v0.0.0-20240820072021-3fab5f5f20fb/go.mod h1:mzv0k5dTnSUE5/ZerXUwGiNKzcPJTakuCh6Wm1emNvU=
go.opentelemetry.io/contrib/config v0.10.0 h1:2JknAzMaYjxrHkTnZh3eOme/Y2P5eHE2SWfhfV6Xd6c=
go.opentelemetry.io/contrib/config v0.10.0/go.mod h1:aND2M6/KfNkntI5cyvHriR/zvZgPf8j9yETdSmvpfmc=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
@ -882,8 +883,8 @@ go.opentelemetry.io/contrib/propagators/b3 v1.30.0 h1:vumy4r1KMyaoQRltX7cJ37p3nl
go.opentelemetry.io/contrib/propagators/b3 v1.30.0/go.mod h1:fRbvRsaeVZ82LIl3u0rIvusIel2UUf+JcaaIpy5taho=
go.opentelemetry.io/contrib/zpages v0.55.0 h1:F+xj261Ulwl79QC+2O+IO1b3NbwppUDwN+7LbDSdQcY=
go.opentelemetry.io/contrib/zpages v0.55.0/go.mod h1:dDqDGDfbXSjt/k9orZk4Huulvz1letX1YWTKts5GQpo=
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 h1:QSKmLBzbFULSyHzOdO9JsN9lpE4zkrz1byYGmJecdVE=
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0/go.mod h1:sTQ/NH8Yrirf0sJ5rWqVu+oT82i4zL9FaF6rWcqnptM=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.30.0 h1:WypxHH02KX2poqqbaadmkMYalGyy/vil4HE4PM4nRJc=
@ -904,18 +905,18 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0 h1:IyFlqNsi8VT/nw
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.30.0/go.mod h1:bxiX8eUeKoAEQmbq/ecUT8UqZwCjZW52yJrXJUSozsk=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0 h1:kn1BudCgwtE7PxLqcZkErpD8GKqLZ6BSzeW9QihQJeM=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.30.0/go.mod h1:ljkUDtAMdleoi9tIG1R6dJUpVwDcYjw3J2Q6Q/SuiC0=
go.opentelemetry.io/otel/log v0.6.0 h1:nH66tr+dmEgW5y+F9LanGJUBYPrRgP4g2EkmPE3LeK8=
go.opentelemetry.io/otel/log v0.6.0/go.mod h1:KdySypjQHhP069JX0z/t26VHwa8vSwzgaKmXtIB3fJM=
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE=
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg=
go.opentelemetry.io/otel/sdk/log v0.6.0 h1:4J8BwXY4EeDE9Mowg+CyhWVBhTSLXVXodiXxS/+PGqI=
go.opentelemetry.io/otel/sdk/log v0.6.0/go.mod h1:L1DN8RMAduKkrwRAFDEX3E3TLOq46+XMGSbUfHU/+vE=
go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0=
go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw=
go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo=
go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM=
go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y=
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=

View File

@ -2,6 +2,7 @@ package errors
import (
"fmt"
"log/slog"
)
const (
@ -25,6 +26,16 @@ type base struct {
a []string
}
func (b *base) LogValue() slog.Value {
return slog.GroupValue(
slog.String("type", b.t.s),
slog.String("code", b.c),
slog.String("message", b.m),
slog.String("url", b.u),
slog.Any("additional", b.a),
)
}
// base implements Error interface.
func (b *base) Error() string {
if b.e != nil {

View File

@ -1,54 +1,51 @@
package factory
import (
sdklog "go.opentelemetry.io/otel/log"
"log/slog"
"github.com/prometheus/client_golang/prometheus"
sdkmetric "go.opentelemetry.io/otel/metric"
sdktrace "go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
)
type ProviderSettings struct {
// LoggerProvider is the otel logger.
LoggerProvider sdklog.LoggerProvider
// ZapLogger is the zap logger.
ZapLogger *zap.Logger
// SlogLogger is the slog logger.
Logger *slog.Logger
// MeterProvider is the meter provider.
MeterProvider sdkmetric.MeterProvider
// TracerProvider is the tracer provider.
TracerProvider sdktrace.TracerProvider
// PrometheusRegistry is the prometheus registry.
PrometheusRegisterer prometheus.Registerer
}
type ScopedProviderSettings interface {
Logger() sdklog.Logger
ZapLogger() *zap.Logger
Logger() *slog.Logger
Meter() sdkmetric.Meter
Tracer() sdktrace.Tracer
PrometheusRegisterer() prometheus.Registerer
}
type scoped struct {
logger sdklog.Logger
zapLogger *zap.Logger
logger *slog.Logger
meter sdkmetric.Meter
tracer sdktrace.Tracer
prometheusRegisterer prometheus.Registerer
}
func NewScopedProviderSettings(settings ProviderSettings, pkgName string) *scoped {
return &scoped{
logger: settings.LoggerProvider.Logger(pkgName),
zapLogger: settings.ZapLogger.Named(pkgName),
logger: settings.Logger.With("logger", pkgName),
meter: settings.MeterProvider.Meter(pkgName),
tracer: settings.TracerProvider.Tracer(pkgName),
prometheusRegisterer: settings.PrometheusRegisterer,
}
}
func (s *scoped) Logger() sdklog.Logger {
func (s *scoped) Logger() *slog.Logger {
return s.logger
}
func (s *scoped) ZapLogger() *zap.Logger {
return s.zapLogger
}
func (s *scoped) Meter() sdkmetric.Meter {
return s.meter
}
@ -56,3 +53,7 @@ func (s *scoped) Meter() sdkmetric.Meter {
func (s *scoped) Tracer() sdktrace.Tracer {
return s.tracer
}
func (s *scoped) PrometheusRegisterer() prometheus.Registerer {
return s.prometheusRegisterer
}

View File

@ -1,9 +1,10 @@
package instrumentation
import (
"log/slog"
contribsdkconfig "go.opentelemetry.io/contrib/config"
"go.signoz.io/signoz/pkg/factory"
"go.uber.org/zap/zapcore"
)
// Config holds the configuration for all instrumentation components.
@ -21,13 +22,7 @@ type Resource struct {
// LogsConfig holds the configuration for the logging component.
type LogsConfig struct {
Enabled bool `mapstructure:"enabled"`
Level zapcore.Level `mapstructure:"level"`
Processors LogsProcessors `mapstructure:"processors"`
}
type LogsProcessors struct {
Batch contribsdkconfig.BatchLogRecordProcessor `mapstructure:"batch"`
Level slog.Level `mapstructure:"level"`
}
// TracesConfig holds the configuration for the tracing component.
@ -61,8 +56,7 @@ func newConfig() factory.Config {
return Config{
Logs: LogsConfig{
Enabled: false,
Level: zapcore.DebugLevel,
Level: slog.LevelInfo,
},
Traces: TracesConfig{
Enabled: false,

View File

@ -0,0 +1,45 @@
package instrumentation
import (
"context"
"log/slog"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.signoz.io/signoz/pkg/config"
"go.signoz.io/signoz/pkg/config/envprovider"
"go.signoz.io/signoz/pkg/factory"
)
func TestNewWithEnvProvider(t *testing.T) {
t.Setenv("SIGNOZ_INSTRUMENTATION_LOGS_LEVEL", "debug")
t.Setenv("SIGNOZ_INSTRUMENTATION_METRICS_READERS_PULL_EXPORTER_PROMETHEUS_PORT", "1111")
t.Setenv("SIGNOZ_INSTRUMENTATION_TRACES_ENABLED", "true")
conf, err := config.New(
context.Background(),
config.ResolverConfig{
Uris: []string{"env:"},
ProviderFactories: []config.ProviderFactory{
envprovider.NewFactory(),
},
},
[]factory.ConfigFactory{
NewConfigFactory(),
},
)
require.NoError(t, err)
actual := Config{}
err = conf.Unmarshal("instrumentation", &actual)
require.NoError(t, err)
port := 1111
expected := NewConfigFactory().New().(Config)
expected.Logs.Level = slog.LevelDebug
expected.Traces.Enabled = true
expected.Metrics.Readers.Pull.Exporter.Prometheus.Port = &port
assert.Equal(t, expected, actual)
}

View File

@ -1,28 +1,25 @@
package instrumentation
import (
"os"
"log/slog"
"go.opentelemetry.io/contrib/bridges/otelzap"
sdklog "go.opentelemetry.io/otel/log"
"github.com/prometheus/client_golang/prometheus"
sdkmetric "go.opentelemetry.io/otel/metric"
sdkresource "go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/trace"
"go.signoz.io/signoz/pkg/factory"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Instrumentation provides the core components for application instrumentation.
type Instrumentation interface {
// LoggerProvider returns the OpenTelemetry logger provider.
LoggerProvider() sdklog.LoggerProvider
// Logger returns the Zap logger.
Logger() *zap.Logger
// Logger returns the Slog logger.
Logger() *slog.Logger
// MeterProvider returns the OpenTelemetry meter provider.
MeterProvider() sdkmetric.MeterProvider
// TracerProvider returns the OpenTelemetry tracer provider.
TracerProvider() sdktrace.TracerProvider
// PrometheusRegisterer returns the Prometheus registerer.
PrometheusRegisterer() prometheus.Registerer
// ToProviderSettings converts instrumentation to provider settings.
ToProviderSettings() factory.ProviderSettings
}
@ -42,14 +39,3 @@ func mergeAttributes(input map[string]any, resource *sdkresource.Resource) map[s
return output
}
// newLogger creates a new Zap logger with the configured level and output.
// It combines a JSON encoder for stdout and an OpenTelemetry bridge.
func newLogger(cfg Config, provider sdklog.LoggerProvider) *zap.Logger {
core := zapcore.NewTee(
zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(os.Stdout), cfg.Logs.Level),
otelzap.NewCore("go.signoz.io/pkg/instrumentation", otelzap.WithLoggerProvider(provider)),
)
return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
}

View File

@ -1,38 +1,33 @@
package instrumentationtest
import (
sdklog "go.opentelemetry.io/otel/log"
nooplog "go.opentelemetry.io/otel/log/noop"
"io"
"log/slog"
"github.com/prometheus/client_golang/prometheus"
sdkmetric "go.opentelemetry.io/otel/metric"
noopmetric "go.opentelemetry.io/otel/metric/noop"
sdktrace "go.opentelemetry.io/otel/trace"
nooptrace "go.opentelemetry.io/otel/trace/noop"
"go.signoz.io/signoz/pkg/factory"
"go.signoz.io/signoz/pkg/instrumentation"
"go.uber.org/zap"
)
type noopInstrumentation struct {
logger *zap.Logger
loggerProvider sdklog.LoggerProvider
logger *slog.Logger
meterProvider sdkmetric.MeterProvider
tracerProvider sdktrace.TracerProvider
}
func New() instrumentation.Instrumentation {
return &noopInstrumentation{
logger: zap.NewNop(),
loggerProvider: nooplog.NewLoggerProvider(),
logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
meterProvider: noopmetric.NewMeterProvider(),
tracerProvider: nooptrace.NewTracerProvider(),
}
}
func (i *noopInstrumentation) LoggerProvider() sdklog.LoggerProvider {
return i.loggerProvider
}
func (i *noopInstrumentation) Logger() *zap.Logger {
func (i *noopInstrumentation) Logger() *slog.Logger {
return i.logger
}
@ -44,11 +39,15 @@ func (i *noopInstrumentation) TracerProvider() sdktrace.TracerProvider {
return i.tracerProvider
}
func (i *noopInstrumentation) PrometheusRegisterer() prometheus.Registerer {
return prometheus.NewRegistry()
}
func (i *noopInstrumentation) ToProviderSettings() factory.ProviderSettings {
return factory.ProviderSettings{
LoggerProvider: i.LoggerProvider(),
ZapLogger: i.Logger(),
Logger: i.Logger(),
MeterProvider: i.MeterProvider(),
TracerProvider: i.TracerProvider(),
PrometheusRegisterer: i.PrometheusRegisterer(),
}
}

View File

@ -0,0 +1,22 @@
package instrumentation
import (
"log/slog"
"os"
"go.signoz.io/signoz/pkg/instrumentation/loghandler"
)
func NewLogger(config Config, wrappers ...loghandler.Wrapper) *slog.Logger {
logger := slog.New(
loghandler.New(
slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: config.Logs.Level, AddSource: true}),
wrappers...,
),
)
slog.SetDefault(logger)
_ = slog.SetLogLoggerLevel(config.Logs.Level)
return logger
}

View File

@ -0,0 +1,44 @@
package loghandler
import (
"context"
"log/slog"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
type correlation struct{}
func NewCorrelation() *correlation {
return &correlation{}
}
func (h *correlation) Wrap(next LogHandler) LogHandler {
return LogHandlerFunc(func(ctx context.Context, record slog.Record) error {
span := trace.SpanFromContext(ctx)
if span == nil || !span.IsRecording() {
return next.Handle(ctx, record)
}
// Adding span info to log record.
spanContext := span.SpanContext()
if spanContext.HasTraceID() {
traceID := spanContext.TraceID().String()
record.AddAttrs(slog.String("trace_id", traceID))
}
if spanContext.HasSpanID() {
spanID := spanContext.SpanID().String()
record.AddAttrs(slog.String("span_id", spanID))
}
// Setting span status if the log is an error.
// Purposely leaving as codes.Unset (default) otherwise.
if record.Level >= slog.LevelError {
span.SetStatus(codes.Error, record.Message)
}
return next.Handle(ctx, record)
})
}

View File

@ -0,0 +1,33 @@
package loghandler
import (
"bytes"
"context"
"encoding/json"
"log/slog"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/sdk/trace"
)
func TestCorrelation(t *testing.T) {
correlation := NewCorrelation()
buf := bytes.NewBuffer(nil)
logger := slog.New(&handler{base: slog.NewJSONHandler(buf, &slog.HandlerOptions{Level: slog.LevelDebug}), wrappers: []Wrapper{correlation}})
tracer := trace.NewTracerProvider().Tracer("test")
ctx, span := tracer.Start(context.Background(), "test")
defer span.End()
logger.InfoContext(ctx, "test")
m := make(map[string]any)
err := json.Unmarshal(buf.Bytes(), &m)
require.NoError(t, err)
assert.Equal(t, span.SpanContext().TraceID().String(), m["trace_id"])
assert.Equal(t, span.SpanContext().SpanID().String(), m["span_id"])
}

View File

@ -0,0 +1,64 @@
package loghandler
import (
"context"
"log/slog"
)
// LogHandlerFunc is to LogHandler as http.HandlerFunc is to http.Handler
type LogHandlerFunc func(ctx context.Context, r slog.Record) error
// LogHandlerFunc implements LogHandler
func (m LogHandlerFunc) Handle(ctx context.Context, r slog.Record) error {
return m(ctx, r)
}
type LogHandler interface {
Handle(ctx context.Context, r slog.Record) error
}
// Wrapper is an interface implemented by all log handlers
type Wrapper interface {
Wrap(LogHandler) LogHandler
}
type WrapperFunc func(LogHandler) LogHandler
func (m WrapperFunc) Wrap(next LogHandler) LogHandler {
return m(next)
}
// Merge wraps the given wrappers into a single wrapper.
func MergeLogHandlerWrappers(handlers ...Wrapper) Wrapper {
return WrapperFunc(func(next LogHandler) LogHandler {
for i := len(handlers) - 1; i >= 0; i-- {
next = handlers[i].Wrap(next)
}
return next
})
}
type handler struct {
base slog.Handler
wrappers []Wrapper
}
func New(base slog.Handler, wrappers ...Wrapper) *handler {
return &handler{base: base, wrappers: wrappers}
}
func (h *handler) Enabled(ctx context.Context, level slog.Level) bool {
return h.base.Enabled(ctx, level)
}
func (h *handler) Handle(ctx context.Context, r slog.Record) error {
return MergeLogHandlerWrappers(h.wrappers...).Wrap(h.base).Handle(ctx, r)
}
func (h *handler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &handler{base: h.base.WithAttrs(attrs), wrappers: h.wrappers}
}
func (h *handler) WithGroup(name string) slog.Handler {
return &handler{base: h.base.WithGroup(name), wrappers: h.wrappers}
}

View File

@ -2,16 +2,17 @@ package instrumentation
import (
"context"
"log/slog"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
contribsdkconfig "go.opentelemetry.io/contrib/config"
sdklog "go.opentelemetry.io/otel/log"
sdkmetric "go.opentelemetry.io/otel/metric"
sdkresource "go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
sdktrace "go.opentelemetry.io/otel/trace"
"go.signoz.io/signoz/pkg/factory"
"go.signoz.io/signoz/pkg/version"
"go.uber.org/zap"
)
var _ factory.Service = (*SDK)(nil)
@ -19,8 +20,9 @@ var _ Instrumentation = (*SDK)(nil)
// SDK holds the core components for application instrumentation.
type SDK struct {
logger *slog.Logger
sdk contribsdkconfig.SDK
logger *zap.Logger
prometheusRegistry *prometheus.Registry
}
// New creates a new Instrumentation instance with configured providers.
@ -56,15 +58,6 @@ func New(ctx context.Context, build version.Build, cfg Config) (*SDK, error) {
SchemaUrl: &sch,
}
var loggerProvider *contribsdkconfig.LoggerProvider
if cfg.Logs.Enabled {
loggerProvider = &contribsdkconfig.LoggerProvider{
Processors: []contribsdkconfig.LogRecordProcessor{
{Batch: &cfg.Logs.Processors.Batch},
},
}
}
var tracerProvider *contribsdkconfig.TracerProvider
if cfg.Traces.Enabled {
tracerProvider = &contribsdkconfig.TracerProvider{
@ -87,7 +80,6 @@ func New(ctx context.Context, build version.Build, cfg Config) (*SDK, error) {
sdk, err := contribsdkconfig.NewSDK(
contribsdkconfig.WithContext(ctx),
contribsdkconfig.WithOpenTelemetryConfiguration(contribsdkconfig.OpenTelemetryConfiguration{
LoggerProvider: loggerProvider,
TracerProvider: tracerProvider,
MeterProvider: meterProvider,
Resource: &configResource,
@ -97,9 +89,13 @@ func New(ctx context.Context, build version.Build, cfg Config) (*SDK, error) {
return nil, err
}
prometheusRegistry := prometheus.NewRegistry()
prometheusRegistry.MustRegister(collectors.NewBuildInfoCollector())
return &SDK{
sdk: sdk,
logger: newLogger(cfg, sdk.LoggerProvider()),
prometheusRegistry: prometheusRegistry,
logger: NewLogger(cfg),
}, nil
}
@ -111,11 +107,7 @@ func (i *SDK) Stop(ctx context.Context) error {
return i.sdk.Shutdown(ctx)
}
func (i *SDK) LoggerProvider() sdklog.LoggerProvider {
return i.sdk.LoggerProvider()
}
func (i *SDK) Logger() *zap.Logger {
func (i *SDK) Logger() *slog.Logger {
return i.logger
}
@ -127,11 +119,15 @@ func (i *SDK) TracerProvider() sdktrace.TracerProvider {
return i.sdk.TracerProvider()
}
func (i *SDK) PrometheusRegisterer() prometheus.Registerer {
return i.prometheusRegistry
}
func (i *SDK) ToProviderSettings() factory.ProviderSettings {
return factory.ProviderSettings{
LoggerProvider: i.LoggerProvider(),
ZapLogger: i.Logger(),
Logger: i.Logger(),
MeterProvider: i.MeterProvider(),
TracerProvider: i.TracerProvider(),
PrometheusRegisterer: i.PrometheusRegisterer(),
}
}

View File

@ -8,7 +8,6 @@ import (
"github.com/uptrace/bun/migrate"
"go.signoz.io/signoz/pkg/factory"
"go.signoz.io/signoz/pkg/sqlstore"
"go.uber.org/zap"
)
var (
@ -33,7 +32,7 @@ func New(ctx context.Context, providerSettings factory.ProviderSettings, sqlstor
}
func (migrator *migrator) Migrate(ctx context.Context) error {
migrator.settings.ZapLogger().Info("starting sqlstore migrations", zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "starting sqlstore migrations", "dialect", migrator.dialect)
if err := migrator.migrator.Init(ctx); err != nil {
return err
}
@ -50,11 +49,11 @@ func (migrator *migrator) Migrate(ctx context.Context) error {
}
if group.IsZero() {
migrator.settings.ZapLogger().Info("no new migrations to run (database is up to date)", zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "no new migrations to run (database is up to date)", "dialect", migrator.dialect)
return nil
}
migrator.settings.ZapLogger().Info("migrated to", zap.String("group", group.String()), zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "migrated to", "group", group.String(), "dialect", migrator.dialect)
return nil
}
@ -70,17 +69,17 @@ func (migrator *migrator) Rollback(ctx context.Context) error {
}
if group.IsZero() {
migrator.settings.ZapLogger().Info("no groups to roll back", zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "no groups to roll back", "dialect", migrator.dialect)
return nil
}
migrator.settings.ZapLogger().Info("rolled back", zap.String("group", group.String()), zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "rolled back", "group", group.String(), "dialect", migrator.dialect)
return nil
}
func (migrator *migrator) Lock(ctx context.Context) error {
if err := migrator.migrator.Lock(ctx); err == nil {
migrator.settings.ZapLogger().Info("acquired migration lock", zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "acquired migration lock", "dialect", migrator.dialect)
return nil
}
@ -94,11 +93,11 @@ func (migrator *migrator) Lock(ctx context.Context) error {
select {
case <-timer.C:
err := errors.New("timed out waiting for lock")
migrator.settings.ZapLogger().Error("cannot acquire lock", zap.Error(err), zap.Duration("lock_timeout", migrator.config.Lock.Timeout), zap.String("dialect", migrator.dialect))
migrator.settings.Logger().ErrorContext(ctx, "cannot acquire lock", "error", err, "lock_timeout", migrator.config.Lock.Timeout, "dialect", migrator.dialect)
return err
case <-ticker.C:
if err := migrator.migrator.Lock(ctx); err == nil {
migrator.settings.ZapLogger().Info("acquired migration lock", zap.String("dialect", migrator.dialect))
migrator.settings.Logger().InfoContext(ctx, "acquired migration lock", "dialect", migrator.dialect)
return nil
}
case <-ctx.Done():

View File

@ -10,7 +10,6 @@ import (
"github.com/uptrace/bun/dialect/sqlitedialect"
"go.signoz.io/signoz/pkg/factory"
"go.signoz.io/signoz/pkg/sqlstore"
"go.uber.org/zap"
)
type provider struct {
@ -31,7 +30,7 @@ func New(ctx context.Context, providerSettings factory.ProviderSettings, config
if err != nil {
return nil, err
}
settings.ZapLogger().Info("connected to sqlite", zap.String("path", config.Sqlite.Path))
settings.Logger().InfoContext(ctx, "connected to sqlite", "path", config.Sqlite.Path)
sqldb.SetMaxOpenConns(config.Connection.MaxOpenConns)
return &provider{