diff --git a/go.mod b/go.mod index 7cb4bc4..c2725b5 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( ) require ( + github.com/XSAM/otelsql v0.32.0 // indirect github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect diff --git a/go.sum b/go.sum index 1b42994..c92d61b 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/XSAM/otelsql v0.32.0 h1:vDRE4nole0iOOlTaC/Bn6ti7VowzgxK39n3Ll1Kt7i0= +github.com/XSAM/otelsql v0.32.0/go.mod h1:Ary0hlyVBbaSwo8atZB8Aoothg9s/LBJj/N/p5qDmLM= github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf h1:+edM69bH/X6JpYPmJYBRLanAMe1V5yRXYU3hHUovGcE= github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf/go.mod h1:FZqLhJSj2tg0ZN48GB1zvj00+ZYcHPqgsC7yzcgCq6k= github.com/aarondl/opt v0.0.0-20240623220848-083f18ab9536 h1:vhpjulzH5Tr4S3uJ3Y/9pNL481kPq5ERj13ceAW0/uE= diff --git a/go/cmd/bluemage/serve/serve.go b/go/cmd/bluemage/serve/serve.go index 726a3d7..93997e6 100644 --- a/go/cmd/bluemage/serve/serve.go +++ b/go/cmd/bluemage/serve/serve.go @@ -2,7 +2,6 @@ package serve import ( "context" - "database/sql" "errors" "fmt" "log/slog" @@ -15,6 +14,7 @@ import ( "connectrpc.com/connect" "connectrpc.com/otelconnect" "connectrpc.com/validate" + "github.com/XSAM/otelsql" sqldblogger "github.com/simukti/sqldb-logger" "github.com/spf13/cobra" "github.com/stephenafamo/bob" @@ -25,6 +25,7 @@ import ( "github.com/tigorlazuardi/bluemage/go/pkg/log" "github.com/tigorlazuardi/bluemage/go/pkg/telemetry" "github.com/tigorlazuardi/bluemage/go/server" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -66,7 +67,7 @@ var Cmd = &cobra.Command{ } dsn := fmt.Sprintf("file:%s", cfg.String("db.path")) - sqldb, err := sql.Open(cfg.String("db.driver"), dsn) + sqldb, err := otelsql.Open(cfg.String("db.driver"), dsn, otelsql.WithAttributes(semconv.DBSystemSqlite)) if err != nil { return errs.Wrapw(err, "failed to open database", "driver", cfg.String("db.driver"), @@ -74,6 +75,13 @@ var Cmd = &cobra.Command{ ) } cleanups = append(cleanups, sqldb.Close) + if err := otelsql.RegisterDBStatsMetrics(sqldb, otelsql.WithAttributes(semconv.DBSystemSqlite)); err != nil { + return errs.Wrapw( + err, "failed to register database stats metrics", + "driver", cfg.String("db.driver"), + "dsn", dsn, + ) + } sqldb = sqldblogger.OpenDriver( dsn, diff --git a/go/pkg/errs/errs.go b/go/pkg/errs/errs.go index 4e38626..76d3cba 100644 --- a/go/pkg/errs/errs.go +++ b/go/pkg/errs/errs.go @@ -43,6 +43,28 @@ func (er *Err) Unwrap() error { return er.origin } +type originErr struct { + err error +} + +func (or originErr) LogValue() slog.Value { + if or.err == nil { + return slog.AnyValue(or.err) + } + if lv, ok := or.err.(slog.LogValuer); ok { + return lv.LogValue() + } + t := reflect.TypeOf(or.err).String() + if t == "*errors.errorString" { + return slog.StringValue(or.err.Error()) + } + return slog.GroupValue( + slog.String("type", t), + slog.String("message", or.err.Error()), + slog.Any("data", or.err), + ) +} + // LogValue implements slog.LogValuer. func (er *Err) LogValue() slog.Value { values := make([]slog.Attr, 0, 5) @@ -58,17 +80,7 @@ func (er *Err) LogValue() slog.Value { if len(er.details) > 0 { values = append(values, slog.Group("details", er.details...)) } - if er.origin == nil { - values = append(values, slog.Any("error", er.origin)) - } else if lv, ok := er.origin.(slog.LogValuer); ok { - values = append(values, slog.Attr{Key: "error", Value: lv.LogValue()}) - } else { - values = append(values, slog.Attr{Key: "error", Value: slog.GroupValue( - slog.String("type", reflect.TypeOf(er.origin).String()), - slog.String("message", er.origin.Error()), - slog.Any("data", er.origin), - )}) - } + values = append(values, slog.Attr{Key: "error", Value: (originErr{er.origin}).LogValue()}) return slog.GroupValue(values...) }