From b10a1ee986601139d936bff8a0b88c5bbabfef13 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Fri, 19 Apr 2024 10:00:42 +0700 Subject: [PATCH 01/17] add initial storage_v2/storage.proto API design Signed-off-by: James Ryans --- .../grpc/proto/storage_v2/storage.proto | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 plugin/storage/grpc/proto/storage_v2/storage.proto diff --git a/plugin/storage/grpc/proto/storage_v2/storage.proto b/plugin/storage/grpc/proto/storage_v2/storage.proto new file mode 100644 index 00000000000..86c2f3b61bb --- /dev/null +++ b/plugin/storage/grpc/proto/storage_v2/storage.proto @@ -0,0 +1,224 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +syntax="proto3"; + +package jaeger.storage_v2; + +import "opentelemetry/proto/collector/trace/v1/trace_service.proto"; +import "opentelemetry/proto/trace/v1/trace.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +import "model.proto"; + +option go_package = "storage_v2"; +option java_package = "io.jaegertracing.storage_v2"; + +message CloseWriterRequest { +} + +message CloseWriterResponse { +} + +// Request object to get a trace. +message GetTraceRequest { + // Hex encoded 64 or 128 bit trace ID. + string trace_id = 1; + // Optional. The start time to search trace ID. + google.protobuf.Timestamp start_time = 2 [ + (gogoproto.stdtime) = true + ]; + // Optional. The end time to search trace ID. + google.protobuf.Timestamp end_time = 3 [ + (gogoproto.stdtime) = true + ]; +} + +// Query parameters to find traces. Except for num_traces, all fields should be treated +// as forming a conjunction, e.g., "service_name='X' AND operation_name='Y' AND ...". +// All fields are matched against individual spans, not at the trace level. +// The returned results contain traces where at least one span matches the conditions. +// When num_traces results in fewer traces returned, there is no required ordering. +// +// Note: num_traces should restrict the number of traces returned, but not all backends +// interpret it this way. For instance, in Cassandra this limits the number of _spans_ +// that match the conditions, and the resulting number of traces can be less. +// +// Note: some storage implementations do not guarantee the correct implementation of all parameters. +// +message TraceQueryParameters { + string service_name = 1; + string operation_name = 2; + // Attributes are matched against Span and Resource attributes. + // At least one span in a trace must match all specified attributes. + map attributes = 3; + // Span min start time in. REST API uses RFC-3339ns format. Required. + google.protobuf.Timestamp start_time_min = 4; + // Span max start time. REST API uses RFC-3339ns format. Required. + google.protobuf.Timestamp start_time_max = 5; + // Span min duration. REST API uses Golang's time format e.g. 10s. + google.protobuf.Duration duration_min = 6; + // Span max duration. REST API uses Golang's time format e.g. 10s. + google.protobuf.Duration duration_max = 7; + + // Maximum number of traces in the response. + int32 num_traces = 8; +} + +// Request object to search traces. +message FindTracesRequest { + TraceQueryParameters query = 1; +} + +// Response object to search trace IDs. +message FindTraceIDsResponse { + // Hex encoded 64 or 128 bit trace ID. + repeated string trace_ids = 1; +} + +// Request object to get service names. +message GetServicesRequest {} + +// Response object to get service names. +message GetServicesResponse { + repeated string services = 1; +} + +// Request object to get operation names. +message GetOperationsRequest { + // Required service name. + string service = 1; + // Optional span kind. + string span_kind = 2; +} + +// Operation encapsulates information about operation. +message Operation { + string name = 1; + string span_kind = 2; +} + +// Response object to get operation names. +message GetOperationsResponse { + repeated Operation operations = 1; +} + +// Request object to archive a trace. +message ArchiveTraceRequest { + // Hex encoded 64 or 128 bit trace ID. + string trace_id = 1; +} + +// Response object to archive a trace. +message ArchiveTraceResponse { +} + +// Request object to get dependencies. +message GetDependenciesRequest { + google.protobuf.Timestamp start_time = 1 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; + google.protobuf.Timestamp end_time = 2 [ + (gogoproto.stdtime) = true, + (gogoproto.nullable) = false + ]; +} + +// Response object to get dependencies. +message GetDependenciesResponse { + repeated jaeger.api_v2.DependencyLink dependencies = 1 [ + (gogoproto.nullable) = false + ]; +} + +// Request object get to capabilities. +message CapabilitiesRequest { +} + +// Response object get to capabilities. +message CapabilitiesResponse { + bool archiveSpanWriter = 1; +} + +// spanstore/Writer +service SpanWriterPlugin { + // Export is a batched version of WriteSpan that handles OTLP exporter. + rpc Export(opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest) returns (opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse) {} + + // Close supports graceful shutdown for Writer + rpc Close(CloseWriterRequest) returns (CloseWriterResponse) {} +} + +// spanstore/Reader +service SpanReaderPlugin { + // GetTrace returns a single trace. + // Note that the JSON response over HTTP is wrapped into result envelope "{"result": ...}" + // It means that the JSON response cannot be directly unmarshalled using JSONPb. + // This can be fixed by first parsing into user-defined envelope with standard JSON library + // or string manipulation to remove the envelope. Alternatively generate objects using OpenAPI. + rpc GetTrace(GetTraceRequest) returns (stream opentelemetry.proto.trace.v1.TracesData) {} + + // FindTraces searches for traces. + // See GetTrace for JSON unmarshalling. + rpc FindTraces(FindTracesRequest) returns (stream opentelemetry.proto.trace.v1.TracesData) {} + + // FindTraceIDs searches for traces and returns the traceID. + rpc FindTraceIDs(FindTracesRequest) returns (FindTraceIDsResponse) {} + + // GetServices returns service names. + rpc GetServices(GetServicesRequest) returns (GetServicesResponse) {} + + // GetOperations returns operation names. + rpc GetOperations(GetOperationsRequest) returns (GetOperationsResponse) {} +} + +// querysvc/QueryService +service QueryService { + // ArchiveTrace finds a trace from primary storage and write it to archive storage. + rpc ArchiveTrace(ArchiveTraceRequest) returns (ArchiveTraceResponse) {} +} + +// dependencystore/Reader +service DependenciesReaderPlugin { + // GetDependencies + rpc GetDependencies(GetDependenciesRequest) returns (GetDependenciesResponse); +} + +service PluginCapabilities { + // Capabilities returns the supported features of the server. + // Currently, it only has an archiveSpanWriter capability. + rpc Capabilities(CapabilitiesRequest) returns (CapabilitiesResponse); +} + +// Below are some helper types when using APIv3 via HTTP endpoints. + +// GRPCGatewayError is the type returned when GRPC server returns an error. +// Example: {"error":{"grpcCode":2,"httpCode":500,"message":"...","httpStatus":"text..."}}. +message GRPCGatewayError { + message GRPCGatewayErrorDetails { + int32 grpcCode = 1; + int32 httpCode = 2; + string message = 3; + string httpStatus = 4; + } + + GRPCGatewayErrorDetails error = 1; +} + +// GRPCGatewayWrapper wraps streaming responses from GetTrace/FindTraces for HTTP. +// Today there is always only one response because internally the HTTP server gets +// data from QueryService that does not support multiple responses. But in the +// future the server may return multiple responeses using Transfer-Encoding: chunked. +// In case of errors, GRPCGatewayError above is used. +// +// Example: +// {"result": {"resourceSpans": ...}} +// +// See https://github.com/grpc-ecosystem/grpc-gateway/issues/2189 +// +message GRPCGatewayWrapper { + opentelemetry.proto.trace.v1.TracesData result = 1; +} From 5ad48626231a4419ced0bc230f4062cdc4ee6d08 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Thu, 25 Apr 2024 16:09:51 +0700 Subject: [PATCH 02/17] move storage_v2 proto to storage_v2/proto/storage.proto Signed-off-by: James Ryans --- .../proto/storage_v2 => storage_v2/proto}/storage.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename {plugin/storage/grpc/proto/storage_v2 => storage_v2/proto}/storage.proto (98%) diff --git a/plugin/storage/grpc/proto/storage_v2/storage.proto b/storage_v2/proto/storage.proto similarity index 98% rename from plugin/storage/grpc/proto/storage_v2/storage.proto rename to storage_v2/proto/storage.proto index 86c2f3b61bb..a5f23fbdc5f 100644 --- a/plugin/storage/grpc/proto/storage_v2/storage.proto +++ b/storage_v2/proto/storage.proto @@ -144,7 +144,7 @@ message CapabilitiesResponse { } // spanstore/Writer -service SpanWriterPlugin { +service TraceWriter { // Export is a batched version of WriteSpan that handles OTLP exporter. rpc Export(opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest) returns (opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse) {} @@ -153,7 +153,7 @@ service SpanWriterPlugin { } // spanstore/Reader -service SpanReaderPlugin { +service TraceReader { // GetTrace returns a single trace. // Note that the JSON response over HTTP is wrapped into result envelope "{"result": ...}" // It means that the JSON response cannot be directly unmarshalled using JSONPb. @@ -176,13 +176,13 @@ service SpanReaderPlugin { } // querysvc/QueryService -service QueryService { +service TraceArchiver { // ArchiveTrace finds a trace from primary storage and write it to archive storage. rpc ArchiveTrace(ArchiveTraceRequest) returns (ArchiveTraceResponse) {} } // dependencystore/Reader -service DependenciesReaderPlugin { +service DependenciesReader { // GetDependencies rpc GetDependencies(GetDependenciesRequest) returns (GetDependenciesResponse); } From 1905b67ed60ee489c33e8ede44f69e28f11b9acb Mon Sep 17 00:00:00 2001 From: James Ryans Date: Thu, 25 Apr 2024 16:11:39 +0700 Subject: [PATCH 03/17] construct the storage_v2 spanstore interface structure Signed-off-by: James Ryans --- storage_v2/spanstore/factory.go | 18 +++++++++ storage_v2/spanstore/reader.go | 65 +++++++++++++++++++++++++++++++++ storage_v2/spanstore/writer.go | 17 +++++++++ 3 files changed, 100 insertions(+) create mode 100644 storage_v2/spanstore/factory.go create mode 100644 storage_v2/spanstore/reader.go create mode 100644 storage_v2/spanstore/writer.go diff --git a/storage_v2/spanstore/factory.go b/storage_v2/spanstore/factory.go new file mode 100644 index 00000000000..30d08a2f87e --- /dev/null +++ b/storage_v2/spanstore/factory.go @@ -0,0 +1,18 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package spanstore + +// Factory defines an interface for a factory that can create implementations of different storage components. +// Implementations are also encouraged to implement plugin.Configurable interface. +type Factory interface { + // Initialize performs internal initialization of the factory, such as opening connections to the backend store. + // It is called after all configuration of the factory itself has been done. + Initialize() error + + // CreateSpanReader creates a spanstore.Reader. + CreateTraceReader() (Reader, error) + + // CreateSpanWriter creates a spanstore.Writer. + CreateTraceWriter() (Writer, error) +} diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go new file mode 100644 index 00000000000..0c8a0065d60 --- /dev/null +++ b/storage_v2/spanstore/reader.go @@ -0,0 +1,65 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package spanstore + +import ( + "context" + "time" + + "github.com/jaegertracing/jaeger/model" +) + +// Reader finds and loads traces and other data from storage. +type Reader interface { + // GetTrace retrieves the trace with a given id. + // + // If no spans are stored for this trace, it returns ErrTraceNotFound. + GetTrace(ctx context.Context, traceID model.TraceID) (*model.Trace, error) + + // GetServices returns all service names known to the backend from spans + // within its retention period. + GetServices(ctx context.Context) ([]string, error) + + // GetOperations returns all operation names for a given service + // known to the backend from spans within its retention period. + GetOperations(ctx context.Context, query OperationQueryParameters) ([]Operation, error) + + // FindTraces returns all traces matching query parameters. There's currently + // an implementation-dependent abiguity whether all query filters (such as + // multiple tags) must apply to the same span within a trace, or can be satisfied + // by different spans. + // + // If no matching traces are found, the function returns (nil, nil). + FindTraces(ctx context.Context, query *TraceQueryParameters) ([]*model.Trace, error) + + // FindTraceIDs does the same search as FindTraces, but returns only the list + // of matching trace IDs. + // + // If no matching traces are found, the function returns (nil, nil). + FindTraceIDs(ctx context.Context, query *TraceQueryParameters) ([]model.TraceID, error) +} + +// TraceQueryParameters contains parameters of a trace query. +type TraceQueryParameters struct { + ServiceName string + OperationName string + Tags map[string]string + StartTimeMin time.Time + StartTimeMax time.Time + DurationMin time.Duration + DurationMax time.Duration + NumTraces int +} + +// OperationQueryParameters contains parameters of query operations, empty spanKind means get operations for all kinds of span. +type OperationQueryParameters struct { + ServiceName string + SpanKind string +} + +// Operation contains operation name and span kind +type Operation struct { + Name string + SpanKind string +} diff --git a/storage_v2/spanstore/writer.go b/storage_v2/spanstore/writer.go new file mode 100644 index 00000000000..0b71b31b30d --- /dev/null +++ b/storage_v2/spanstore/writer.go @@ -0,0 +1,17 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package spanstore + +import ( + "context" + + "go.opentelemetry.io/collector/pdata/ptrace" +) + +// Writer writes spans to storage. +type Writer interface { + // WriteTrace writes batches of spans at once and + // compatible with OTLP Exporter API. + WriteTraces(ctx context.Context, td ptrace.Traces) error +} From 5b59349e50fb4e95e825938a31aa6b3b8a9c008b Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 00:18:57 +0700 Subject: [PATCH 04/17] Remove Close API from TraceWriter service Signed-off-by: James Ryans --- storage_v2/proto/storage.proto | 9 --------- 1 file changed, 9 deletions(-) diff --git a/storage_v2/proto/storage.proto b/storage_v2/proto/storage.proto index a5f23fbdc5f..afad9eff4ca 100644 --- a/storage_v2/proto/storage.proto +++ b/storage_v2/proto/storage.proto @@ -16,12 +16,6 @@ import "model.proto"; option go_package = "storage_v2"; option java_package = "io.jaegertracing.storage_v2"; -message CloseWriterRequest { -} - -message CloseWriterResponse { -} - // Request object to get a trace. message GetTraceRequest { // Hex encoded 64 or 128 bit trace ID. @@ -147,9 +141,6 @@ message CapabilitiesResponse { service TraceWriter { // Export is a batched version of WriteSpan that handles OTLP exporter. rpc Export(opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest) returns (opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse) {} - - // Close supports graceful shutdown for Writer - rpc Close(CloseWriterRequest) returns (CloseWriterResponse) {} } // spanstore/Reader From 36c235a1db62a9c53b7e16a233e085d47e6b1866 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 00:50:40 +0700 Subject: [PATCH 05/17] Add empty test to storage_v2/spanstore/ Signed-off-by: James Ryans --- storage_v2/spanstore/empty_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 storage_v2/spanstore/empty_test.go diff --git a/storage_v2/spanstore/empty_test.go b/storage_v2/spanstore/empty_test.go new file mode 100644 index 00000000000..50d2cb2753a --- /dev/null +++ b/storage_v2/spanstore/empty_test.go @@ -0,0 +1,14 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package spanstore + +import ( + "testing" + + "github.com/jaegertracing/jaeger/pkg/testutils" +) + +func TestMain(m *testing.M) { + testutils.VerifyGoLeaks(m) +} From 663324d119b9417d58eeccd52ef00c5b9f2d8730 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 12:06:36 +0700 Subject: [PATCH 06/17] Clarify WriteTraces func description Signed-off-by: James Ryans --- storage_v2/spanstore/writer.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/storage_v2/spanstore/writer.go b/storage_v2/spanstore/writer.go index 0b71b31b30d..cbccaf7c258 100644 --- a/storage_v2/spanstore/writer.go +++ b/storage_v2/spanstore/writer.go @@ -11,7 +11,9 @@ import ( // Writer writes spans to storage. type Writer interface { - // WriteTrace writes batches of spans at once and - // compatible with OTLP Exporter API. + // WriteTrace writes a batch of spans to storage. Idempotent. + // Implementations are not required to support atomic transactions, + // so if any of the spans fail to be written an error is returned. + // Compatible with OTLP Exporter API. WriteTraces(ctx context.Context, td ptrace.Traces) error } From 40467b06b0f07807e8dd475b2121266a3521ec24 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:30:02 +0700 Subject: [PATCH 07/17] Use OTLP trace instead of Jaeger model Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index 0c8a0065d60..1aa367c73dc 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -7,7 +7,8 @@ import ( "context" "time" - "github.com/jaegertracing/jaeger/model" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" ) // Reader finds and loads traces and other data from storage. @@ -15,7 +16,7 @@ type Reader interface { // GetTrace retrieves the trace with a given id. // // If no spans are stored for this trace, it returns ErrTraceNotFound. - GetTrace(ctx context.Context, traceID model.TraceID) (*model.Trace, error) + GetTrace(ctx context.Context, traceID pcommon.TraceID) ([]*ptrace.Traces, error) // GetServices returns all service names known to the backend from spans // within its retention period. @@ -31,13 +32,13 @@ type Reader interface { // by different spans. // // If no matching traces are found, the function returns (nil, nil). - FindTraces(ctx context.Context, query *TraceQueryParameters) ([]*model.Trace, error) + FindTraces(ctx context.Context, query *TraceQueryParameters) ([]*ptrace.Traces, error) // FindTraceIDs does the same search as FindTraces, but returns only the list // of matching trace IDs. // // If no matching traces are found, the function returns (nil, nil). - FindTraceIDs(ctx context.Context, query *TraceQueryParameters) ([]model.TraceID, error) + FindTraceIDs(ctx context.Context, query *TraceQueryParameters) ([]pcommon.TraceID, error) } // TraceQueryParameters contains parameters of a trace query. From ee732495a6fe10b5c47f175419906f1f81ae296a Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:35:12 +0700 Subject: [PATCH 08/17] Define trace not found error in spanstore pkg Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index 1aa367c73dc..ef9dcd45d82 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -7,10 +7,15 @@ import ( "context" "time" + spanstore_v1 "github.com/jaegertracing/jaeger/storage/spanstore" + "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" ) +// ErrTraceNotFound is returned by Reader's GetTrace if no data is found for given trace ID. +var ErrTraceNotFound = spanstore_v1.ErrTraceNotFound + // Reader finds and loads traces and other data from storage. type Reader interface { // GetTrace retrieves the trace with a given id. From 929288ec1a783cde53c4f07e2b7962220f805988 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:36:55 +0700 Subject: [PATCH 09/17] Fix Reader.FindTraces description typo Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index ef9dcd45d82..0ed6830eeca 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -32,7 +32,7 @@ type Reader interface { GetOperations(ctx context.Context, query OperationQueryParameters) ([]Operation, error) // FindTraces returns all traces matching query parameters. There's currently - // an implementation-dependent abiguity whether all query filters (such as + // an implementation-dependent ambiguity whether all query filters (such as // multiple tags) must apply to the same span within a trace, or can be satisfied // by different spans. // From 27451ec2b6a5b244e9abd1e6b83779dd2aeb138d Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:38:21 +0700 Subject: [PATCH 10/17] Remove proto file from this PR Signed-off-by: James Ryans --- storage_v2/proto/storage.proto | 215 --------------------------------- 1 file changed, 215 deletions(-) delete mode 100644 storage_v2/proto/storage.proto diff --git a/storage_v2/proto/storage.proto b/storage_v2/proto/storage.proto deleted file mode 100644 index afad9eff4ca..00000000000 --- a/storage_v2/proto/storage.proto +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2024 The Jaeger Authors. -// SPDX-License-Identifier: Apache-2.0 - -syntax="proto3"; - -package jaeger.storage_v2; - -import "opentelemetry/proto/collector/trace/v1/trace_service.proto"; -import "opentelemetry/proto/trace/v1/trace.proto"; -import "gogoproto/gogo.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/duration.proto"; - -import "model.proto"; - -option go_package = "storage_v2"; -option java_package = "io.jaegertracing.storage_v2"; - -// Request object to get a trace. -message GetTraceRequest { - // Hex encoded 64 or 128 bit trace ID. - string trace_id = 1; - // Optional. The start time to search trace ID. - google.protobuf.Timestamp start_time = 2 [ - (gogoproto.stdtime) = true - ]; - // Optional. The end time to search trace ID. - google.protobuf.Timestamp end_time = 3 [ - (gogoproto.stdtime) = true - ]; -} - -// Query parameters to find traces. Except for num_traces, all fields should be treated -// as forming a conjunction, e.g., "service_name='X' AND operation_name='Y' AND ...". -// All fields are matched against individual spans, not at the trace level. -// The returned results contain traces where at least one span matches the conditions. -// When num_traces results in fewer traces returned, there is no required ordering. -// -// Note: num_traces should restrict the number of traces returned, but not all backends -// interpret it this way. For instance, in Cassandra this limits the number of _spans_ -// that match the conditions, and the resulting number of traces can be less. -// -// Note: some storage implementations do not guarantee the correct implementation of all parameters. -// -message TraceQueryParameters { - string service_name = 1; - string operation_name = 2; - // Attributes are matched against Span and Resource attributes. - // At least one span in a trace must match all specified attributes. - map attributes = 3; - // Span min start time in. REST API uses RFC-3339ns format. Required. - google.protobuf.Timestamp start_time_min = 4; - // Span max start time. REST API uses RFC-3339ns format. Required. - google.protobuf.Timestamp start_time_max = 5; - // Span min duration. REST API uses Golang's time format e.g. 10s. - google.protobuf.Duration duration_min = 6; - // Span max duration. REST API uses Golang's time format e.g. 10s. - google.protobuf.Duration duration_max = 7; - - // Maximum number of traces in the response. - int32 num_traces = 8; -} - -// Request object to search traces. -message FindTracesRequest { - TraceQueryParameters query = 1; -} - -// Response object to search trace IDs. -message FindTraceIDsResponse { - // Hex encoded 64 or 128 bit trace ID. - repeated string trace_ids = 1; -} - -// Request object to get service names. -message GetServicesRequest {} - -// Response object to get service names. -message GetServicesResponse { - repeated string services = 1; -} - -// Request object to get operation names. -message GetOperationsRequest { - // Required service name. - string service = 1; - // Optional span kind. - string span_kind = 2; -} - -// Operation encapsulates information about operation. -message Operation { - string name = 1; - string span_kind = 2; -} - -// Response object to get operation names. -message GetOperationsResponse { - repeated Operation operations = 1; -} - -// Request object to archive a trace. -message ArchiveTraceRequest { - // Hex encoded 64 or 128 bit trace ID. - string trace_id = 1; -} - -// Response object to archive a trace. -message ArchiveTraceResponse { -} - -// Request object to get dependencies. -message GetDependenciesRequest { - google.protobuf.Timestamp start_time = 1 [ - (gogoproto.stdtime) = true, - (gogoproto.nullable) = false - ]; - google.protobuf.Timestamp end_time = 2 [ - (gogoproto.stdtime) = true, - (gogoproto.nullable) = false - ]; -} - -// Response object to get dependencies. -message GetDependenciesResponse { - repeated jaeger.api_v2.DependencyLink dependencies = 1 [ - (gogoproto.nullable) = false - ]; -} - -// Request object get to capabilities. -message CapabilitiesRequest { -} - -// Response object get to capabilities. -message CapabilitiesResponse { - bool archiveSpanWriter = 1; -} - -// spanstore/Writer -service TraceWriter { - // Export is a batched version of WriteSpan that handles OTLP exporter. - rpc Export(opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest) returns (opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse) {} -} - -// spanstore/Reader -service TraceReader { - // GetTrace returns a single trace. - // Note that the JSON response over HTTP is wrapped into result envelope "{"result": ...}" - // It means that the JSON response cannot be directly unmarshalled using JSONPb. - // This can be fixed by first parsing into user-defined envelope with standard JSON library - // or string manipulation to remove the envelope. Alternatively generate objects using OpenAPI. - rpc GetTrace(GetTraceRequest) returns (stream opentelemetry.proto.trace.v1.TracesData) {} - - // FindTraces searches for traces. - // See GetTrace for JSON unmarshalling. - rpc FindTraces(FindTracesRequest) returns (stream opentelemetry.proto.trace.v1.TracesData) {} - - // FindTraceIDs searches for traces and returns the traceID. - rpc FindTraceIDs(FindTracesRequest) returns (FindTraceIDsResponse) {} - - // GetServices returns service names. - rpc GetServices(GetServicesRequest) returns (GetServicesResponse) {} - - // GetOperations returns operation names. - rpc GetOperations(GetOperationsRequest) returns (GetOperationsResponse) {} -} - -// querysvc/QueryService -service TraceArchiver { - // ArchiveTrace finds a trace from primary storage and write it to archive storage. - rpc ArchiveTrace(ArchiveTraceRequest) returns (ArchiveTraceResponse) {} -} - -// dependencystore/Reader -service DependenciesReader { - // GetDependencies - rpc GetDependencies(GetDependenciesRequest) returns (GetDependenciesResponse); -} - -service PluginCapabilities { - // Capabilities returns the supported features of the server. - // Currently, it only has an archiveSpanWriter capability. - rpc Capabilities(CapabilitiesRequest) returns (CapabilitiesResponse); -} - -// Below are some helper types when using APIv3 via HTTP endpoints. - -// GRPCGatewayError is the type returned when GRPC server returns an error. -// Example: {"error":{"grpcCode":2,"httpCode":500,"message":"...","httpStatus":"text..."}}. -message GRPCGatewayError { - message GRPCGatewayErrorDetails { - int32 grpcCode = 1; - int32 httpCode = 2; - string message = 3; - string httpStatus = 4; - } - - GRPCGatewayErrorDetails error = 1; -} - -// GRPCGatewayWrapper wraps streaming responses from GetTrace/FindTraces for HTTP. -// Today there is always only one response because internally the HTTP server gets -// data from QueryService that does not support multiple responses. But in the -// future the server may return multiple responeses using Transfer-Encoding: chunked. -// In case of errors, GRPCGatewayError above is used. -// -// Example: -// {"result": {"resourceSpans": ...}} -// -// See https://github.com/grpc-ecosystem/grpc-gateway/issues/2189 -// -message GRPCGatewayWrapper { - opentelemetry.proto.trace.v1.TracesData result = 1; -} From c851fb2f0347d2211300767854b78b9925cf34be Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:42:07 +0700 Subject: [PATCH 11/17] Refactored from make fmt Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index 0ed6830eeca..5e87a39d8bb 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -7,10 +7,10 @@ import ( "context" "time" - spanstore_v1 "github.com/jaegertracing/jaeger/storage/spanstore" - "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" + + spanstore_v1 "github.com/jaegertracing/jaeger/storage/spanstore" ) // ErrTraceNotFound is returned by Reader's GetTrace if no data is found for given trace ID. From 67bd83b2e872a5e9cab5653b4ce3f3646fc17cbc Mon Sep 17 00:00:00 2001 From: James Ryans Date: Tue, 30 Apr 2024 13:56:35 +0700 Subject: [PATCH 12/17] Fix GetTrace func should return only one ptrace.Traces Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index 5e87a39d8bb..20c5f04fa87 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -21,7 +21,7 @@ type Reader interface { // GetTrace retrieves the trace with a given id. // // If no spans are stored for this trace, it returns ErrTraceNotFound. - GetTrace(ctx context.Context, traceID pcommon.TraceID) ([]*ptrace.Traces, error) + GetTrace(ctx context.Context, traceID pcommon.TraceID) (*ptrace.Traces, error) // GetServices returns all service names known to the backend from spans // within its retention period. From 04459ae6017e55069c324e9e55569a03b3bf77a7 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Wed, 1 May 2024 09:27:56 +0700 Subject: [PATCH 13/17] Change WriteTraces to accept pointer of traces Signed-off-by: James Ryans --- storage_v2/spanstore/writer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_v2/spanstore/writer.go b/storage_v2/spanstore/writer.go index cbccaf7c258..d2e6793b455 100644 --- a/storage_v2/spanstore/writer.go +++ b/storage_v2/spanstore/writer.go @@ -15,5 +15,5 @@ type Writer interface { // Implementations are not required to support atomic transactions, // so if any of the spans fail to be written an error is returned. // Compatible with OTLP Exporter API. - WriteTraces(ctx context.Context, td ptrace.Traces) error + WriteTraces(ctx context.Context, td *ptrace.Traces) error } From bc09999113e7512274d3c19293f2ee8114df6cb8 Mon Sep 17 00:00:00 2001 From: James Ryans Date: Wed, 1 May 2024 21:32:46 +0700 Subject: [PATCH 14/17] Add lifecycle methods to storage_v2.Factory Signed-off-by: James Ryans --- storage_v2/factory.go | 21 +++++++++++++++++++++ storage_v2/spanstore/factory.go | 16 +++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 storage_v2/factory.go diff --git a/storage_v2/factory.go b/storage_v2/factory.go new file mode 100644 index 00000000000..58bdfc73310 --- /dev/null +++ b/storage_v2/factory.go @@ -0,0 +1,21 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package storage_v2 + +import ( + "context" +) + +// Factory is a general factory interface to be reused across different storage factories. +// It lives within the OTEL collector extension component's lifecycle. +// The Initialize and Close functions supposed to be called from the +// OTEL component's Start and Shutdown functions. +type Factory interface { + // Initialize performs internal initialization of the factory, + // such as opening connections to the backend store. + Initialize(ctx context.Context) error + + // Close closes the resources held by the factory + Close(ctx context.Context) error +} diff --git a/storage_v2/spanstore/factory.go b/storage_v2/spanstore/factory.go index 30d08a2f87e..c0cffd825fc 100644 --- a/storage_v2/spanstore/factory.go +++ b/storage_v2/spanstore/factory.go @@ -3,16 +3,18 @@ package spanstore -// Factory defines an interface for a factory that can create implementations of different storage components. -// Implementations are also encouraged to implement plugin.Configurable interface. +import ( + "github.com/jaegertracing/jaeger/storage_v2" +) + +// Factory defines an interface for a factory that can create implementations of +// different span storage components. type Factory interface { - // Initialize performs internal initialization of the factory, such as opening connections to the backend store. - // It is called after all configuration of the factory itself has been done. - Initialize() error + storage_v2.Factory - // CreateSpanReader creates a spanstore.Reader. + // CreateTraceReader creates a spanstore.Reader. CreateTraceReader() (Reader, error) - // CreateSpanWriter creates a spanstore.Writer. + // CreateTraceWriter creates a spanstore.Writer. CreateTraceWriter() (Writer, error) } From 08fb5d725d16d0458c7cba6d463537abf43364fb Mon Sep 17 00:00:00 2001 From: James Ryans Date: Wed, 1 May 2024 22:25:16 +0700 Subject: [PATCH 15/17] Add empty test to storage_v2 pkg Signed-off-by: James Ryans --- storage_v2/empty_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 storage_v2/empty_test.go diff --git a/storage_v2/empty_test.go b/storage_v2/empty_test.go new file mode 100644 index 00000000000..1802ccdc52e --- /dev/null +++ b/storage_v2/empty_test.go @@ -0,0 +1,14 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package storage_v2 + +import ( + "testing" + + "github.com/jaegertracing/jaeger/pkg/testutils" +) + +func TestMain(m *testing.M) { + testutils.VerifyGoLeaks(m) +} From c6b2e27e5e45376121be54a995dbf56392ca8c9f Mon Sep 17 00:00:00 2001 From: James Ryans Date: Wed, 1 May 2024 22:51:21 +0700 Subject: [PATCH 16/17] Rename storage_v2.Factory to FactoryBase Signed-off-by: James Ryans --- storage_v2/factory.go | 2 +- storage_v2/spanstore/factory.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage_v2/factory.go b/storage_v2/factory.go index 58bdfc73310..e7515549e05 100644 --- a/storage_v2/factory.go +++ b/storage_v2/factory.go @@ -11,7 +11,7 @@ import ( // It lives within the OTEL collector extension component's lifecycle. // The Initialize and Close functions supposed to be called from the // OTEL component's Start and Shutdown functions. -type Factory interface { +type FactoryBase interface { // Initialize performs internal initialization of the factory, // such as opening connections to the backend store. Initialize(ctx context.Context) error diff --git a/storage_v2/spanstore/factory.go b/storage_v2/spanstore/factory.go index c0cffd825fc..3701a97ccda 100644 --- a/storage_v2/spanstore/factory.go +++ b/storage_v2/spanstore/factory.go @@ -10,7 +10,7 @@ import ( // Factory defines an interface for a factory that can create implementations of // different span storage components. type Factory interface { - storage_v2.Factory + storage_v2.FactoryBase // CreateTraceReader creates a spanstore.Reader. CreateTraceReader() (Reader, error) From 6cbd5d86f4b009a182e4fcee17713117823a805a Mon Sep 17 00:00:00 2001 From: James Ryans Date: Wed, 1 May 2024 23:30:08 +0700 Subject: [PATCH 17/17] Change spanstore Reader & Writer func back to accepts struct Signed-off-by: James Ryans --- storage_v2/spanstore/reader.go | 6 +++--- storage_v2/spanstore/writer.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage_v2/spanstore/reader.go b/storage_v2/spanstore/reader.go index 20c5f04fa87..b7e9f78ca09 100644 --- a/storage_v2/spanstore/reader.go +++ b/storage_v2/spanstore/reader.go @@ -21,7 +21,7 @@ type Reader interface { // GetTrace retrieves the trace with a given id. // // If no spans are stored for this trace, it returns ErrTraceNotFound. - GetTrace(ctx context.Context, traceID pcommon.TraceID) (*ptrace.Traces, error) + GetTrace(ctx context.Context, traceID pcommon.TraceID) (ptrace.Traces, error) // GetServices returns all service names known to the backend from spans // within its retention period. @@ -37,13 +37,13 @@ type Reader interface { // by different spans. // // If no matching traces are found, the function returns (nil, nil). - FindTraces(ctx context.Context, query *TraceQueryParameters) ([]*ptrace.Traces, error) + FindTraces(ctx context.Context, query TraceQueryParameters) ([]ptrace.Traces, error) // FindTraceIDs does the same search as FindTraces, but returns only the list // of matching trace IDs. // // If no matching traces are found, the function returns (nil, nil). - FindTraceIDs(ctx context.Context, query *TraceQueryParameters) ([]pcommon.TraceID, error) + FindTraceIDs(ctx context.Context, query TraceQueryParameters) ([]pcommon.TraceID, error) } // TraceQueryParameters contains parameters of a trace query. diff --git a/storage_v2/spanstore/writer.go b/storage_v2/spanstore/writer.go index d2e6793b455..cbccaf7c258 100644 --- a/storage_v2/spanstore/writer.go +++ b/storage_v2/spanstore/writer.go @@ -15,5 +15,5 @@ type Writer interface { // Implementations are not required to support atomic transactions, // so if any of the spans fail to be written an error is returned. // Compatible with OTLP Exporter API. - WriteTraces(ctx context.Context, td *ptrace.Traces) error + WriteTraces(ctx context.Context, td ptrace.Traces) error }