![JAR search and dependency download from the Maven repository](/logo.png)
com.lightstep.opentelemetry.exporter.Adapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lightstep-opentelemetry-auto-exporter Show documentation
Show all versions of lightstep-opentelemetry-auto-exporter Show documentation
Lightstep OpenTelemetry Auto Exporter
The newest version!
package com.lightstep.opentelemetry.exporter;
import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Durations;
import com.google.protobuf.util.Timestamps;
import com.lightstep.tracer.grpc.KeyValue;
import com.lightstep.tracer.grpc.Log;
import com.lightstep.tracer.grpc.Reference;
import com.lightstep.tracer.grpc.Reference.Relationship;
import com.lightstep.tracer.grpc.Span;
import com.lightstep.tracer.grpc.SpanContext;
import io.opentelemetry.common.AttributeValue;
import io.opentelemetry.common.ReadableAttributes;
import io.opentelemetry.common.ReadableKeyValuePairs.KeyValueConsumer;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.data.SpanData.Event;
import io.opentelemetry.sdk.trace.data.SpanData.Link;
import io.opentelemetry.trace.SpanId;
import io.opentelemetry.trace.TraceId;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
/**
* Adapts OpenTelemetry objects to Lightstep objects.
*/
@ThreadSafe
final class Adapter {
static final String KEY_LOG_MESSAGE = "message";
static final String KEY_SPAN_KIND = "span.kind";
static final String KEY_SPAN_STATUS_MESSAGE = "span.status.message";
static final String KEY_SPAN_STATUS_CODE = "span.status.code";
static final String KEY_ERROR = "error";
private Adapter() {
}
/**
* Converts a list of {@link SpanData} into a collection of Lightstep's {@link Span}.
*
* @param spans the list of spans to be converted
* @param lsSpanAttributes the list of LS-specific Span attributes to add.
* @return the collection of Lightstep spans
* @see #toLightstepSpan(SpanData, Collection)
*/
static List toLightstepSpans(Collection spans,
Collection lsSpanAttributes) {
List converted = new ArrayList<>();
for (SpanData span : spans) {
converted.add(toLightstepSpan(span, lsSpanAttributes));
}
return converted;
}
/**
* Converts a single {@link SpanData} into a Lightstep's {@link Span}.
*
* @param spanData the spanData to be converted
* @param lsSpanAttributes the list of LS-specific Span attributes to add.
* @return the Lightstep span
*/
static Span toLightstepSpan(SpanData spanData, Collection lsSpanAttributes) {
final Span.Builder builder = Span.newBuilder();
builder.setOperationName(spanData.getName());
long traceId = traceIdToLong(spanData.getTraceId());
long spanId = spanIdToLong(spanData.getSpanId());
final SpanContext spanContext =
SpanContext.newBuilder().setTraceId(traceId).setSpanId(spanId).build();
builder.setSpanContext(spanContext);
final Timestamp startTimestamp = Timestamps.fromNanos(spanData.getStartEpochNanos());
final Timestamp endTimestamp = Timestamps.fromNanos(spanData.getEndEpochNanos());
builder.setStartTimestamp(startTimestamp);
builder.setDurationMicros(Durations.toMicros(Timestamps.between(startTimestamp, endTimestamp)));
builder.addAllTags(toKeyValues(spanData.getAttributes()));
builder.addAllTags(toKeyValues(spanData.getResource().getAttributes()));
if (lsSpanAttributes != null && !lsSpanAttributes.isEmpty()) {
builder.addAllTags(lsSpanAttributes);
}
builder.addAllLogs(toLightstepLogs(spanData.getEvents()));
builder.addAllReferences(toReferences(spanData.getLinks()));
// add the parent span
if (spanData.getParentSpanId().isValid()) {
final Reference.Builder referenceBuilder = Reference.newBuilder();
final long parentSpanId = spanIdToLong(spanData.getParentSpanId());
referenceBuilder.setSpanContext(
SpanContext.newBuilder().setTraceId(traceId).setSpanId(parentSpanId).build());
referenceBuilder.setRelationship(Relationship.CHILD_OF);
builder.addReferences(referenceBuilder.build());
}
if (spanData.getKind() != null) {
builder.addTags(
KeyValue.newBuilder()
.setKey(KEY_SPAN_KIND)
.setStringValue(spanData.getKind().name())
.build());
}
if (spanData.getStatus().getDescription() != null) {
builder.addTags(
KeyValue.newBuilder()
.setKey(KEY_SPAN_STATUS_MESSAGE)
.setStringValue(spanData.getStatus().getDescription())
.build());
}
builder.addTags(
KeyValue.newBuilder()
.setKey(KEY_SPAN_STATUS_CODE)
.setIntValue(spanData.getStatus().getCanonicalCode().value())
.build());
if (!spanData.getStatus().isOk()) {
builder.addTags(
KeyValue.newBuilder()
.setKey(KEY_ERROR)
.setBoolValue(true)
.build());
}
return builder.build();
}
/**
* Converts {@link Link}s into a collection of Lightstep's {@link Reference}.
*
* @param links the span's links property to be converted
* @return a collection of Lightstep span references
*/
@VisibleForTesting
static List toReferences(List links) {
final List references = new ArrayList<>();
for (Link link : links) {
references.add(toReference(link));
}
return references;
}
/**
* Converts a single {@link Link} into a Lightstep's {@link Reference}.
*
* @param link the OpenTelemetry link to be converted
* @return the Lightstep span reference
*/
@VisibleForTesting
static Reference toReference(Link link) {
final Reference.Builder builder = Reference.newBuilder();
final long traceId = traceIdToLong(link.getContext().getTraceId());
final long spanId = spanIdToLong(link.getContext().getSpanId());
builder.setSpanContext(SpanContext.newBuilder().setTraceId(traceId).setSpanId(spanId).build());
builder.setRelationship(Relationship.FOLLOWS_FROM);
return builder.build();
}
/**
* Converts {@link SpanData.Event}s into a collection of Lightstep's {@link Log}.
*
* @param timeEvents the timed events to be converted
* @return a collection of Lightstep logs
* @see #toLightstepLog(Event)
*/
@VisibleForTesting
static List toLightstepLogs(List timeEvents) {
final List logs = new ArrayList<>();
for (Event timedEvent : timeEvents) {
logs.add(toLightstepLog(timedEvent));
}
return logs;
}
/**
* Converts a {@link SpanData.Event} into Lightstep's {@link Log}.
*
* @param timedEvent the timed event to be converted
* @return a Lightstep log
*/
@VisibleForTesting
static Log toLightstepLog(Event timedEvent) {
final Log.Builder builder = Log.newBuilder();
builder.setTimestamp(Timestamps.fromNanos(timedEvent.getEpochNanos()));
builder.addFields(
KeyValue.newBuilder().setKey(KEY_LOG_MESSAGE).setStringValue(timedEvent.getName()).build());
builder.addAllFields(toKeyValues(timedEvent.getAttributes()));
return builder.build();
}
/**
* Converts a map of attributes into a collection of Lightstep's {@link KeyValue}.
*
* @param attributes the span attributes
* @return a collection of Lightstep key values
* @see #toKeyValue(String, AttributeValue)
*/
@VisibleForTesting
static List toKeyValues(ReadableAttributes attributes) {
final List keyValues = new ArrayList<>();
attributes.forEach(new KeyValueConsumer() {
@Override
public void consume(String key, AttributeValue value) {
keyValues.add(toKeyValue(key, value));
}
});
return keyValues;
}
/**
* Converts the given key and {@link AttributeValue} into Lightstep's {@link KeyValue}.
*
* @param key the entry key as string
* @param value the entry value
* @return a Lightstep key value
*/
@VisibleForTesting
static KeyValue toKeyValue(String key, AttributeValue value) {
final KeyValue.Builder builder = KeyValue.newBuilder().setKey(key);
switch (value.getType()) {
case STRING:
builder.setStringValue(value.getStringValue());
break;
case LONG:
builder.setIntValue(value.getLongValue());
break;
case BOOLEAN:
builder.setBoolValue(value.getBooleanValue());
break;
case DOUBLE:
builder.setDoubleValue(value.getDoubleValue());
break;
}
return builder.build();
}
/**
* Convert {@link TraceId} to long value.
*
* @param traceId trace id
* @return long value of trace id
*/
@VisibleForTesting
static long traceIdToLong(final TraceId traceId) {
if (traceId == null) {
return 0L;
}
final ByteString protoTraceId = toByteString(traceId);
return fromByteArray(protoTraceId.toByteArray());
}
private static ByteString toByteString(TraceId traceId) {
int traceIdSize = TraceId.getSize();
byte[] traceIdBytes = new byte[traceIdSize];
traceId.copyBytesTo(traceIdBytes, 0);
// Use the 64 least significant bits, represented by the right-most
// 8 bytes. See https://github.com/openzipkin/b3-propagation#traceid-1
return ByteString.copyFrom(traceIdBytes, traceIdSize / 2, traceIdSize / 2);
}
private static ByteString toByteString(SpanId spanId) {
byte[] spanIdBytes = new byte[SpanId.getSize()];
spanId.copyBytesTo(spanIdBytes, 0);
return ByteString.copyFrom(spanIdBytes);
}
/**
* Convert {@link SpanId} to long value.
*
* @param spanId span id
* @return long value of span id
*/
@VisibleForTesting
static long spanIdToLong(final SpanId spanId) {
if (spanId == null) {
return 0L;
}
final ByteString protoSpanId = toByteString(spanId);
return fromByteArray(protoSpanId.toByteArray());
}
private static long fromByteArray(byte[] bytes) {
return ByteBuffer.wrap(bytes).getLong();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy