Skip to content

Commit

Permalink
Merge branch 'main' into es-kind
Browse files Browse the repository at this point in the history
  • Loading branch information
Manik2708 authored Dec 24, 2024
2 parents 502dd38 + 53468aa commit 02bff1c
Show file tree
Hide file tree
Showing 34 changed files with 915 additions and 65 deletions.
7 changes: 7 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ linters-settings:
files:
- "**_test.go"

disallow-otel-contrib-translator:
deny:
- pkg: github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger
desc: "Use jptrace package instead of opentelemetry-collector-contrib/pkg/translator/jaeger"
files:
- "!**/jptrace/**"

goimports:
local-prefixes: github.com/jaegertracing/jaeger
gosec:
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ Jaeger is an open source project with open governance. We welcome contributions

## Version Compatibility Guarantees

Occasionally, CLI flags can be deprecated due to, for example, usability improvements or new functionality.
Since Jaeger uses many components from the [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector/) we try to maintain configuration compatibility between Jaeger releases. Occasionally, configuration options in Jaeger (or in Jaeger v1 CLI flags) can be deprecated due to usability improvements, new functionality, or changes in our dependencies.
In such situations, developers introducing the deprecation are required to follow [these guidelines](./CONTRIBUTING.md#deprecating-cli-flags).

In short, for a deprecated CLI flag, you should expect to see the following message in the `--help` documentation:
In short, for a deprecated configuration option, you should expect to see the following message in the documentation or release notes:
```
(deprecated, will be removed after yyyy-mm-dd or in release vX.Y.Z, whichever is later)
```

A grace period of at least **3 months** or **two minor version bumps** (whichever is later) from the first release
containing the deprecation notice will be provided before the deprecated CLI flag _can_ be deleted.
containing the deprecation notice will be provided before the deprecated configuration option _can_ be deleted.

For example, consider a scenario where v1.28.0 is released on 01-Jun-2021 containing a deprecation notice for a CLI flag.
This flag will remain in a deprecated state until the later of 01-Sep-2021 or v1.30.0 where it _can_ be removed on or after either of those events.
For example, consider a scenario where v2.0.0 is released on 01-Sep-2024 containing a deprecation notice for a configuration option.
This configuration option will remain in a deprecated state until the later of 01-Dec-2024 or v2.2.0 where it _can_ be removed on or after either of those events.
It may remain deprecated for longer than the aforementioned grace period.

## Go Version Compatibility Guarantees
Expand Down
4 changes: 2 additions & 2 deletions cmd/collector/app/handler/otlp_receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"fmt"

otlp2jaeger "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componentstatus"
"go.opentelemetry.io/collector/config/confignet"
Expand All @@ -23,6 +22,7 @@ import (

"github.com/jaegertracing/jaeger/cmd/collector/app/flags"
"github.com/jaegertracing/jaeger/cmd/collector/app/processor"
"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/pkg/tenancy"
)

Expand Down Expand Up @@ -108,7 +108,7 @@ type consumerDelegate struct {
}

func (c *consumerDelegate) consume(ctx context.Context, td ptrace.Traces) error {
batches := otlp2jaeger.ProtoFromTraces(td)
batches := jptrace.ProtoFromTraces(td)
for _, batch := range batches {
err := c.batchConsumer.consume(ctx, batch)
if err != nil {
Expand Down
7 changes: 2 additions & 5 deletions cmd/jaeger/internal/integration/span_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import (
"io"
"time"

jaeger2otlp "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configtls"
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/exporter/exportertest"
"go.opentelemetry.io/collector/exporter/otlpexporter"
"go.uber.org/zap"

"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/model"
"github.com/jaegertracing/jaeger/storage/spanstore"
)
Expand Down Expand Up @@ -68,15 +68,12 @@ func (w *spanWriter) Close() error {
}

func (w *spanWriter) WriteSpan(ctx context.Context, span *model.Span) error {
td, err := jaeger2otlp.ProtoToTraces([]*model.Batch{
td := jptrace.ProtoToTraces([]*model.Batch{
{
Spans: []*model.Span{span},
Process: span.Process,
},
})
if err != nil {
return err
}

return w.exporter.ConsumeTraces(ctx, td)
}
4 changes: 2 additions & 2 deletions cmd/jaeger/internal/processors/adaptivesampling/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"context"
"fmt"

otlp2jaeger "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/ptrace"

"github.com/jaegertracing/jaeger/cmd/collector/app/sampling/samplingstrategy"
"github.com/jaegertracing/jaeger/cmd/jaeger/internal/extension/remotesampling"
"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/internal/metrics/otelmetrics"
"github.com/jaegertracing/jaeger/plugin/sampling/strategyprovider/adaptive"
)
Expand Down Expand Up @@ -65,7 +65,7 @@ func (tp *traceProcessor) close(context.Context) error {
}

func (tp *traceProcessor) processTraces(_ context.Context, td ptrace.Traces) (ptrace.Traces, error) {
batches := otlp2jaeger.ProtoFromTraces(td)
batches := jptrace.ProtoFromTraces(td)
for _, batch := range batches {
for _, span := range batch.Spans {
if span.Process == nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/query/app/apiv3/otlp_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
package apiv3

import (
model2otel "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
"go.opentelemetry.io/collector/pdata/ptrace"

"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/model"
)

func modelToOTLP(spans []*model.Span) ptrace.Traces {
batch := &model.Batch{Spans: spans}
// there is never an error returned from ProtoToTraces
tr, _ := model2otel.ProtoToTraces([]*model.Batch{batch})
tr := jptrace.ProtoToTraces([]*model.Batch{batch})
return tr
}
4 changes: 2 additions & 2 deletions cmd/query/app/otlp_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ package app
import (
"fmt"

model2otel "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger"
"go.opentelemetry.io/collector/pdata/ptrace"

"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/model"
)

Expand All @@ -18,7 +18,7 @@ func otlp2traces(otlpSpans []byte) ([]*model.Trace, error) {
if err != nil {
return nil, fmt.Errorf("cannot unmarshal OTLP : %w", err)
}
jaegerBatches := model2otel.ProtoFromTraces(otlpTraces)
jaegerBatches := jptrace.ProtoFromTraces(otlpTraces)
var traces []*model.Trace
traceMap := make(map[model.TraceID]*model.Trace)
for _, batch := range jaegerBatches {
Expand Down
207 changes: 207 additions & 0 deletions cmd/query/app/querysvc/adjuster/clockskew.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Copyright (c) 2024 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package adjuster

import (
"fmt"
"time"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/ptrace"

"github.com/jaegertracing/jaeger/internal/jptrace"
"github.com/jaegertracing/jaeger/pkg/otelsemconv"
)

const (
warningDuplicateSpanID = "duplicate span IDs; skipping clock skew adjustment"
warningMissingParentSpanID = "parent span ID=%s is not in the trace; skipping clock skew adjustment"
warningMaxDeltaExceeded = "max clock skew adjustment delta of %v exceeded; not applying calculated delta of %v"
warningSkewAdjustDisabled = "clock skew adjustment disabled; not applying calculated delta of %v"
)

// CorrectClockSkew returns an Adjuster that corrects span timestamps for clock skew.
//
// This adjuster modifies the start and log timestamps of child spans that are
// inconsistent with their parent spans due to clock differences between hosts.
// It assumes all spans have unique IDs and should be used after SpanIDUniquifier.
//
// The adjuster determines if two spans belong to the same source by deriving a
// unique string representation of a host based on resource attributes,
// such as `host.id`, `host.ip`, or `host.name`.
// If two spans have the same host key, they are considered to be from
// the same source, and no clock skew adjustment is expected between them.
//
// Parameters:
// - maxDelta: The maximum allowable time adjustment. Adjustments exceeding
// this value will be ignored.
func CorrectClockSkew(maxDelta time.Duration) Adjuster {
return Func(func(traces ptrace.Traces) {
adjuster := &clockSkewAdjuster{
traces: traces,
maxDelta: maxDelta,
}
adjuster.buildNodesMap()
adjuster.buildSubGraphs()
for _, root := range adjuster.roots {
skew := clockSkew{hostKey: root.hostKey}
adjuster.adjustNode(root, nil, skew)
}
})
}

type clockSkewAdjuster struct {
traces ptrace.Traces
maxDelta time.Duration
spans map[pcommon.SpanID]*node
roots map[pcommon.SpanID]*node
}

type clockSkew struct {
delta time.Duration
hostKey string
}

type node struct {
span ptrace.Span
children []*node
hostKey string
}

// hostKey derives a unique string representation of a host based on resource attributes.
// This is used to determine if two spans are from the same host.
func hostKey(resource ptrace.ResourceSpans) string {
if attr, ok := resource.Resource().Attributes().Get(string(otelsemconv.HostIDKey)); ok {
return attr.Str()
}
if attr, ok := resource.Resource().Attributes().Get(string(otelsemconv.HostIPKey)); ok {
if attr.Type() == pcommon.ValueTypeStr {
return attr.Str()
} else if attr.Type() == pcommon.ValueTypeSlice {
ips := attr.Slice()
if ips.Len() > 0 {
return ips.At(0).AsString()
}
}
}
if attr, ok := resource.Resource().Attributes().Get(string(otelsemconv.HostNameKey)); ok {
return attr.Str()
}
return ""
}

// buildNodesMap creates a mapping of span IDs to their corresponding nodes.
func (a *clockSkewAdjuster) buildNodesMap() {
a.spans = make(map[pcommon.SpanID]*node)
resources := a.traces.ResourceSpans()
for i := 0; i < resources.Len(); i++ {
resource := resources.At(i)
hk := hostKey(resource)
scopes := resource.ScopeSpans()
for j := 0; j < scopes.Len(); j++ {
spans := scopes.At(j).Spans()
for k := 0; k < spans.Len(); k++ {
span := spans.At(k)
if _, exists := a.spans[span.SpanID()]; exists {
jptrace.AddWarnings(span, warningDuplicateSpanID)
} else {
a.spans[span.SpanID()] = &node{
span: span,
hostKey: hk,
}
}
}
}
}
}

// finds all spans that have no parent, i.e. where parentID is either 0
// or points to an ID for which there is no span.
func (a *clockSkewAdjuster) buildSubGraphs() {
a.roots = make(map[pcommon.SpanID]*node)
for _, n := range a.spans {
if n.span.ParentSpanID() == pcommon.NewSpanIDEmpty() {
a.roots[n.span.SpanID()] = n
continue
}
if p, ok := a.spans[n.span.ParentSpanID()]; ok {
p.children = append(p.children, n)
} else {
warning := fmt.Sprintf(warningMissingParentSpanID, n.span.ParentSpanID())
jptrace.AddWarnings(n.span, warning)
// treat spans with invalid parent ID as root spans
a.roots[n.span.SpanID()] = n
}
}
}

func (a *clockSkewAdjuster) adjustNode(n *node, parent *node, skew clockSkew) {
if (n.hostKey != skew.hostKey || n.hostKey == "") && parent != nil {
// Node n is from a different host. The parent has already been adjusted,
// so we can compare this node's timestamps against the parent.
skew = clockSkew{
hostKey: n.hostKey,
delta: a.calculateSkew(n, parent),
}
}
a.adjustTimestamps(n, skew)
for _, child := range n.children {
a.adjustNode(child, n, skew)
}
}

func (*clockSkewAdjuster) calculateSkew(child *node, parent *node) time.Duration {
parentStartTime := parent.span.StartTimestamp().AsTime()
childStartTime := child.span.StartTimestamp().AsTime()
parentEndTime := parent.span.EndTimestamp().AsTime()
childEndTime := child.span.EndTimestamp().AsTime()
parentDuration := parentEndTime.Sub(parentStartTime)
childDuration := childEndTime.Sub(childStartTime)

if childDuration > parentDuration {
// When the child lasted longer than the parent, it was either
// async or the parent may have timed out before child responded.
// The only reasonable adjustment we can do in this case is to make
// sure the child does not start before parent.
if childStartTime.Before(parentStartTime) {
return parentStartTime.Sub(childStartTime)
}
return 0
}
if !childStartTime.Before(parentStartTime) && !childEndTime.After(parentEndTime) {
// child already fits within the parent span, do not adjust
return 0
}
// Assume that network latency is equally split between req and res.
latency := (parentDuration - childDuration) / 2
// Goal: parentStartTime + latency = childStartTime + adjustment
return parentStartTime.Add(latency).Sub(childStartTime)
}

func (a *clockSkewAdjuster) adjustTimestamps(n *node, skew clockSkew) {
if skew.delta == 0 {
return
}
if absDuration(skew.delta) > a.maxDelta {
if a.maxDelta == 0 {
jptrace.AddWarnings(n.span, fmt.Sprintf(warningSkewAdjustDisabled, skew.delta))
return
}
jptrace.AddWarnings(n.span, fmt.Sprintf(warningMaxDeltaExceeded, a.maxDelta, skew.delta))
return
}
n.span.SetStartTimestamp(pcommon.NewTimestampFromTime(n.span.StartTimestamp().AsTime().Add(skew.delta)))
jptrace.AddWarnings(n.span, fmt.Sprintf("This span's timestamps were adjusted by %v", skew.delta))
for i := 0; i < n.span.Events().Len(); i++ {
event := n.span.Events().At(i)
event.SetTimestamp(pcommon.NewTimestampFromTime(event.Timestamp().AsTime().Add(skew.delta)))
}
}

func absDuration(d time.Duration) time.Duration {
if d < 0 {
return -1 * d
}
return d
}
Loading

0 comments on commit 02bff1c

Please sign in to comment.