-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[awsxrayexporter] Allow sending spans in otlp format with a new config #236
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,9 @@ package awsxrayexporter // import "github.com/open-telemetry/opentelemetry-colle | |
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/amazon-contributing/opentelemetry-collector-contrib/extension/awsmiddleware" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
|
@@ -15,6 +17,7 @@ import ( | |
"go.opentelemetry.io/collector/exporter" | ||
"go.opentelemetry.io/collector/exporter/exporterhelper" | ||
"go.opentelemetry.io/collector/pdata/ptrace" | ||
"go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" | ||
"go.uber.org/zap" | ||
|
||
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/internal/translator" | ||
|
@@ -24,7 +27,10 @@ import ( | |
) | ||
|
||
const ( | ||
maxSegmentsPerPut = int(50) // limit imposed by PutTraceSegments API | ||
maxSegmentsPerPut = int(50) // limit imposed by PutTraceSegments API | ||
otlpFormatPrefix = "T1S" // X-Ray PutTraceSegment API uses this prefix to detect the format | ||
otlpFormatKeyIndexAllAttributes = "aws.xray.exporter.config.index_all_attributes" | ||
otlpFormatKeyIndexAttributes = "aws.xray.exporter.config.indexed_attributes" | ||
) | ||
|
||
// newTracesExporter creates an exporter.Traces that converts to an X-Ray PutTraceSegments | ||
|
@@ -57,7 +63,15 @@ func newTracesExporter( | |
var err error | ||
logger.Debug("TracesExporter", typeLog, nameLog, zap.Int("#spans", td.SpanCount())) | ||
|
||
documents := extractResourceSpans(cfg, logger, td) | ||
var documents []*string | ||
if cfg.TransitSpanInOtlpFormat { | ||
documents, err = encodeOtlpAsBase64(td, cfg) | ||
if err != nil { | ||
return err | ||
} | ||
} else { // by default use xray format | ||
documents = extractResourceSpans(cfg, logger, td) | ||
} | ||
|
||
for offset := 0; offset < len(documents); offset += maxSegmentsPerPut { | ||
var nextOffset int | ||
|
@@ -137,3 +151,37 @@ func wrapErrorIfBadRequest(err error) error { | |
} | ||
return err | ||
} | ||
|
||
// encodeOtlpAsBase64 builds bytes from traces and generate base64 value for them | ||
func encodeOtlpAsBase64(td ptrace.Traces, cfg *Config) ([]*string, error) { | ||
var documents []*string | ||
for i := 0; i < td.ResourceSpans().Len(); i++ { | ||
// 1. build a new trace with one resource span | ||
singleTrace := ptrace.NewTraces() | ||
td.ResourceSpans().At(i).CopyTo(singleTrace.ResourceSpans().AppendEmpty()) | ||
|
||
// 2. append index configuration to resource span as attributes, such that X-Ray Service build indexes based on them. | ||
injectIndexConfigIntoOtlpPayload(singleTrace.ResourceSpans().At(0), cfg) | ||
|
||
// 3. Marshal single trace into proto bytes | ||
bytes, err := ptraceotlp.NewExportRequestFromTraces(singleTrace).MarshalProto() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: we can call it b instead of bytes, |
||
if err != nil { | ||
return nil, fmt.Errorf("failed to marshal traces: %w", err) | ||
} | ||
|
||
// 4. build bytes into base64 and append with PROTOCOL HEADER at the beginning | ||
base64Str := otlpFormatPrefix + base64.StdEncoding.EncodeToString(bytes) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose we are not checking the size of encoded document? Does cwagent config has translator on the batching processor config? Though I think number of spans in one resource span is configured by the batch processor inside application for instrumentation SDK https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#batch-span-processor @mxiamxia Batch processor in agent/collector only has impact on how many resource spans (which equals to documents) and exporter is already handling more than 50 documents. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah we don't check the size, would this cause any issue? I think as long as X-Ray Service can accept such size, we should be good.
I'm not aware of that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
documents = append(documents, &base64Str) | ||
} | ||
|
||
return documents, nil | ||
} | ||
|
||
func injectIndexConfigIntoOtlpPayload(resourceSpan ptrace.ResourceSpans, cfg *Config) { | ||
jefchien marked this conversation as resolved.
Show resolved
Hide resolved
|
||
attributes := resourceSpan.Resource().Attributes() | ||
attributes.PutBool(otlpFormatKeyIndexAllAttributes, cfg.IndexAllAttributes) | ||
indexAttributes := attributes.PutEmptySlice(otlpFormatKeyIndexAttributes) | ||
for _, indexAttribute := range cfg.IndexedAttributes { | ||
indexAttributes.AppendEmpty().SetStr(indexAttribute) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,9 @@ type Config struct { | |
// AWS client. | ||
MiddlewareID *component.ID `mapstructure:"middleware,omitempty"` | ||
|
||
// X-Ray Export sends spans in its original otlp format to X-Ray Service when this flag is on | ||
TransitSpanInOtlpFormat bool `mapstructure:"transit_spans_in_otlp_format,omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure this config name is accurate because strictly speaking we are not using otlp format. Server side is accepting base64 encoded protobuf binary where OTLP is passing the raw bytes are request body. I suggest we call it something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with the intention but I don't think exposing too much implementation details to users is helpful. All users need to know is that this flag enable them to send complete otlp format span to X-Ray, which contains more information than X-Ray format. Hence, i would still prefer keeping the name. |
||
|
||
// skipTimestampValidation if enabled, will skip timestamp validation logic on the trace ID | ||
skipTimestampValidation bool | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason here copy to a new trace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because I didn't find a function that takes resourcespans as the input and produce bytes. The only function i found is this
MarshalTraces
, which takes trace as the input.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to put them under traces, this is the format used by the export request protobuf.
Basically the protobuf schema has same structure for
TracesDatat
andExportTraceServiceRequest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try using
ExportTraceServiceRequest
https://opentelemetry.io/docs/specs/otlp/#binary-protobuf-encoding I think it should work as well and is closer to otlp implementation, which may have some other information in the future.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExportTraceServiceRequest is the
Orig
ofTrace
, howeverOrig
is not being exposed publicly. there's a function as below, but as you can see, it's a private function.