Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

package io.opentelemetry.contrib.awsxray;

import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.common.AttributeKey;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
Expand All @@ -19,7 +19,7 @@
* #setAttributesKeysToPropagate} are not invoked, the builder defaults to using specific {@link
* AwsAttributeKeys} as propagation targets.
*/
public class AttributePropagatingSpanProcessorBuilder {
public final class AttributePropagatingSpanProcessorBuilder {

private AttributeKey<String> spanNamePropagationKey = AwsAttributeKeys.AWS_LOCAL_OPERATION;
private List<AttributeKey<String>> attributesKeysToPropagate =
Expand All @@ -43,7 +43,7 @@ public AttributePropagatingSpanProcessorBuilder setSpanNamePropagationKey(
public AttributePropagatingSpanProcessorBuilder setAttributesKeysToPropagate(
List<AttributeKey<String>> attributesKeysToPropagate) {
requireNonNull(attributesKeysToPropagate, "attributesKeysToPropagate");
this.attributesKeysToPropagate = Collections.unmodifiableList(attributesKeysToPropagate);
this.attributesKeysToPropagate = unmodifiableList(attributesKeysToPropagate);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,34 @@

package io.opentelemetry.contrib.awsxray;

import static io.opentelemetry.api.common.AttributeKey.stringKey;

import io.opentelemetry.api.common.AttributeKey;

/** Utility class holding attribute keys with special meaning to AWS components */
final class AwsAttributeKeys {

private AwsAttributeKeys() {}

static final AttributeKey<String> AWS_SPAN_KIND = AttributeKey.stringKey("aws.span.kind");
static final AttributeKey<String> AWS_SPAN_KIND = stringKey("aws.span.kind");

static final AttributeKey<String> AWS_LOCAL_SERVICE = AttributeKey.stringKey("aws.local.service");
static final AttributeKey<String> AWS_LOCAL_SERVICE = stringKey("aws.local.service");

static final AttributeKey<String> AWS_LOCAL_OPERATION =
AttributeKey.stringKey("aws.local.operation");
static final AttributeKey<String> AWS_LOCAL_OPERATION = stringKey("aws.local.operation");

static final AttributeKey<String> AWS_REMOTE_SERVICE =
AttributeKey.stringKey("aws.remote.service");
static final AttributeKey<String> AWS_REMOTE_SERVICE = stringKey("aws.remote.service");

static final AttributeKey<String> AWS_REMOTE_OPERATION =
AttributeKey.stringKey("aws.remote.operation");
static final AttributeKey<String> AWS_REMOTE_OPERATION = stringKey("aws.remote.operation");

static final AttributeKey<String> AWS_REMOTE_TARGET = AttributeKey.stringKey("aws.remote.target");
static final AttributeKey<String> AWS_REMOTE_TARGET = stringKey("aws.remote.target");

// use the same AWS Resource attribute name defined by OTel java auto-instr for aws_sdk_v_1_1
// TODO: all AWS specific attributes should be defined in semconv package and reused cross all
// otel packages. Related sim -
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/8710

static final AttributeKey<String> AWS_BUCKET_NAME = AttributeKey.stringKey("aws.bucket.name");
static final AttributeKey<String> AWS_QUEUE_NAME = AttributeKey.stringKey("aws.queue.name");
static final AttributeKey<String> AWS_STREAM_NAME = AttributeKey.stringKey("aws.stream.name");
static final AttributeKey<String> AWS_TABLE_NAME = AttributeKey.stringKey("aws.table.name");
static final AttributeKey<String> AWS_BUCKET_NAME = stringKey("aws.bucket.name");
static final AttributeKey<String> AWS_QUEUE_NAME = stringKey("aws.queue.name");
static final AttributeKey<String> AWS_STREAM_NAME = stringKey("aws.stream.name");
static final AttributeKey<String> AWS_TABLE_NAME = stringKey("aws.table.name");

private AwsAttributeKeys() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* attributes.
*/
@Immutable
public class AwsMetricAttributesSpanExporter implements SpanExporter {
public final class AwsMetricAttributesSpanExporter implements SpanExporter {

private final SpanExporter delegate;
private final MetricAttributeGenerator generator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.export.SpanExporter;

public class AwsMetricAttributesSpanExporterBuilder {
public final class AwsMetricAttributesSpanExporterBuilder {

// Defaults
private static final MetricAttributeGenerator DEFAULT_GENERATOR =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package io.opentelemetry.contrib.awsxray;

import static io.opentelemetry.api.common.AttributeKey.longKey;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleHistogram;
Expand Down Expand Up @@ -41,7 +43,7 @@
public final class AwsSpanMetricsProcessor implements SpanProcessor {

private static final AttributeKey<Long> HTTP_STATUS_CODE =
AttributeKey.longKey("http.status_code");
longKey("http.status_code");

private static final double NANOS_TO_MILLIS = 1_000_000.0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@

package io.opentelemetry.contrib.awsxray;

import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.FINE;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
Expand All @@ -29,17 +36,15 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** Remote sampler that gets sampling configuration from AWS X-Ray. */
public final class AwsXrayRemoteSampler implements Sampler, Closeable {

static final long DEFAULT_TARGET_INTERVAL_NANOS = TimeUnit.SECONDS.toNanos(10);
static final long DEFAULT_TARGET_INTERVAL_NANOS = SECONDS.toNanos(10);

private static final Logger logger = Logger.getLogger(AwsXrayRemoteSampler.class.getName());

Expand Down Expand Up @@ -134,26 +139,25 @@ private void getAndUpdateSampler() {
initialSampler,
response.getSamplingRules().stream()
.map(SamplingRuleRecord::getRule)
.collect(Collectors.toList())));
.collect(toList())));

previousRulesResponse = response;
ScheduledFuture<?> existingFetchTargetsFuture = fetchTargetsFuture;
if (existingFetchTargetsFuture != null) {
existingFetchTargetsFuture.cancel(false);
}
fetchTargetsFuture =
executor.schedule(
this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS);
executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS);
}
} catch (Throwable t) {
logger.log(Level.FINE, "Failed to update sampler", t);
logger.log(FINE, "Failed to update sampler", t);
}
scheduleSamplerUpdate();
}

private void scheduleSamplerUpdate() {
long delay = pollingIntervalNanos + jitterNanos.next();
pollFuture = executor.schedule(this::getAndUpdateSampler, delay, TimeUnit.NANOSECONDS);
pollFuture = executor.schedule(this::getAndUpdateSampler, delay, NANOSECONDS);
}

/**
Expand All @@ -168,7 +172,7 @@ Duration getNextSamplerUpdateScheduledDuration() {
if (pollFuture == null) {
return null;
}
return Duration.ofNanos(pollFuture.getDelay(TimeUnit.NANOSECONDS));
return Duration.ofNanos(pollFuture.getDelay(NANOSECONDS));
}

private void fetchTargets() {
Expand All @@ -181,28 +185,25 @@ private void fetchTargets() {
Date now = Date.from(Instant.ofEpochSecond(0, clock.now()));
List<SamplingStatisticsDocument> statistics = xrayRulesSampler.snapshot(now);
Set<String> requestedTargetRuleNames =
statistics.stream()
.map(SamplingStatisticsDocument::getRuleName)
.collect(Collectors.toSet());
statistics.stream().map(SamplingStatisticsDocument::getRuleName).collect(toSet());

GetSamplingTargetsResponse response =
client.getSamplingTargets(GetSamplingTargetsRequest.create(statistics));
Map<String, SamplingTargetDocument> targets =
response.getDocuments().stream()
.collect(Collectors.toMap(SamplingTargetDocument::getRuleName, Function.identity()));
.collect(toMap(SamplingTargetDocument::getRuleName, Function.identity()));
updateInternalSamplers(xrayRulesSampler.withTargets(targets, requestedTargetRuleNames, now));
} catch (Throwable t) {
// Might be a transient API failure, try again after a default interval.
fetchTargetsFuture =
executor.schedule(
this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS);
executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS);
return;
}

long nextTargetFetchIntervalNanos =
xrayRulesSampler.nextTargetFetchTimeNanos() - clock.nanoTime();
fetchTargetsFuture =
executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, TimeUnit.NANOSECONDS);
executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, NANOSECONDS);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package io.opentelemetry.contrib.awsxray;

import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.sdk.common.Clock;
Expand All @@ -26,7 +28,7 @@ public final class AwsXrayRemoteSamplerBuilder {
private Clock clock = Clock.getDefault();
private String endpoint = DEFAULT_ENDPOINT;
@Nullable private Sampler initialSampler;
private long pollingIntervalNanos = TimeUnit.SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS);
private long pollingIntervalNanos = SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS);

AwsXrayRemoteSamplerBuilder(Resource resource) {
this.resource = resource;
Expand All @@ -51,7 +53,7 @@ public AwsXrayRemoteSamplerBuilder setEndpoint(String endpoint) {
@CanIgnoreReturnValue
public AwsXrayRemoteSamplerBuilder setPollingInterval(Duration delay) {
requireNonNull(delay, "delay");
return setPollingInterval(delay.toNanos(), TimeUnit.NANOSECONDS);
return setPollingInterval(delay.toNanos(), NANOSECONDS);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import java.util.Map;

@AutoService(ConfigurableSamplerProvider.class)
public class AwsXrayRemoteSamplerProvider implements ConfigurableSamplerProvider {
public final class AwsXrayRemoteSamplerProvider implements ConfigurableSamplerProvider {

@Override
public Sampler createSampler(ConfigProperties config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

package io.opentelemetry.contrib.awsxray;

import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
import static java.util.concurrent.TimeUnit.SECONDS;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
Expand All @@ -23,12 +27,10 @@
import io.opentelemetry.semconv.ServerAttributes;
import io.opentelemetry.semconv.UrlAttributes;
import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand All @@ -38,25 +40,23 @@ final class SamplingRuleApplier {

// copied from AwsIncubatingAttributes
private static final AttributeKey<String> AWS_ECS_CONTAINER_ARN =
AttributeKey.stringKey("aws.ecs.container.arn");
stringKey("aws.ecs.container.arn");
// copied from CloudIncubatingAttributes
private static final AttributeKey<String> CLOUD_PLATFORM =
AttributeKey.stringKey("cloud.platform");
private static final AttributeKey<String> CLOUD_RESOURCE_ID =
AttributeKey.stringKey("cloud.resource_id");
private static final AttributeKey<String> CLOUD_PLATFORM = stringKey("cloud.platform");
private static final AttributeKey<String> CLOUD_RESOURCE_ID = stringKey("cloud.resource_id");
// copied from CloudIncubatingAttributes.CloudPlatformIncubatingValues
public static final String AWS_EC2 = "aws_ec2";
public static final String AWS_ECS = "aws_ecs";
public static final String AWS_EKS = "aws_eks";
public static final String AWS_LAMBDA = "aws_lambda";
public static final String AWS_ELASTIC_BEANSTALK = "aws_elastic_beanstalk";
// copied from HttpIncubatingAttributes
private static final AttributeKey<String> HTTP_HOST = AttributeKey.stringKey("http.host");
private static final AttributeKey<String> HTTP_METHOD = AttributeKey.stringKey("http.method");
private static final AttributeKey<String> HTTP_TARGET = AttributeKey.stringKey("http.target");
private static final AttributeKey<String> HTTP_URL = AttributeKey.stringKey("http.url");
private static final AttributeKey<String> HTTP_HOST = stringKey("http.host");
private static final AttributeKey<String> HTTP_METHOD = stringKey("http.method");
private static final AttributeKey<String> HTTP_TARGET = stringKey("http.target");
private static final AttributeKey<String> HTTP_URL = stringKey("http.url");
// copied from NetIncubatingAttributes
private static final AttributeKey<String> NET_HOST_NAME = AttributeKey.stringKey("net.host.name");
private static final AttributeKey<String> NET_HOST_NAME = stringKey("net.host.name");

private static final Map<String, String> XRAY_CLOUD_PLATFORM;

Expand All @@ -71,7 +71,7 @@ final class SamplingRuleApplier {
xrayCloudPlatform.put(AWS_EKS, "AWS::EKS::Container");
xrayCloudPlatform.put(AWS_ELASTIC_BEANSTALK, "AWS::ElasticBeanstalk::Environment");
xrayCloudPlatform.put(AWS_LAMBDA, "AWS::Lambda::Function");
XRAY_CLOUD_PLATFORM = Collections.unmodifiableMap(xrayCloudPlatform);
XRAY_CLOUD_PLATFORM = unmodifiableMap(xrayCloudPlatform);
}

private final String clientId;
Expand Down Expand Up @@ -127,7 +127,7 @@ final class SamplingRuleApplier {
fixedRateSampler = createFixedRate(rule.getFixedRate());

if (rule.getAttributes().isEmpty()) {
attributeMatchers = Collections.emptyMap();
attributeMatchers = emptyMap();
} else {
attributeMatchers =
rule.getAttributes().entrySet().stream()
Expand Down Expand Up @@ -317,7 +317,7 @@ SamplingRuleApplier withTarget(SamplingTargetDocument target, Date now) {
}
long intervalNanos =
target.getIntervalSecs() != null
? TimeUnit.SECONDS.toNanos(target.getIntervalSecs())
? SECONDS.toNanos(target.getIntervalSecs())
: AwsXrayRemoteSampler.DEFAULT_TARGET_INTERVAL_NANOS;
long newNextSnapshotTimeNanos = clock.nanoTime() + intervalNanos;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package io.opentelemetry.contrib.awsxray;

import static java.util.logging.Level.FINE;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
Expand Down Expand Up @@ -84,7 +86,7 @@ public SamplingResult shouldSample(
// In practice, X-Ray always returns a Default rule that matches all requests so it is a bug in
// our code or X-Ray to reach here, fallback just in case.
logger.log(
Level.FINE,
FINE,
"No sampling rule matched the request. "
+ "This is a bug in either the OpenTelemetry SDK or X-Ray.");
return fallbackSampler.shouldSample(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* Unit tests for {@link ResourceHolder}. Note that there isn't a great way to test the "default"
* fallback logic, as when the test suite is run, the customize logic appears to be invoked.
*/
public class ResourceHolderTest {
class ResourceHolderTest {

@Test
@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

package io.opentelemetry.contrib.awsxray;

import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.TraceId;
Expand Down Expand Up @@ -175,7 +175,7 @@ private static SamplingResult doSample(Sampler sampler, String name) {
TraceId.fromLongs(1, 2),
name,
SpanKind.CLIENT,
Attributes.of(AttributeKey.stringKey("test"), name),
Attributes.of(stringKey("test"), name),
Collections.emptyList());
}
}