add opentelemetry tracing
This commit is contained in:
@ -3,5 +3,4 @@ package config
|
||||
type HTTP struct {
|
||||
ListenAddr string `json:"listen_addr"`
|
||||
MountLive bool `json:"mount_live"`
|
||||
Engine string `json:"engine"`
|
||||
}
|
||||
|
||||
6
internal/common/config/trace.go
Normal file
6
internal/common/config/trace.go
Normal file
@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
type Trace struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
LicenseKey string `json:"license_key"`
|
||||
}
|
||||
@ -2,11 +2,24 @@ package decorator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.loyso.art/frx/kurious/internal/common/xcontext"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
commandAttribute = attribute.Key("command_name")
|
||||
queryAttribute = attribute.Key("query_name")
|
||||
argsAttribute = attribute.Key("args")
|
||||
|
||||
apiTracer = otel.Tracer("cq")
|
||||
)
|
||||
|
||||
type commandLoggingDecorator[T any] struct {
|
||||
@ -18,6 +31,17 @@ func (c commandLoggingDecorator[T]) Handle(ctx context.Context, cmd T) (err erro
|
||||
handlerName := getTypeName[T]()
|
||||
|
||||
ctx = xcontext.WithLogFields(ctx, slog.String("handler", handlerName))
|
||||
|
||||
var argsBuilder strings.Builder
|
||||
_ = json.NewEncoder(&argsBuilder).Encode(cmd)
|
||||
|
||||
var span trace.Span
|
||||
ctx, span = apiTracer.Start(ctx, handlerName)
|
||||
span.SetAttributes(
|
||||
commandAttribute.String(handlerName),
|
||||
argsAttribute.String(argsBuilder.String()),
|
||||
)
|
||||
|
||||
xcontext.LogDebug(ctx, c.log, "executing command")
|
||||
start := time.Now()
|
||||
|
||||
@ -27,7 +51,9 @@ func (c commandLoggingDecorator[T]) Handle(ctx context.Context, cmd T) (err erro
|
||||
xcontext.LogInfo(ctx, c.log, "command executed successfuly", elapsed)
|
||||
} else {
|
||||
xcontext.LogError(ctx, c.log, "command execution failed", elapsed, slog.Any("err", err))
|
||||
span.RecordError(err)
|
||||
}
|
||||
span.End()
|
||||
}()
|
||||
|
||||
return c.base.Handle(ctx, cmd)
|
||||
@ -41,6 +67,17 @@ type queryLoggingDecorator[Q, U any] struct {
|
||||
func (q queryLoggingDecorator[Q, U]) Handle(ctx context.Context, query Q) (entity U, err error) {
|
||||
handlerName := getTypeName[Q]()
|
||||
ctx = xcontext.WithLogFields(ctx, slog.String("handler", handlerName))
|
||||
|
||||
var argsBuilder strings.Builder
|
||||
_ = json.NewEncoder(&argsBuilder).Encode(query)
|
||||
|
||||
var span trace.Span
|
||||
ctx, span = apiTracer.Start(ctx, handlerName)
|
||||
span.SetAttributes(
|
||||
queryAttribute.String(handlerName),
|
||||
argsAttribute.String(argsBuilder.String()),
|
||||
)
|
||||
|
||||
xcontext.LogDebug(ctx, q.log, "executing command")
|
||||
start := time.Now()
|
||||
|
||||
@ -50,7 +87,10 @@ func (q queryLoggingDecorator[Q, U]) Handle(ctx context.Context, query Q) (entit
|
||||
xcontext.LogInfo(ctx, q.log, "command executed successfuly", elapsed)
|
||||
} else {
|
||||
xcontext.LogError(ctx, q.log, "command execution failed", elapsed, slog.Any("err", err))
|
||||
span.RecordError(err)
|
||||
}
|
||||
now := time.Now()
|
||||
span.End(trace.WithTimestamp(now))
|
||||
}()
|
||||
|
||||
return q.base.Handle(ctx, query)
|
||||
|
||||
@ -6,6 +6,16 @@ import (
|
||||
)
|
||||
|
||||
type ctxLogKey struct{}
|
||||
type ctxRequestID struct{}
|
||||
|
||||
func WithRequestID(ctx context.Context, requestID string) context.Context {
|
||||
return context.WithValue(ctx, ctxRequestID{}, requestID)
|
||||
}
|
||||
|
||||
func GetRequestID(ctx context.Context) string {
|
||||
reqid, _ := ctx.Value(ctxRequestID{}).(string)
|
||||
return reqid
|
||||
}
|
||||
|
||||
type ctxLogAttrStore struct {
|
||||
attrs []slog.Attr
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
package xslices
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func ForEach[T any](items []T, f func(T)) {
|
||||
for _, item := range items {
|
||||
f(item)
|
||||
@ -13,3 +18,12 @@ func AsMap[T any, U comparable](items []T, f func(T) U) map[U]struct{} {
|
||||
})
|
||||
return out
|
||||
}
|
||||
|
||||
func Shuffle[T any](items []T) {
|
||||
maxnum := big.NewInt(int64(len(items)))
|
||||
for i := range items {
|
||||
swapWith, _ := rand.Int(rand.Reader, maxnum)
|
||||
swapWithIdx := int(swapWith.Int64())
|
||||
items[i], items[swapWithIdx] = items[swapWithIdx], items[i]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user