Skip to content

Commit

Permalink
NH-93486: export traces using otlp
Browse files Browse the repository at this point in the history
  • Loading branch information
cleverchuk committed Nov 8, 2024
1 parent c85404d commit 4756f1c
Show file tree
Hide file tree
Showing 15 changed files with 364 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.solarwinds.opentelemetry.extensions;

import com.google.auto.service.AutoService;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.resources.Resource;

@AutoService(ResourceProvider.class)
public class ApmResource implements ResourceProvider {
public static final AttributeKey<String> moduleKey = AttributeKey.stringKey("sw.data.module");

public static final AttributeKey<String> versionKey = AttributeKey.stringKey("sw.apm.version");

@Override
public Resource createResource(ConfigProperties configProperties) {
Attributes resourceAttributes =
Attributes.of(moduleKey, "apm", versionKey, BuildConfig.SOLARWINDS_AGENT_VERSION);
return Resource.create(resourceAttributes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

package com.solarwinds.opentelemetry.extensions;

import static com.solarwinds.opentelemetry.extensions.SharedNames.LAYER_NAME_PLACEHOLDER;
import static com.solarwinds.opentelemetry.extensions.SharedNames.TRANSACTION_NAME_KEY;

import com.solarwinds.joboe.logging.Logger;
import com.solarwinds.joboe.logging.LoggerFactory;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.metrics.LongHistogram;
Expand Down Expand Up @@ -116,7 +118,12 @@ public void onEnding(ReadWriteSpan span) {
final SpanContext parentSpanContext = spanData.getParentSpanContext();
if (!parentSpanContext.isValid() || parentSpanContext.isRemote()) {
span.setAttribute(TRANSACTION_NAME_KEY, TransactionNameManager.getTransactionName(spanData));
span.setAttribute(AttributeKey.stringKey(
"TransactionName"), TransactionNameManager.getTransactionName(spanData));
}

span.setAttribute(
"Layer", String.format(LAYER_NAME_PLACEHOLDER, span.getKind(), span.getName().trim()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ public class ResourceCustomizer implements BiFunction<Resource, ConfigProperties

@Override
public Resource apply(Resource resource, ConfigProperties configProperties) {
ResourceBuilder resourceBuilder =
resource.toBuilder()
.put("sw.data.module", "apm")
.put("sw.apm.version", BuildConfig.SOLARWINDS_AGENT_VERSION);
ResourceBuilder resourceBuilder = resource.toBuilder();
String resourceAttribute = resource.getAttribute(ResourceAttributes.PROCESS_COMMAND_LINE);
List<String> processArgs = resource.getAttribute(ResourceAttributes.PROCESS_COMMAND_ARGS);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.solarwinds.opentelemetry.extensions;

import static com.solarwinds.opentelemetry.extensions.ApmResource.moduleKey;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ApmResourceTest {
@InjectMocks private ApmResource apmResource;

@Test
void testCreateResource() {
Resource resource =
apmResource.createResource(DefaultConfigProperties.create(Collections.emptyMap()));
String module = resource.getAttribute(moduleKey);
String version = resource.getAttribute(moduleKey);

assertNotNull(module);
assertNotNull(version);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import static org.junit.jupiter.api.Assertions.*;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.resources.Resource;
Expand Down Expand Up @@ -100,19 +99,4 @@ void verifyThatProcessCommandLineIsNotModifiedWhenServiceKeyIsNotPresentProcessC
Arrays.asList("-Duser.country=US", "-Duser.language=en"),
actual.getAttribute(ResourceAttributes.PROCESS_COMMAND_ARGS));
}

@Test
void verifyAgentVersionIsAddedToResource() {
Resource resource =
Resource.create(
Attributes.builder()
.put(
ResourceAttributes.PROCESS_COMMAND_ARGS,
Arrays.asList("-Duser.country=US", "-Duser.language=en"))
.build());
Resource actual =
tested.apply(resource, DefaultConfigProperties.create(Collections.emptyMap()));

assertNotNull(actual.getAttribute(AttributeKey.stringKey("sw.apm.version")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.
*/

/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.
*/

/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.solarwinds.opentelemetry.extensions;

import com.google.auto.service.AutoService;
import com.solarwinds.joboe.core.HostId;
import com.solarwinds.joboe.core.util.ServerHostInfoReader;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.semconv.ResourceAttributes;
import java.util.function.BiConsumer;

@AutoService(ResourceProvider.class)
public class HostIdResourceProvider implements ResourceProvider {

@Override
public Resource createResource(ConfigProperties configProperties) {
AttributesBuilder builder = Attributes.builder();

HostId hostId = ServerHostInfoReader.INSTANCE.getHostId();
setIfNotNull(builder::put, ResourceAttributes.HOST_NAME, hostId.getHostname());
setIfNotNull(
builder::put, ResourceAttributes.CLOUD_AVAILABILITY_ZONE, hostId.getEc2AvailabilityZone());
setIfNotNull(builder::put, ResourceAttributes.HOST_ID, hostId.getEc2InstanceId());

setIfNotNull(builder::put, ResourceAttributes.CONTAINER_ID, hostId.getDockerContainerId());
setIfNotNull(builder::put, ResourceAttributes.PROCESS_PID, (long) hostId.getPid());
setIfNotNull(
builder::put, AttributeKey.stringArrayKey("mac.addresses"), hostId.getMacAddresses());

setIfNotNull(
builder::put,
AttributeKey.stringKey("azure.app.service.instance.id"),
hostId.getAzureAppServiceInstanceId());
setIfNotNull(builder::put, ResourceAttributes.HOST_ID, hostId.getHerokuDynoId());
setIfNotNull(
builder::put, AttributeKey.stringKey("sw.uams.client.id"), hostId.getUamsClientId());
setIfNotNull(builder::put, AttributeKey.stringKey("uuid"), hostId.getUuid());

HostId.K8sMetadata k8sMetadata = hostId.getK8sMetadata();
if (k8sMetadata != null) {
setIfNotNull(builder::put, ResourceAttributes.K8S_POD_UID, k8sMetadata.getPodUid());
setIfNotNull(builder::put, ResourceAttributes.K8S_NAMESPACE_NAME, k8sMetadata.getNamespace());
setIfNotNull(builder::put, ResourceAttributes.K8S_POD_NAME, k8sMetadata.getPodName());
}

HostId.AwsMetadata awsMetadata = hostId.getAwsMetadata();
if (awsMetadata != null) {
setIfNotNull(builder::put, ResourceAttributes.HOST_ID, awsMetadata.getHostId());
setIfNotNull(builder::put, ResourceAttributes.HOST_NAME, awsMetadata.getHostName());
setIfNotNull(builder::put, ResourceAttributes.CLOUD_PROVIDER, awsMetadata.getCloudProvider());

setIfNotNull(
builder::put, ResourceAttributes.CLOUD_ACCOUNT_ID, awsMetadata.getCloudAccountId());
setIfNotNull(builder::put, ResourceAttributes.CLOUD_PLATFORM, awsMetadata.getCloudPlatform());
setIfNotNull(
builder::put,
ResourceAttributes.CLOUD_AVAILABILITY_ZONE,
awsMetadata.getCloudAvailabilityZone());

setIfNotNull(builder::put, ResourceAttributes.CLOUD_REGION, awsMetadata.getCloudRegion());
setIfNotNull(builder::put, ResourceAttributes.HOST_IMAGE_ID, awsMetadata.getHostImageId());
setIfNotNull(builder::put, ResourceAttributes.HOST_TYPE, awsMetadata.getHostType());
}

HostId.AzureVmMetadata azureVmMetadata = hostId.getAzureVmMetadata();
if (azureVmMetadata != null) {
setIfNotNull(builder::put, ResourceAttributes.HOST_ID, azureVmMetadata.getHostId());
setIfNotNull(builder::put, ResourceAttributes.HOST_NAME, azureVmMetadata.getHostName());
setIfNotNull(
builder::put, ResourceAttributes.CLOUD_PROVIDER, azureVmMetadata.getCloudProvider());

setIfNotNull(
builder::put, ResourceAttributes.CLOUD_ACCOUNT_ID, azureVmMetadata.getCloudAccountId());
setIfNotNull(
builder::put, ResourceAttributes.CLOUD_PLATFORM, azureVmMetadata.getCloudPlatform());
setIfNotNull(builder::put, ResourceAttributes.CLOUD_REGION, azureVmMetadata.getCloudRegion());

setIfNotNull(
builder::put, AttributeKey.stringKey("azure.vm.name"), azureVmMetadata.getAzureVmName());
setIfNotNull(
builder::put, AttributeKey.stringKey("azure.vm.size"), azureVmMetadata.getAzureVmSize());
setIfNotNull(
builder::put,
AttributeKey.stringKey("azure.resource.group.name"),
azureVmMetadata.getAzureResourceGroupName());

setIfNotNull(
builder::put,
AttributeKey.stringKey("azure.vm.scale.set.name"),
azureVmMetadata.getAzureVmScaleSetName());
}

return Resource.create(builder.build());
}

private <V> void setIfNotNull(
BiConsumer<AttributeKey<V>, V> setter, AttributeKey<V> key, V value) {
if (value != null) {
setter.accept(key, value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ protected MetricsMonitor buildMetricsMonitor() {
*/
private void reportInit() {
try {
if (ConfigurationLoader.shouldUseOtlpForTraces()) {
return;
}
reportLayerInit();
} catch (Exception e) {
logger.warn("Failed to post init message: " + (e.getMessage() != null ? e.getMessage() : e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public class SolarwindsPropertiesSupplier implements Supplier<Map<String, String

static {
if (isAgentEnabled()) {
PROPERTIES.put("otel.traces.exporter", COMPONENT_NAME);
PROPERTIES.put("otel.metrics.exporter", "none");
PROPERTIES.put("otel.logs.exporter", "none");
PROPERTIES.put("otel.propagators", String.format("tracecontext,baggage,%s", COMPONENT_NAME));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,33 +84,10 @@ public CompletableResultCode export(@Nonnull Collection<SpanData> collection) {
entryEvent = new EventImpl(null, w3cContext, false);
}

if (!spanData.getParentSpanContext().isValid()
|| spanData.getParentSpanContext().isRemote()) { // then a root span of this service
String transactionName =
spanData
.getAttributes()
.get(
AttributeKey.stringKey(
"TransactionName")); // check if there's transaction name set as
// attribute
if (transactionName == null) {
transactionName = TransactionNameManager.getTransactionName(spanData);
if (transactionName != null) {
entryEvent.addInfo(
"TransactionName",
transactionName); // only do this if we are generating a transaction name here.
// If it's already in attributes, it will be inserted by
// addInfo(getTags...)
}
}
}

InstrumentationScopeInfo scopeInfo = spanData.getInstrumentationScopeInfo();
entryEvent.addInfo(
"Label",
"entry",
"Layer",
spanName,
"sw.span_kind",
spanData.getKind().toString(),
"otel.scope.name",
Expand Down
Loading

0 comments on commit 4756f1c

Please sign in to comment.