Skip to content
This repository has been archived by the owner on Jul 1, 2022. It is now read-only.

Add BaggageRestrictionManager #217

Merged
20 changes: 6 additions & 14 deletions jaeger-core/src/main/java/com/uber/jaeger/Span.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

package com.uber.jaeger;

import com.uber.jaeger.baggage.BaggageSetter;
import io.opentracing.tag.Tags;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -116,22 +117,13 @@ public List<LogData> getLogs() {

@Override
public Span setBaggageItem(String key, String value) {
if (key == null || value == null) {
return this;
}
synchronized (this) {
// TODO emit a metric whenever baggage is updated
String prevItem = this.getBaggageItem(key);
this.context = this.context.withBaggageItem(key, value);
if (context.isSampled()) {
Map<String, String> fields = new HashMap<String, String>();
fields.put("event", "baggage");
fields.put("key", key);
fields.put("value", value);
if (prevItem != null) {
fields.put("override", "true");
}
return this.log(fields);
}
context = tracer.setBaggage(this, key, value);
return this;
}
return this;
}

@Override
Expand Down
23 changes: 18 additions & 5 deletions jaeger-core/src/main/java/com/uber/jaeger/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

package com.uber.jaeger;

import com.uber.jaeger.Constants;
import com.uber.jaeger.baggage.BaggageRestrictionManager;
import com.uber.jaeger.baggage.BaggageSetter;
import com.uber.jaeger.baggage.DefaultBaggageRestrictionManager;
import com.uber.jaeger.exceptions.UnsupportedFormatException;
import com.uber.jaeger.metrics.Metrics;
import com.uber.jaeger.metrics.NullStatsReporter;
Expand Down Expand Up @@ -74,6 +76,7 @@ public class Tracer implements io.opentracing.Tracer {
private final Map<String, ?> tags;
private final boolean zipkinSharedRpcSpan;
private final ActiveSpanSource activeSpanSource;
private final BaggageSetter baggageSetter;

private Tracer(
String serviceName,
Expand All @@ -84,7 +87,8 @@ private Tracer(
Metrics metrics,
Map<String, Object> tags,
boolean zipkinSharedRpcSpan,
ActiveSpanSource activeSpanSource) {
ActiveSpanSource activeSpanSource,
BaggageRestrictionManager baggageRestrictionManager) {
this.serviceName = serviceName;
this.reporter = reporter;
this.sampler = sampler;
Expand All @@ -93,6 +97,7 @@ private Tracer(
this.metrics = metrics;
this.zipkinSharedRpcSpan = zipkinSharedRpcSpan;
this.activeSpanSource = activeSpanSource;
this.baggageSetter = new BaggageSetter(baggageRestrictionManager, metrics);

this.version = loadVersion();

Expand Down Expand Up @@ -442,12 +447,13 @@ public static final class Builder {
private final Sampler sampler;
private final Reporter reporter;
private final PropagationRegistry registry = new PropagationRegistry();
private Metrics metrics;
private Metrics metrics = new Metrics(new StatsFactoryImpl(new NullStatsReporter()));
private String serviceName;
private Clock clock = new SystemClock();
private Map<String, Object> tags = new HashMap<String, Object>();
private boolean zipkinSharedRpcSpan;
private ActiveSpanSource activeSpanSource = new ThreadLocalActiveSpanSource();
private BaggageRestrictionManager baggageRestrictionManager = new DefaultBaggageRestrictionManager();

public Builder(String serviceName, Reporter reporter, Sampler sampler) {
if (serviceName == null || serviceName.trim().length() == 0) {
Expand All @@ -456,7 +462,6 @@ public Builder(String serviceName, Reporter reporter, Sampler sampler) {
this.serviceName = serviceName;
this.reporter = reporter;
this.sampler = sampler;
this.metrics = new Metrics(new StatsFactoryImpl(new NullStatsReporter()));

TextMapCodec textMapCodec = new TextMapCodec(false);
this.registerInjector(Format.Builtin.TEXT_MAP, textMapCodec);
Expand Down Expand Up @@ -524,9 +529,14 @@ public Builder withTags(Map<String, String> tags) {
return this;
}

public Builder withBaggageRestrictionManager(BaggageRestrictionManager baggageRestrictionManager) {
this.baggageRestrictionManager = baggageRestrictionManager;
return this;
}

public Tracer build() {
return new Tracer(this.serviceName, reporter, sampler, registry, clock, metrics, tags,
zipkinSharedRpcSpan, activeSpanSource);
zipkinSharedRpcSpan, activeSpanSource, baggageRestrictionManager);
}
}

Expand Down Expand Up @@ -582,4 +592,7 @@ String getHostName() {
}
}

SpanContext setBaggage(Span span, String key, String value) {
return baggageSetter.setBaggage(span, key, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger.baggage;

/**
* BaggageRestrictionManager is an interface for a class that manages baggage
* restrictions for baggage keys. The manager will return a {@link Restriction}
* for a specific baggage key which will determine whether the baggage key is
* allowed for the current service and any other applicable restrictions on the
* baggage value.
*/
public interface BaggageRestrictionManager {
int DEFAULT_MAX_VALUE_LENGTH = 2048;

Restriction getRestriction(String service, String key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger.baggage;

import com.uber.jaeger.Span;
import com.uber.jaeger.SpanContext;
import com.uber.jaeger.metrics.Metric;
import com.uber.jaeger.metrics.Metrics;

import java.util.HashMap;
import java.util.Map;

/**
* BaggageSetter is a class that sets baggage and the logs associated
* with the baggage on a given {@link Span}.
*/
public class BaggageSetter {

private final BaggageRestrictionManager restrictionManager;
private final Metrics metrics;

public BaggageSetter(BaggageRestrictionManager restrictionManager, Metrics metrics) {
this.restrictionManager = restrictionManager;
this.metrics = metrics;
}

/**
* Sets the baggage key:value on the {@link Span} and the corresponding
* logs. Whether the baggage is set on the span depends on if the key
* is allowed to be set by this service.
* <p>
* A {@link SpanContext} is returned with the new baggage key:value set
* if key is valid, else returns the existing {@link SpanContext}
* on the {@link Span}.
*
* @param span the span to set the baggage on
* @param value the baggage value to set
* @return the SpanContext with the baggage set
*/
public SpanContext setBaggage(Span span, String key, String value) {
Restriction restriction = restrictionManager.getRestriction(span.getTracer().getServiceName(), key);
boolean truncated = false;
String prevItem = null;
if (!restriction.isKeyAllowed()) {
metrics.baggageUpdateFailure.inc(1);
logFields(span, key, value, prevItem, truncated, restriction.isKeyAllowed());
return span.context();
}
if (value.length() > restriction.getMaxValueLength()) {
truncated = true;
value = value.substring(0, restriction.getMaxValueLength());
metrics.baggageTruncate.inc(1);
}
prevItem = span.getBaggageItem(key);
logFields(span, key, value, prevItem, truncated, restriction.isKeyAllowed());
metrics.baggageUpdateSuccess.inc(1);
return span.context().withBaggageItem(key, value);
}

private void logFields(Span span, String key, String value, String prevItem, boolean truncated, boolean valid) {
if (!span.context().isSampled()) {
return;
}
Map<String, String> fields = new HashMap<String, String>();
fields.put("event", "baggage");
fields.put("key", key);
fields.put("value", value);
if (prevItem != null) {
fields.put("override", "true");
}
if (truncated) {
fields.put("truncated", "true");
}
if (!valid) {
fields.put("invalid", "true");
}
span.log(fields);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger.baggage;

/**
* DefaultBaggageRestrictionManager is a manager that returns a {@link Restriction}
* that allows all baggage.
*/
public class DefaultBaggageRestrictionManager implements BaggageRestrictionManager {
private final Restriction restriction;

public DefaultBaggageRestrictionManager() {
this(DEFAULT_MAX_VALUE_LENGTH);
}

DefaultBaggageRestrictionManager(int maxValueLength) {
this.restriction = Restriction.of(true, maxValueLength);
}

@Override
public Restriction getRestriction(String service, String key) {
return restriction;
}
}
35 changes: 35 additions & 0 deletions jaeger-core/src/main/java/com/uber/jaeger/baggage/Restriction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2017, Uber Technologies, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.uber.jaeger.baggage;

import lombok.Value;

/**
* Restriction determines whether a baggage key is allowed and contains any
* restrictions on the baggage value.
*/
@Value(staticConstructor = "of")
public class Restriction {
boolean keyAllowed;
int maxValueLength;
}
18 changes: 18 additions & 0 deletions jaeger-core/src/main/java/com/uber/jaeger/metrics/Metrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,22 @@ public static Metrics fromStatsReporter(StatsReporter reporter) {
)
// Number of times the Sampler failed to parse retrieved sampling strategy
public Counter samplerParsingFailure;

@Metric(
name = "baggage-update",
tags = {@Tag(key = "result", value = "ok")}
)
// Number of times baggage was successfully written or updated on spans
public Counter baggageUpdateSuccess;

@Metric(
name = "baggage-update",
tags = {@Tag(key = "result", value = "err")}
)
// Number of times baggage failed to write or update on spans
public Counter baggageUpdateFailure;

@Metric(name = "baggage-truncate")
// Number of times baggage was truncated as per baggage restrictions
public Counter baggageTruncate;
}
Loading