fix bug when no child tracer created

This commit is contained in:
Sergey Chubaryan 2024-09-02 21:24:57 +03:00
parent 2c1abf5a7f
commit ea967a5608
7 changed files with 86 additions and 24 deletions

30
deploy/grafana-ds.yaml Normal file
View File

@ -0,0 +1,30 @@
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
uid: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
basicAuth: false
isDefault: false
version: 1
editable: false
jsonData:
httpMethod: GET
- name: Tempo
type: tempo
access: proxy
orgId: 1
url: http://tempo:3200
basicAuth: false
isDefault: true
version: 1
editable: false
apiVersion: 1
uid: tempo
jsonData:
httpMethod: GET
serviceMap:
datasourceUid: prometheus

View File

@ -18,6 +18,7 @@ services:
- "host.docker.internal:host-gateway" - "host.docker.internal:host-gateway"
volumes: volumes:
- grafana-volume:/var/lib/grafana - grafana-volume:/var/lib/grafana
- ./deploy/grafana-ds.yaml:/etc/grafana/provisioning/datasources/datasources.yaml
prometheus: prometheus:
image: prom/prometheus:v2.54.0 image: prom/prometheus:v2.54.0

View File

@ -24,7 +24,8 @@ import (
"time" "time"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/sdk/trace" traceSdk "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/trace"
) )
type App struct{} type App struct{}
@ -105,6 +106,24 @@ func (a *App) Run(p RunParams) {
} }
} }
var tracer trace.Tracer
{
tracerExporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpointURL("http://localhost:4318"))
if err != nil {
logger.Fatal().Err(err).Msg("failed initializing tracer")
}
tracerProvider := traceSdk.NewTracerProvider(
traceSdk.WithSampler(traceSdk.AlwaysSample()),
traceSdk.WithBatcher(
tracerExporter,
traceSdk.WithMaxQueueSize(4096),
traceSdk.WithMaxExportBatchSize(1024),
),
)
tracer = tracerProvider.Tracer("backend")
}
// Build business-logic objects // Build business-logic objects
var ( var (
userService services.UserService userService services.UserService
@ -115,7 +134,7 @@ func (a *App) Run(p RunParams) {
jwtUtil = utils.NewJwtUtil(key) jwtUtil = utils.NewJwtUtil(key)
passwordUtil = utils.NewPasswordUtil() passwordUtil = utils.NewPasswordUtil()
userRepo = repos.NewUserRepo(sqlDb) userRepo = repos.NewUserRepo(sqlDb, tracer)
emailRepo = repos.NewEmailRepo() emailRepo = repos.NewEmailRepo()
actionTokenRepo = repos.NewActionTokenRepo(sqlDb) actionTokenRepo = repos.NewActionTokenRepo(sqlDb)
@ -163,17 +182,6 @@ func (a *App) Run(p RunParams) {
clientNotifier := client_notifier.NewBasicNotifier() clientNotifier := client_notifier.NewBasicNotifier()
tracerExporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpointURL("http://localhost:4318"))
if err != nil {
logger.Fatal().Err(err).Msg("failed initializing tracer")
}
tracerProvider := trace.NewTracerProvider(
trace.WithSampler(trace.AlwaysSample()),
trace.WithBatcher(tracerExporter),
)
tracer := tracerProvider.Tracer("backend")
// Start profiling // Start profiling
if args.GetProfilePath() != "" { if args.GetProfilePath() != "" {
pprofFile, err := os.Create(args.GetProfilePath()) pprofFile, err := os.Create(args.GetProfilePath())

View File

@ -6,6 +6,8 @@ import (
"context" "context"
"database/sql" "database/sql"
"errors" "errors"
"go.opentelemetry.io/otel/trace"
) )
// type userDAO struct { // type userDAO struct {
@ -22,15 +24,19 @@ type UserRepo interface {
GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error) GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error)
} }
func NewUserRepo(db integrations.SqlDB) UserRepo { func NewUserRepo(db integrations.SqlDB, tracer trace.Tracer) UserRepo {
return &userRepo{db} return &userRepo{db, tracer}
} }
type userRepo struct { type userRepo struct {
db integrations.SqlDB db integrations.SqlDB
tracer trace.Tracer
} }
func (u *userRepo) CreateUser(ctx context.Context, dto models.UserDTO) (*models.UserDTO, error) { func (u *userRepo) CreateUser(ctx context.Context, dto models.UserDTO) (*models.UserDTO, error) {
_, span := u.tracer.Start(ctx, "postgres")
defer span.End()
query := `insert into users (email, secret, name) values ($1, $2, $3) returning id;` query := `insert into users (email, secret, name) values ($1, $2, $3) returning id;`
row := u.db.QueryRowContext(ctx, query, dto.Email, dto.Secret, dto.Name) row := u.db.QueryRowContext(ctx, query, dto.Email, dto.Secret, dto.Name)
@ -48,6 +54,9 @@ func (u *userRepo) CreateUser(ctx context.Context, dto models.UserDTO) (*models.
} }
func (u *userRepo) UpdateUser(ctx context.Context, userId string, dto models.UserUpdateDTO) error { func (u *userRepo) UpdateUser(ctx context.Context, userId string, dto models.UserUpdateDTO) error {
_, span := u.tracer.Start(ctx, "postgres")
defer span.End()
query := `update users set secret=$1, name=$2 where id = $3;` query := `update users set secret=$1, name=$2 where id = $3;`
_, err := u.db.ExecContext(ctx, query, dto.Secret, dto.Name, userId) _, err := u.db.ExecContext(ctx, query, dto.Secret, dto.Name, userId)
if err != nil { if err != nil {
@ -58,6 +67,9 @@ func (u *userRepo) UpdateUser(ctx context.Context, userId string, dto models.Use
} }
func (u *userRepo) GetUserById(ctx context.Context, id string) (*models.UserDTO, error) { func (u *userRepo) GetUserById(ctx context.Context, id string) (*models.UserDTO, error) {
_, span := u.tracer.Start(ctx, "postgres")
defer span.End()
query := `select id, email, secret, name from users where id = $1;` query := `select id, email, secret, name from users where id = $1;`
row := u.db.QueryRowContext(ctx, query, id) row := u.db.QueryRowContext(ctx, query, id)
@ -74,6 +86,9 @@ func (u *userRepo) GetUserById(ctx context.Context, id string) (*models.UserDTO,
} }
func (u *userRepo) GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error) { func (u *userRepo) GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error) {
_, span := u.tracer.Start(ctx, "postgres")
defer span.End()
query := `select id, email, secret, name from users where email = $1;` query := `select id, email, secret, name from users where email = $1;`
row := u.db.QueryRowContext(ctx, query, login) row := u.db.QueryRowContext(ctx, query, login)

View File

@ -7,7 +7,6 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
) )
@ -16,15 +15,11 @@ func NewRequestLogMiddleware(logger log.Logger, tracer trace.Tracer, prometheus
prometheus.RequestInc() prometheus.RequestInc()
defer prometheus.RequestDec() defer prometheus.RequestDec()
_, span := tracer.Start(c.Request.Context(), c.Request.URL.Path)
defer span.End()
requestId := c.GetHeader("X-Request-Id") requestId := c.GetHeader("X-Request-Id")
if requestId == "" { if requestId == "" {
requestId = uuid.New().String() requestId = uuid.New().String()
} }
span.SetAttributes(attribute.String("requestId", c.ClientIP()))
log.SetCtxRequestId(c, requestId) log.SetCtxRequestId(c, requestId)
path := c.Request.URL.Path path := c.Request.URL.Path

View File

@ -2,16 +2,26 @@ package middleware
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
) )
func NewTracingMiddleware(tracer trace.Tracer) gin.HandlerFunc { func NewTracingMiddleware(tracer trace.Tracer) gin.HandlerFunc {
prop := otel.GetTextMapPropagator()
return func(c *gin.Context) { return func(c *gin.Context) {
_, span := tracer.Start(c.Request.Context(), c.Request.URL.Path) savedCtx := c.Request.Context()
defer func() {
c.Request = c.Request.WithContext(savedCtx)
}()
ctx := prop.Extract(savedCtx, propagation.HeaderCarrier(c.Request.Header))
ctx, span := tracer.Start(ctx, c.Request.URL.Path)
defer span.End() defer span.End()
span.SetAttributes(attribute.String("requestId", c.ClientIP())) c.Request = c.Request.WithContext(ctx)
c.Next() c.Next()
} }

View File

@ -35,6 +35,8 @@ func New(opts NewServerOpts) *Server {
} }
r := gin.New() r := gin.New()
r.ContextWithFallback = true // Use it to allow getting values from c.Request.Context()
r.Static("/webapp", "./webapp") r.Static("/webapp", "./webapp")
r.GET("/health", handlers.NewDummyHandler()) r.GET("/health", handlers.NewDummyHandler())
@ -43,6 +45,7 @@ func New(opts NewServerOpts) *Server {
r.Use(middleware.NewRecoveryMiddleware(opts.Logger, prometheus, opts.DebugMode)) r.Use(middleware.NewRecoveryMiddleware(opts.Logger, prometheus, opts.DebugMode))
r.Use(middleware.NewRequestLogMiddleware(opts.Logger, opts.Tracer, prometheus)) r.Use(middleware.NewRequestLogMiddleware(opts.Logger, opts.Tracer, prometheus))
r.Use(middleware.NewTracingMiddleware(opts.Tracer))
r.GET("/pooling", handlers.NewLongPoolingHandler(opts.Logger, opts.Notifier)) r.GET("/pooling", handlers.NewLongPoolingHandler(opts.Logger, opts.Notifier))