
com.uber.jaeger.Span Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaeger-core Show documentation
Show all versions of jaeger-core Show documentation
Jaeger Java bindings for OpenTracing API
/*
* Copyright (c) 2016, Uber Technologies, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.uber.jaeger;
import io.opentracing.tag.Tags;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Span implements io.opentracing.Span {
private static final Logger logger = LoggerFactory.getLogger(Span.class);
private final Tracer tracer;
private final long startTimeMicroseconds;
private final long startTimeNanoTicks;
private final boolean computeDurationViaNanoTicks;
private final Map tags;
private long durationMicroseconds; // span durationMicroseconds
private String operationName;
private final List references;
private SpanContext context;
private List logs;
private boolean finished = false; // to prevent the same span from getting reported multiple times
Span(
Tracer tracer,
String operationName,
SpanContext context,
long startTimeMicroseconds,
long startTimeNanoTicks,
boolean computeDurationViaNanoTicks,
Map tags,
List references) {
this.tracer = tracer;
this.operationName = operationName;
this.context = context;
this.startTimeMicroseconds = startTimeMicroseconds;
this.startTimeNanoTicks = startTimeNanoTicks;
this.computeDurationViaNanoTicks = computeDurationViaNanoTicks;
this.tags = new HashMap();
this.references = references != null ? new ArrayList(references) : null;
for (Map.Entry tag : tags.entrySet()) {
setTagAsObject(tag.getKey(), tag.getValue());
}
}
public long getStart() {
return startTimeMicroseconds;
}
public long getDuration() {
synchronized (this) {
return durationMicroseconds;
}
}
public Tracer getTracer() {
return tracer;
}
public List getReferences() {
if (references == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(references);
}
public Map getTags() {
synchronized (this) {
return Collections.unmodifiableMap(tags);
}
}
@Override
public Span setOperationName(String operationName) {
synchronized (this) {
this.operationName = operationName;
}
return this;
}
public String getOperationName() {
synchronized (this) {
return operationName;
}
}
public String getServiceName() {
synchronized (this) {
return this.getTracer().getServiceName();
}
}
public List getLogs() {
synchronized (this) {
if (logs == null) {
return null;
}
return Collections.unmodifiableList(logs);
}
}
@Override
public Span setBaggageItem(String key, String value) {
if (key == null || value == null) {
return this;
}
synchronized (this) {
context = tracer.setBaggage(this, key, value);
return this;
}
}
@Override
public String getBaggageItem(String key) {
synchronized (this) {
return this.context.getBaggageItem(key);
}
}
@Override
public String toString() {
synchronized (this) {
return context.contextAsString() + " - " + operationName;
}
}
@Override
public SpanContext context() {
synchronized (this) {
// doesn't need to be a copy since all fields are final
return context;
}
}
@Override
public void finish() {
if (computeDurationViaNanoTicks) {
long nanoDuration = tracer.clock().currentNanoTicks() - startTimeNanoTicks;
finishWithDuration(nanoDuration / 1000);
} else {
finish(tracer.clock().currentTimeMicros());
}
}
@Override
public void finish(long finishMicros) {
finishWithDuration(finishMicros - startTimeMicroseconds);
}
private void finishWithDuration(long durationMicros) {
synchronized (this) {
if (finished) {
logger.warn("Span has already been finished; will not be reported again.");
return;
}
finished = true;
this.durationMicroseconds = durationMicros;
}
if (context.isSampled()) {
tracer.reportSpan(this);
}
}
@Override
public synchronized Span setTag(String key, String value) {
return setTagAsObject(key, value);
}
@Override
public synchronized Span setTag(String key, boolean value) {
return setTagAsObject(key, value);
}
@Override
public synchronized Span setTag(String key, Number value) {
return setTagAsObject(key, value);
}
private Span setTagAsObject(String key, Object value) {
if (key.equals(Tags.SAMPLING_PRIORITY.getKey()) && (value instanceof Number)) {
int priority = ((Number) value).intValue();
byte newFlags;
if (priority > 0) {
newFlags = (byte) (context.getFlags() | SpanContext.flagSampled | SpanContext.flagDebug);
} else {
newFlags = (byte) (context.getFlags() & (~SpanContext.flagSampled));
}
context = context.withFlags(newFlags);
}
if (context.isSampled()) {
tags.put(key, value);
}
return this;
}
@Override
public Span log(Map fields) {
return log(tracer.clock().currentTimeMicros(), fields);
}
@Override
public Span log(long timestampMicroseconds, Map fields) {
synchronized (this) {
if (fields == null) {
return this;
}
if (context.isSampled()) {
if (logs == null) {
this.logs = new ArrayList();
}
logs.add(new LogData(timestampMicroseconds, fields));
}
return this;
}
}
@Override
public Span log(String event) {
return log(tracer.clock().currentTimeMicros(), event);
}
@Override
public Span log(long timestampMicroseconds, String event) {
synchronized (this) {
if (event == null) {
return this;
}
if (context.isSampled()) {
if (logs == null) {
this.logs = new ArrayList();
}
logs.add(new LogData(timestampMicroseconds, event));
}
return this;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy