Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NH-94685: capture stacktrace for span #288

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .github/workflows/rlscan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
permissions:
contents: read

env:
GITHUB_USERNAME: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
reversing_lab_scan_agent:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ subprojects {
opentelemetryJavaagent: property('otel.agent.version'),
bytebuddy : "1.15.10",
guava : "30.1-jre",
joboe : "10.0.15",
joboe : "10.0.16",
agent : swoVersion, // the custom distro agent version
autoservice : "1.0.1",
caffeine : "2.9.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class LambdaConfigurationLoader {
ConfigProperty.AGENT_TRIGGER_TRACE_ENABLED.setParser(ModeStringToBooleanParser.INSTANCE);
ConfigProperty.AGENT_TRANSACTION_NAMING_SCHEMES.setParser(new TransactionNamingSchemesParser());
ConfigProperty.AGENT_SQL_TAG_DATABASES.setParser(new SqlTagDatabasesParser());
ConfigProperty.AGENT_SPAN_STACK_TRACE_FILTERS.setParser(new StackTraceFilterParser());
}

public static void load() throws InvalidConfigException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.solarwinds.opentelemetry.extensions;

import static com.solarwinds.opentelemetry.extensions.SharedNames.COMPONENT_NAME;
import static com.solarwinds.opentelemetry.extensions.SharedNames.SPAN_STACKTRACE_FILTER_CLASS;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -30,6 +31,8 @@ public PropertiesSupplier() {
defaultProperties.put(
"otel.propagators", String.format("tracecontext,baggage,%s,xray", COMPONENT_NAME));
defaultProperties.put("otel.instrumentation.runtime-telemetry.enabled", "false");
defaultProperties.put(
"otel.java.experimental.span-stacktrace.filter", SPAN_STACKTRACE_FILTER_CLASS);
defaultProperties.put("otel.exporter.otlp.protocol", "grpc");
}

Expand Down
3 changes: 3 additions & 0 deletions custom/shared/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ dependencies {
implementation "org.json:json:${versions.json}"
implementation "com.google.code.gson:gson:2.10.1"
implementation "com.github.ben-manes.caffeine:caffeine:${versions.caffeine}"
implementation("io.opentelemetry.contrib:opentelemetry-span-stacktrace:${property('otel.java.contrib.version')}") {
exclude(module: "opentelemetry-sdk", group: "io.opentelemetry") // the agent includes this
}

testImplementation("org.json:json:${versions.json}")
testImplementation "com.solarwinds.joboe:sampling:${versions.joboe}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ private SharedNames() {}

public static String TRANSACTION_NAME_KEY = "sw.transaction";

public static String SPAN_STACKTRACE_FILTER_CLASS =
"com.solarwinds.opentelemetry.extensions.SpanStacktraceFilter";

// This is visible to customer via span layer and can be used to configure transaction
// filtering setting.
public static final String LAYER_NAME_PLACEHOLDER = "%s:%s";
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 io.opentelemetry.api.common.AttributeKey.stringKey;

import com.solarwinds.joboe.config.ConfigManager;
import com.solarwinds.joboe.config.ConfigProperty;
import io.opentelemetry.sdk.trace.ReadableSpan;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

public class SpanStacktraceFilter implements Predicate<ReadableSpan> {
private static final Set<String> filterAttributes = new HashSet<>();

static {
filterAttributes.add("db.system");
Set<String> configuredFilterAttributes =
ConfigManager.getConfigOptional(
ConfigProperty.AGENT_SPAN_STACK_TRACE_FILTERS, filterAttributes);
filterAttributes.addAll(configuredFilterAttributes);
}

@Override
public boolean test(ReadableSpan readableSpan) {
return filterAttributes.stream()
.anyMatch(attr -> readableSpan.getAttribute(stringKey(attr)) != null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* © 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.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.solarwinds.joboe.config.ConfigParser;
import com.solarwinds.joboe.config.InvalidConfigException;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public final class StackTraceFilterParser implements ConfigParser<String, Set<String>> {
private static final Gson gson = new GsonBuilder().create();

@Override
public Set<String> convert(String input) throws InvalidConfigException {
try {
if (input.startsWith("[")) {
Type type = new TypeToken<Set<String>>() {}.getType();
return gson.fromJson(input, type);
}
return Arrays.stream(input.split(",")).map(String::trim).collect(Collectors.toSet());
} catch (JsonSyntaxException e) {
throw new InvalidConfigException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* © 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 org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import io.opentelemetry.sdk.trace.ReadableSpan;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class SpanStacktraceFilterTest {

@InjectMocks private SpanStacktraceFilter tested;

@Mock private ReadableSpan readableSpanMock;

@Test
void returnTrueWhenAttributeHasValue() {
when(readableSpanMock.getAttribute(any())).thenReturn("test-value");
assertTrue(tested.test(readableSpanMock));
}

@Test
void returnFalseWhenAttributeHasNoValue() {
assertFalse(tested.test(readableSpanMock));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* © 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 org.junit.jupiter.api.Assertions.assertEquals;

import com.solarwinds.joboe.config.InvalidConfigException;
import java.util.HashSet;
import java.util.Set;
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 StackTraceFilterParserTest {

@InjectMocks private StackTraceFilterParser tested;

@Test
void returnListOfStringGivenCommaSeparatedString() throws InvalidConfigException {
String input = "name, status";
Set<String> expected = new HashSet<>();
expected.add("name");

expected.add("status");
assertEquals(expected, tested.convert(input));
}

@Test
void returnListOfStringGivenJsonList() throws InvalidConfigException {
String input = "[\"name\",\"status\"]";
Set<String> expected = new HashSet<>();
expected.add("name");

expected.add("status");
assertEquals(expected, tested.convert(input));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.solarwinds.opentelemetry.extensions;

import static com.solarwinds.opentelemetry.extensions.SharedNames.COMPONENT_NAME;
import static com.solarwinds.opentelemetry.extensions.SharedNames.SPAN_STACKTRACE_FILTER_CLASS;
import static com.solarwinds.opentelemetry.extensions.initialize.AutoConfigurationCustomizerProviderImpl.isAgentEnabled;

import java.util.HashMap;
Expand All @@ -31,6 +32,8 @@ public class SolarwindsPropertiesSupplier implements Supplier<Map<String, String
if (isAgentEnabled()) {
PROPERTIES.put("otel.metrics.exporter", "none");
PROPERTIES.put("otel.logs.exporter", "none");

PROPERTIES.put("otel.java.experimental.span-stacktrace.filter", SPAN_STACKTRACE_FILTER_CLASS);
PROPERTIES.put("otel.propagators", String.format("tracecontext,baggage,%s", COMPONENT_NAME));
} else {
PROPERTIES.put("otel.sdk.disabled", "true");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.solarwinds.opentelemetry.extensions.NamingScheme;
import com.solarwinds.opentelemetry.extensions.RangeValidationParser;
import com.solarwinds.opentelemetry.extensions.SqlTagDatabasesParser;
import com.solarwinds.opentelemetry.extensions.StackTraceFilterParser;
import com.solarwinds.opentelemetry.extensions.TracingModeParser;
import com.solarwinds.opentelemetry.extensions.TransactionNameManager;
import com.solarwinds.opentelemetry.extensions.TransactionNamingScheme;
Expand Down Expand Up @@ -101,6 +102,7 @@ public class ConfigurationLoader {
ConfigProperty.PROFILER.setParser(ProfilerSettingParser.INSTANCE);
ConfigProperty.AGENT_TRANSACTION_NAMING_SCHEMES.setParser(new TransactionNamingSchemesParser());
ConfigProperty.AGENT_SQL_TAG_DATABASES.setParser(new SqlTagDatabasesParser());
ConfigProperty.AGENT_SPAN_STACK_TRACE_FILTERS.setParser(new StackTraceFilterParser());
}

public static void load() throws InvalidConfigException {
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ systemProp.org.gradle.internal.repository.max.retries=10
systemProp.org.gradle.internal.repository.initial.backoff=500

# Project properties provides a central place for shared property among subprojects
swo.agent.version=2.10.0
otel.agent.version=2.10.0
otel.sdk.version=1.44.1
swo.agent.version=2.10.0
otel.java.contrib.version=1.41.0-alpha

This file was deleted.

Loading
Loading