mirror of
https://github.com/linka-cloud/grpc.git
synced 2025-06-22 01:02:29 +00:00
add otel module based on uptrace-go
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
120
otel/client.go
Normal file
120
otel/client.go
Normal file
@ -0,0 +1,120 @@
|
||||
package otel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
sdklog "go.opentelemetry.io/otel/sdk/log"
|
||||
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const dummySpanName = "__dummy__"
|
||||
|
||||
type client struct {
|
||||
dsn *DSN
|
||||
tracer trace.Tracer
|
||||
|
||||
tp *sdktrace.TracerProvider
|
||||
mp *sdkmetric.MeterProvider
|
||||
lp *sdklog.LoggerProvider
|
||||
}
|
||||
|
||||
func newClient(dsn *DSN) *client {
|
||||
return &client{
|
||||
dsn: dsn,
|
||||
tracer: otel.Tracer("otel-go"),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) Shutdown(ctx context.Context) (lastErr error) {
|
||||
if c.tp != nil {
|
||||
if err := c.tp.Shutdown(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
c.tp = nil
|
||||
}
|
||||
if c.mp != nil {
|
||||
if err := c.mp.Shutdown(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
c.mp = nil
|
||||
}
|
||||
if c.lp != nil {
|
||||
if err := c.lp.Shutdown(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
c.lp = nil
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
|
||||
func (c *client) ForceFlush(ctx context.Context) (lastErr error) {
|
||||
if c.tp != nil {
|
||||
if err := c.tp.ForceFlush(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
if c.mp != nil {
|
||||
if err := c.mp.ForceFlush(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
if c.lp != nil {
|
||||
if err := c.lp.ForceFlush(ctx); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
|
||||
// TraceURL returns the trace URL for the span.
|
||||
func (c *client) TraceURL(span trace.Span) string {
|
||||
sctx := span.SpanContext()
|
||||
return fmt.Sprintf("%s/traces/%s?span_id=%s",
|
||||
c.dsn.SiteURL(), sctx.TraceID(), sctx.SpanID().String())
|
||||
}
|
||||
|
||||
// ReportError reports an error as a span event creating a dummy span if necessary.
|
||||
func (c *client) ReportError(ctx context.Context, err error, opts ...trace.EventOption) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
if !span.IsRecording() {
|
||||
_, span = c.tracer.Start(ctx, dummySpanName)
|
||||
defer span.End()
|
||||
}
|
||||
|
||||
span.RecordError(err, opts...)
|
||||
}
|
||||
|
||||
// ReportPanic is used with defer to report panics.
|
||||
func (c *client) ReportPanic(ctx context.Context, val any) {
|
||||
c.reportPanic(ctx, val)
|
||||
// Force flush since we are about to exit on panic.
|
||||
if c.tp != nil {
|
||||
_ = c.tp.ForceFlush(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) reportPanic(ctx context.Context, val interface{}) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
if !span.IsRecording() {
|
||||
_, span = c.tracer.Start(ctx, dummySpanName)
|
||||
defer span.End()
|
||||
}
|
||||
|
||||
stackTrace := make([]byte, 2048)
|
||||
n := runtime.Stack(stackTrace, false)
|
||||
|
||||
span.AddEvent(
|
||||
"log",
|
||||
trace.WithAttributes(
|
||||
attribute.String("log.severity", "panic"),
|
||||
attribute.String("log.message", fmt.Sprint(val)),
|
||||
attribute.String("exception.stackstrace", string(stackTrace[:n])),
|
||||
),
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user