add grpc support
This commit is contained in:
		| @@ -22,7 +22,7 @@ import ( | ||||
| 	"go.opentelemetry.io/otel/sdk/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| 	traceSDK "go.opentelemetry.io/otel/sdk/trace" | ||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.24.0" | ||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.27.0" | ||||
| 	trace "go.opentelemetry.io/otel/trace" | ||||
| 	"go.opentelemetry.io/otel/trace/noop" | ||||
| ) | ||||
| @@ -170,7 +170,7 @@ func newResource(ctx context.Context) *resource.Resource { | ||||
| 	attributes := []attribute.KeyValue{ | ||||
| 		semconv.ServiceName(cfg.Name), | ||||
| 		semconv.ServiceVersion(cfg.Version), | ||||
| 		semconv.DeploymentEnvironment(cfg.Environment), | ||||
| 		semconv.DeploymentEnvironmentName(cfg.Environment), | ||||
| 		semconv.K8SPodName(os.Getenv("HOSTNAME")), | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package grpc | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/codes" | ||||
| 	"go.opentelemetry.io/otel/metric" | ||||
| 	"go.opentelemetry.io/otel/trace" | ||||
| @@ -38,12 +40,18 @@ func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) error { | ||||
| 	ctx, span := appGRPC.tracer.Start(ctx, "appgrpc.init") | ||||
| 	defer span.End() | ||||
|  | ||||
| 	// Prepare grpc.Server for use | ||||
| 	if err := appGRPC.prepGRPCServer(ctx); err != nil { | ||||
| 		span.RecordError(err) | ||||
| 		span.SetStatus(codes.Error, "failed to prepare GRPC Server") | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Load span with server info | ||||
| 	span.SetAttributes(appGRPC.getServerAttributes()...) | ||||
|  | ||||
| 	// Run, returning a shutdown func and an error chan | ||||
| 	// TODO: Implement shutdown func and error chan | ||||
| 	err := appGRPC.runGRPCServer(ctx) | ||||
| 	if err != nil { | ||||
| 		span.RecordError(err) | ||||
| @@ -54,3 +62,31 @@ func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) error { | ||||
| 	span.SetStatus(codes.Ok, "") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Convert grpc.ServiceInfo map to []attribute.KeyValue | ||||
| func (a *appGRPCServer) getServerAttributes() []attribute.KeyValue { | ||||
| 	var attrs []attribute.KeyValue | ||||
|  | ||||
| 	for serviceName, info := range a.server.GetServiceInfo() { | ||||
| 		// Add the service name | ||||
| 		attrs = append(attrs, attribute.String("grpc.service", serviceName)) | ||||
|  | ||||
| 		// Convert methods into a comma-separated string | ||||
| 		var methods []string | ||||
| 		for _, method := range info.Methods { | ||||
| 			methods = append(methods, method.Name) | ||||
| 		} | ||||
|  | ||||
| 		// Add methods if present | ||||
| 		if len(methods) > 0 { | ||||
| 			attrs = append(attrs, attribute.String("grpc.service.methods", strings.Join(methods, ","))) | ||||
| 		} | ||||
|  | ||||
| 		// If metadata is a string, store it | ||||
| 		if metadata, ok := info.Metadata.(string); ok && metadata != "" { | ||||
| 			attrs = append(attrs, attribute.String("grpc.service.metadata", metadata)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return attrs | ||||
| } | ||||
|   | ||||
| @@ -34,31 +34,31 @@ func (a *appGRPCServer) prepGRPCServer(spanCtx context.Context) error { | ||||
| 	// Chain interceptors for unary RPCs | ||||
| 	a.serverOpts = append(a.serverOpts, | ||||
| 		grpc.ChainUnaryInterceptor(a.opts.UnaryInterceptors...)) | ||||
| 	span.SetAttributes(attribute.Int("numUnaryInterceptors", | ||||
| 	span.SetAttributes(attribute.Int("grpc.server.unaryinterceptors", | ||||
| 		len(a.opts.UnaryInterceptors))) | ||||
|  | ||||
| 	// Chain interceptors for streaming RPCs | ||||
| 	a.serverOpts = append(a.serverOpts, | ||||
| 		grpc.ChainStreamInterceptor(a.opts.StreamInterceptors...)) | ||||
| 	span.SetAttributes(attribute.Int("numStreamInterceptors", | ||||
| 	span.SetAttributes(attribute.Int("grpc.server.streaminterceptors", | ||||
| 		len(a.opts.StreamInterceptors))) | ||||
|  | ||||
| 	// Prepare GRPC Server | ||||
| 	a.server = grpc.NewServer(a.serverOpts...) | ||||
| 	span.SetAttributes(attribute.Int("numServerOpts", len(a.serverOpts))) | ||||
| 	span.SetAttributes(attribute.Int("grpc.server.serveropts", len(a.serverOpts))) | ||||
|  | ||||
| 	// Load given services into server registry | ||||
| 	for _, service := range a.opts.Services { | ||||
| 		span.AddEvent(fmt.Sprintf("registered %s service", service.Name)) | ||||
| 		a.server.RegisterService(service.Type, service.Service) | ||||
| 	} | ||||
| 	span.SetAttributes(attribute.Int("numGRPCServices", len(a.opts.Services))) | ||||
| 	span.SetAttributes(attribute.Int("grpc.server.grpcservices", len(a.opts.Services))) | ||||
|  | ||||
| 	// Enable reflection if desired | ||||
| 	if a.opts.EnableReflection { | ||||
| 		reflection.Register(a.server) | ||||
| 	} | ||||
| 	span.SetAttributes(attribute.Bool("reflectionEnabled", a.opts.EnableReflection)) | ||||
| 	span.SetAttributes(attribute.Bool("grpc.server.reflection", a.opts.EnableReflection)) | ||||
|  | ||||
| 	span.SetStatus(codes.Ok, "") | ||||
| 	return nil | ||||
| @@ -66,8 +66,7 @@ func (a *appGRPCServer) prepGRPCServer(spanCtx context.Context) error { | ||||
|  | ||||
| func (a *appGRPCServer) prepareOTEL(spanCtx context.Context) { | ||||
| 	_, span := a.tracer.Start(spanCtx, "appgrpc.init.prepare.otel", trace.WithAttributes( | ||||
| 		attribute.Bool("instrumentationEnabled", a.opts.EnableInstrumentation), | ||||
| 		attribute.String("logLevel", a.logger.GetLevel().String()))) | ||||
| 		attribute.Bool("grpc.server.instrumented", a.opts.EnableInstrumentation))) | ||||
| 	defer span.End() | ||||
|  | ||||
| 	if a.opts.EnableInstrumentation { | ||||
| @@ -83,7 +82,8 @@ func (a *appGRPCServer) prepareOTEL(spanCtx context.Context) { | ||||
|  | ||||
| func (a *appGRPCServer) prepareLogging(spanCtx context.Context) { | ||||
| 	_, span := a.tracer.Start(spanCtx, "appgrpc.init.prepare.logging", trace.WithAttributes( | ||||
| 		attribute.Bool("instrumentationEnabled", a.opts.LogRequests))) | ||||
| 		attribute.Bool("grpc.server.instrumentated", a.opts.LogRequests), | ||||
| 		attribute.String("grpc.server.loglevel", a.logger.GetLevel().String()))) | ||||
| 	defer span.End() | ||||
|  | ||||
| 	if a.opts.LogRequests { | ||||
|   | ||||
| @@ -1,11 +1,21 @@ | ||||
| package grpc | ||||
|  | ||||
| import "context" | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	semconv "go.opentelemetry.io/otel/semconv/v1.27.0" | ||||
| ) | ||||
|  | ||||
| // TODO: Implement | ||||
| func (a *appGRPCServer) runGRPCServer(spanCtx context.Context) error { | ||||
| 	_, span := a.tracer.Start(spanCtx, "appgrpc.init.start") | ||||
| 	defer span.End() | ||||
|  | ||||
| 	span.SetAttributes( | ||||
| 		semconv.RPCSystemGRPC, | ||||
| 		semconv.NetworkProtocolName("grpc"), | ||||
| 		semconv.ServerAddress(a.opts.Listen), | ||||
| 	) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user