mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description
The gRPC service handlers for all four signal types allocate the
top-level ExportXxxServiceRequest with bare new(), bypassing the
sync.Pool when pdata.useProtoPooling is enabled. This means objects
returned to the pool via Delete are never retrieved, so the pool
accumulates unreused objects.
Replace new() with the pool-aware New*() constructors so the top-level
request struct participates in the pool lifecycle.
benchstat (20 runs, pdata.useProtoPooling=true, 10k logs/request):
```
│ old (new()) │ new (New*()) │
│ sec/op │ sec/op vs base │
GRPCLogsSequentialPooling-12 3.858m ± 2% 3.811m ± 1% ~ (p=0.165 n=20)
│ B/op │ B/op vs base │
GRPCLogsSequentialPooling-12 3.551Mi ± 2% 3.523Mi ± 1% ~ (p=0.445 n=20)
│ allocs/op │ allocs/op vs base│
GRPCLogsSequentialPooling-12 75.46k ± 0% 75.46k ± 0% ~ (p=0.867 n=20)
```
No measurable perf difference (1 alloc out of 75k), but this is a
correctness fix for the pool lifecycle.
<!-- Issue number if applicable -->
#### Link to tracking issue
Fixes #
<!--Describe what testing was performed and which tests were added.-->
#### Testing
<!--Describe the documentation added.-->
#### Documentation
<!--Please delete paragraphs that you did not use before submitting.-->
---------
Co-authored-by: Pablo Baeyens <[email protected]>
89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package otelgrpc // import "go.opentelemetry.io/collector/pdata/internal/otelgrpc"
|
|
|
|
import (
|
|
"context"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
|
|
"go.opentelemetry.io/collector/pdata/internal"
|
|
)
|
|
|
|
// MetricsServiceClient is the client API for MetricsService service.
|
|
//
|
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
|
type MetricsServiceClient interface {
|
|
Export(context.Context, *internal.ExportMetricsServiceRequest, ...grpc.CallOption) (*internal.ExportMetricsServiceResponse, error)
|
|
}
|
|
|
|
type metricsServiceClient struct {
|
|
cc *grpc.ClientConn
|
|
}
|
|
|
|
func NewMetricsServiceClient(cc *grpc.ClientConn) MetricsServiceClient {
|
|
return &metricsServiceClient{cc}
|
|
}
|
|
|
|
func (c *metricsServiceClient) Export(ctx context.Context, in *internal.ExportMetricsServiceRequest, opts ...grpc.CallOption) (*internal.ExportMetricsServiceResponse, error) {
|
|
out := new(internal.ExportMetricsServiceResponse)
|
|
err := c.cc.Invoke(ctx, "/opentelemetry.proto.collector.metrics.v1.MetricsService/Export", in, out, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// MetricsServiceServer is the server API for MetricsService service.
|
|
type MetricsServiceServer interface {
|
|
Export(context.Context, *internal.ExportMetricsServiceRequest) (*internal.ExportMetricsServiceResponse, error)
|
|
}
|
|
|
|
// UnimplementedMetricsServiceServer can be embedded to have forward compatible implementations.
|
|
type UnimplementedMetricsServiceServer struct{}
|
|
|
|
func (*UnimplementedMetricsServiceServer) Export(context.Context, *internal.ExportMetricsServiceRequest) (*internal.ExportMetricsServiceResponse, error) {
|
|
return nil, status.Errorf(codes.Unimplemented, "method Export not implemented")
|
|
}
|
|
|
|
func RegisterMetricsServiceServer(s *grpc.Server, srv MetricsServiceServer) {
|
|
s.RegisterService(&metricsServiceServiceDesc, srv)
|
|
}
|
|
|
|
// Context cannot be the first parameter of the function because gRPC definition.
|
|
//
|
|
//nolint:revive
|
|
func metricsServiceExportHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
|
|
in := internal.NewExportMetricsServiceRequest()
|
|
if err := dec(in); err != nil {
|
|
return nil, err
|
|
}
|
|
if interceptor == nil {
|
|
return srv.(MetricsServiceServer).Export(ctx, in)
|
|
}
|
|
info := &grpc.UnaryServerInfo{
|
|
Server: srv,
|
|
FullMethod: "/opentelemetry.proto.collector.metrics.v1.MetricsService/Export",
|
|
}
|
|
handler := func(ctx context.Context, req any) (any, error) {
|
|
return srv.(MetricsServiceServer).Export(ctx, req.(*internal.ExportMetricsServiceRequest))
|
|
}
|
|
return interceptor(ctx, in, info, handler)
|
|
}
|
|
|
|
var metricsServiceServiceDesc = grpc.ServiceDesc{
|
|
ServiceName: "opentelemetry.proto.collector.metrics.v1.MetricsService",
|
|
HandlerType: (*MetricsServiceServer)(nil),
|
|
Methods: []grpc.MethodDesc{
|
|
{
|
|
MethodName: "Export",
|
|
Handler: metricsServiceExportHandler,
|
|
},
|
|
},
|
|
Streams: []grpc.StreamDesc{},
|
|
Metadata: "opentelemetry/proto/collector/metrics/v1/metrics_service.proto",
|
|
}
|