Documentation forSolarWinds Observability SaaS

Components supported by the Java Library

Verify the following to ensure the library can collect and transmit data:

  • The platform where your APM library will be installed is supported.

  • Your firewall configuration permits TCP/HTTPS/TLS outbound connections to otel.collector.xx-yy.cloud.solarwinds.com (or apm.collector.xx-yy.cloud.solarwinds.com when using legacy mode) port 443, where xx-yy is determined by the URL you use to access SolarWinds Observability SaaS, described in Data centers and endpoint URIs. See Firewall or access control requirements.

    If your firewall or access control requirements do not allow such connections, configure the library to send data through a proxy.

Because the SolarWinds Observability Java Library is a custom distro based on the OpenTelemetry Java agent, it supports the same versions, libraries, and frameworks as the OpenTelemetry agent.

For Java 8, JDK 1.8 builds 252 and above is supported.

See Supported libraries, frameworks, application servers, and JVMs in the OpenTelemetry Java Instrumentation documentation. For more information about GuideWire support, see GuideWire support.

While OTel Java does not explicitly mention Scala support, instrumenting Scala applications that run on a JVM supported by our library should work, in general. We have confirmed basic functionality on JDK 17 with Scala:2.13.10, using a Spring boot:2.7.8 and Spring web setup.

Extend the Java Library

The SolarWinds Observability Java Library can be extended with the same constructs used to extend upstream OTel agents. See the examples of extensions to the Java Library in the opentelemetry-java-instrumentation GitHub repository.

Do not replace the sampler. If you replace the sampler, data may not appear in SolarWinds Observability SaaS or may appear incorrectly.

Do not replace propagators, instead make additive changes. Replacing propagators could break distributed traces.

Once you have implemented a custom OTel component:

  1. Add a file, named for the fully qualified name of the component, to the META-INF/service/ directory. This file should contain the fully qualified name of the custom class. If there are multiple extensions of the same component, each class name should be on a new line.

  2. Build the jar.

  3. Add the extension to your Java Library by defining either an environment variable or a system variable with the path to your jar.

    Environment variable

    OTEL_JAVAAGENT_EXTENSIONS=path-to-your-jar

    System variable

    -Dotel.javaagent.extensions=path-to-your-jar

Custom exporter example

The following example adds your own custom exporter. A file io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider is added to the META-INF/service/ directory, containing the text your-package-name.CustomExporterProvider.

// ------------CustomExporterProvider.java------------
public class CustomExporterProvider implements ConfigurableSpanExporterProvider {
    public static final String EXPORTER_NAME = "custom-exporter";
    @Override
    public SpanExporter createExporter(ConfigProperties config) {
        return new CustomExporter();
    }

    @Override
    public String getName() {
        return EXPORTER_NAME;
    }
}

// ---------CustomExporter.java--------------
public class CustomExporter implements SpanExporter {
    @Override
    public CompletableResultCode export(Collection<SpanData> spans) {
        // do something
        return CompletableResultCode.ofSuccess();
    }

    @Override
    public CompletableResultCode flush() {
        // do something
        return CompletableResultCode.ofSuccess();
    }

    @Override
    public CompletableResultCode shutdown() {
        // do something
        return CompletableResultCode.ofSuccess();
    }
}

// -------------Customizer.java----------------
public class Customizer implements AutoConfigurationCustomizerProvider {

    @Override
    public void customize(AutoConfigurationCustomizer autoConfiguration) {
        autoConfiguration.addPropertiesCustomizer(configProperties -> {
            String defaultExporters = configProperties.getString("otel.traces.exporter");
            String updatedExporters = String.format("%s,%s", defaultExporters, EXPORTER_NAME); // additive
            return new HashMap<String, String>(){{put("otel.traces.exporter", updatedExporters);}};
        });
    }
}