diff --git a/changelogs/head.asciidoc b/changelogs/head.asciidoc index 8155e463ae8..ab1a5e60bcd 100644 --- a/changelogs/head.asciidoc +++ b/changelogs/head.asciidoc @@ -13,6 +13,7 @@ https://github.com/elastic/apm-server/compare/8.15\...main[View commits] [float] ==== Deprecations +- Support for Jaeger is now deprecated, and will be removed in a future release {pull}13809[13809] [float] ==== Intake API Changes diff --git a/internal/beater/jaeger/grpc.go b/internal/beater/jaeger/grpc.go index 624a6dfff16..f0c722d56e2 100644 --- a/internal/beater/jaeger/grpc.go +++ b/internal/beater/jaeger/grpc.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "strconv" + "sync" jaegermodel "github.com/jaegertracing/jaeger/model" "github.com/jaegertracing/jaeger/proto-gen/api_v2" @@ -58,6 +59,8 @@ const ( // elasticAuthTag is the name of the agent tag that will be used for auth. // The tag value should be "Bearer ". elasticAuthTag = "elastic-apm-auth" + + deprecationNotice = "deprecation notice: support for Jaeger will be removed in an upcoming version" ) // RegisterGRPCServices registers Jaeger gRPC services with srv. @@ -73,12 +76,18 @@ func RegisterGRPCServices( Logger: logger, Semaphore: semaphore, }) - api_v2.RegisterCollectorServiceServer(srv, &grpcCollector{traceConsumer}) - api_v2.RegisterSamplingManagerServer(srv, &grpcSampler{logger, fetcher}) + + logger.Info(deprecationNotice) + + api_v2.RegisterCollectorServiceServer(srv, &grpcCollector{sync.Once{}, logger, traceConsumer}) + api_v2.RegisterSamplingManagerServer(srv, &grpcSampler{sync.Once{}, logger, fetcher}) } // grpcCollector implements Jaeger api_v2 protocol for receiving tracing data type grpcCollector struct { + // Use an atomic counter to ensure concurrent safety. + once sync.Once + logger *zap.Logger consumer consumer.Traces } @@ -120,6 +129,11 @@ func (c *grpcCollector) RequestMetrics(fullMethodName string) map[request.Result // The implementation of the protobuf contract is based on the open-telemetry implementation at // https://github.com/open-telemetry/opentelemetry-collector/tree/master/receiver/jaegerreceiver func (c *grpcCollector) PostSpans(ctx context.Context, r *api_v2.PostSpansRequest) (*api_v2.PostSpansResponse, error) { + + c.once.Do(func() { + c.logger.Warn(deprecationNotice) + }) + if err := c.postSpans(ctx, r.Batch); err != nil { return nil, err } @@ -146,6 +160,8 @@ var ( ) type grpcSampler struct { + // Use an atomic counter to ensure concurrent safety. + once sync.Once logger *zap.Logger fetcher agentcfg.Fetcher } @@ -157,6 +173,10 @@ func (s *grpcSampler) GetSamplingStrategy( ctx context.Context, params *api_v2.SamplingStrategyParameters) (*api_v2.SamplingStrategyResponse, error) { + s.once.Do(func() { + s.logger.Warn(deprecationNotice) + }) + samplingRate, err := s.fetchSamplingRate(ctx, params.ServiceName) if err != nil { // do not return full error details since this is part of an unprotected endpoint response diff --git a/internal/beater/jaeger/grpc_test.go b/internal/beater/jaeger/grpc_test.go index d17f8796c8d..6b0914a4349 100644 --- a/internal/beater/jaeger/grpc_test.go +++ b/internal/beater/jaeger/grpc_test.go @@ -51,7 +51,7 @@ func TestPostSpans(t *testing.T) { var processor modelpb.ProcessBatchFunc = func(ctx context.Context, batch *modelpb.Batch) error { return processorErr } - conn, _ := newServer(t, processor, nil) + conn, logs := newServer(t, processor, nil) client := api_v2.NewCollectorServiceClient(conn) result, err := client.PostSpans(context.Background(), &api_v2.PostSpansRequest{}) @@ -80,6 +80,17 @@ func TestPostSpans(t *testing.T) { t.Run(name, func(t *testing.T) { processorErr = tc.processorErr resp, err := client.PostSpans(context.Background(), tc.request) + + // Deprecation log shown on server startup. + log := logs.All()[0] + assert.Equal(t, log.Level, zap.InfoLevel) + assert.Contains(t, log.Message, deprecationNotice) + + // Deprecation log shown on first endpoint hit. + log = logs.All()[1] + assert.Equal(t, log.Level, zap.WarnLevel) + assert.Contains(t, log.Message, deprecationNotice) + if tc.expectedErr != nil { assert.Nil(t, resp) assert.Error(t, err) @@ -167,15 +178,27 @@ func TestGRPCSampler_GetSamplingStrategy(t *testing.T) { client := api_v2.NewSamplingManagerClient(conn) resp, err := client.GetSamplingStrategy(context.Background(), tc.params) + // Deprecation log shown on server startup. + log := logs.All()[0] + assert.Equal(t, log.Level, zap.InfoLevel) + assert.Contains(t, log.Message, deprecationNotice) + + // Deprecation log shown on first endpoint hit. + log = logs.All()[1] + assert.Equal(t, log.Level, zap.WarnLevel) + assert.Contains(t, log.Message, deprecationNotice) + // assert sampling response if tc.expectedErrMsg != "" { require.Error(t, err) assert.Contains(t, err.Error(), tc.expectedErrMsg) assert.Nil(t, resp) - require.Equal(t, 1, logs.Len()) - log := logs.All()[0] + require.Equal(t, 3, logs.Len()) + + log = logs.All()[2] assert.Contains(t, log.Message, tc.expectedLogMsg) + if tc.expectedLogError != "" { assert.Equal(t, tc.expectedLogError, log.ContextMap()["error"]) }