-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: integrate OpenTelemetry and dependencies into project
- Add the `otelx` package with OpenTelemetry SDK setup - Add `github.com/blackhorseya/ryze/pkg/contextx` import to several files - Change the error message in `initApplication` to include service name - Add `github.com/cenkalti/backoff/v4` and `github.com/google/uuid` as dependencies - Add `github.com/grpc-ecosystem/grpc-gateway/v2` as a dependency - Update the dependencies for OpenTelemetry to version `v1.28.0` Signed-off-by: Sean Zheng <[email protected]>
- Loading branch information
1 parent
ff74387
commit ba4234a
Showing
7 changed files
with
236 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package otelx | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/blackhorseya/ryze/app/infra/configx" | ||
"github.com/blackhorseya/ryze/pkg/contextx" | ||
"go.opentelemetry.io/otel" | ||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" | ||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" | ||
"go.opentelemetry.io/otel/propagation" | ||
sdkmetric "go.opentelemetry.io/otel/sdk/metric" | ||
"go.opentelemetry.io/otel/sdk/resource" | ||
sdktrace "go.opentelemetry.io/otel/sdk/trace" | ||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0" | ||
"go.opentelemetry.io/otel/trace" | ||
"go.uber.org/zap" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials/insecure" | ||
) | ||
|
||
var ( | ||
// Tracer is the global tracer. | ||
Tracer = otel.Tracer("") | ||
|
||
// Meter is the global meter. | ||
Meter = otel.Meter("") | ||
) | ||
|
||
// Shutdown is the function to shutdown the OpenTelemetry SDK. | ||
var Shutdown = func(context.Context) error { | ||
return nil | ||
} | ||
|
||
// SetupOTelSDK sets up the OpenTelemetry SDK with the Jaeger exporter. | ||
func SetupOTelSDK(ctx contextx.Contextx, app *configx.Application) (err error) { | ||
if app.OTel.Target == "" { | ||
ctx.Warn("OpenTelemetry is disabled") | ||
return nil | ||
} | ||
|
||
ctx.Info( | ||
"setting up OpenTelemetry SDK", | ||
zap.String("service_name", app.Name), | ||
zap.String("otlp", app.OTel.Target), | ||
) | ||
|
||
var shutdownFuncs []func(context.Context) error | ||
|
||
Shutdown = func(ctx context.Context) error { | ||
for _, fn := range shutdownFuncs { | ||
err = errors.Join(err, fn(ctx)) | ||
} | ||
shutdownFuncs = nil | ||
return err | ||
} | ||
|
||
res, err := resource.New(ctx, resource.WithAttributes(semconv.ServiceNameKey.String(app.Name))) | ||
if err != nil { | ||
return fmt.Errorf("failed to create resource: %w", err) | ||
} | ||
|
||
conn, err := initConn(app) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
tracerProvider, err := newTracer(ctx, res, conn, app) | ||
if err != nil { | ||
return err | ||
} | ||
shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) | ||
|
||
meterProvider, err := newMeter(ctx, res, conn, app) | ||
if err != nil { | ||
return err | ||
} | ||
shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) | ||
|
||
return nil | ||
} | ||
|
||
func initConn(app *configx.Application) (*grpc.ClientConn, error) { | ||
conn, err := grpc.NewClient(app.OTel.Target, grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create gRPC client: %w", err) | ||
} | ||
|
||
return conn, nil | ||
} | ||
|
||
func newTracer( | ||
ctx context.Context, | ||
res *resource.Resource, | ||
conn *grpc.ClientConn, | ||
app *configx.Application, | ||
) (*sdktrace.TracerProvider, error) { | ||
exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create the Jaeger exporter: %w", err) | ||
} | ||
|
||
processor := sdktrace.NewBatchSpanProcessor(exporter) | ||
provider := sdktrace.NewTracerProvider( | ||
sdktrace.WithSampler(sdktrace.AlwaysSample()), | ||
sdktrace.WithResource(res), | ||
sdktrace.WithSpanProcessor(processor), | ||
) | ||
otel.SetTracerProvider(provider) | ||
|
||
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( | ||
propagation.TraceContext{}, | ||
propagation.Baggage{}, | ||
)) | ||
|
||
Tracer = provider.Tracer(app.Name) | ||
|
||
return provider, nil | ||
} | ||
|
||
func newMeter( | ||
ctx context.Context, | ||
res *resource.Resource, | ||
conn *grpc.ClientConn, | ||
app *configx.Application, | ||
) (p *sdkmetric.MeterProvider, err error) { | ||
exporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithGRPCConn(conn)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create the OTLP exporter: %w", err) | ||
} | ||
|
||
provider := sdkmetric.NewMeterProvider( | ||
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter, sdkmetric.WithInterval(3*time.Second))), | ||
sdkmetric.WithResource(res), | ||
) | ||
otel.SetMeterProvider(provider) | ||
|
||
Meter = provider.Meter(app.Name) | ||
|
||
return provider, nil | ||
} | ||
|
||
// Span is used to start a span. | ||
func Span(parent contextx.Contextx, name string) (ctx contextx.Contextx, span trace.Span) { | ||
next, span := Tracer.Start(parent, name) | ||
return contextx.WithContext(next), span | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters