Skip to content

Commit

Permalink
Telemetry exporter config (opensearch-project#8624)
Browse files Browse the repository at this point in the history
* Makes exporter configurable

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Makes exporter configurable

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Makes exporter configurable

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Makes exporter configurable

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Makes exporter configurable

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Add logs for successful instantiation

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Move settings to OtelTelemetrySettings

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Move settings to OtelTelemetrySettings

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Move settings to OtelTelemetrySettings

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Add test cases

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Fix test cases

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Empty-Commit

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Empty-Commit

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* Fix test cases

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* refactor

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* refactor

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

* refactor

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>

---------

Signed-off-by: Gagan Juneja <gjjuneja@amazon.com>
Signed-off-by: Gagan Juneja <gagandeepjuneja@gmail.com>
Co-authored-by: Gagan Juneja <gjjuneja@amazon.com>
Signed-off-by: sahil buddharaju <sahilbud@amazon.com>
  • Loading branch information
2 people authored and sahil buddharaju committed Jul 18, 2023
1 parent bcfb779 commit 7c8dcf2
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Pass localNode info to all plugins on node start ([#7919](https://github.com/opensearch-project/OpenSearch/pull/7919))
- Improved performance of parsing floating point numbers ([#7909](https://github.com/opensearch-project/OpenSearch/pull/7909))
- Move span actions to Scope ([#8411](https://github.com/opensearch-project/OpenSearch/pull/8411))
- Make Span exporter configurable ([#8620](https://github.com/opensearch-project/OpenSearch/issues/8620))
- Add wrapper tracer implementation

### Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.plugins.Plugin;
import org.opensearch.plugins.TelemetryPlugin;
import org.opensearch.telemetry.metrics.MetricsTelemetry;
Expand All @@ -29,36 +28,6 @@ public class OTelTelemetryPlugin extends Plugin implements TelemetryPlugin {

static final String OTEL_TRACER_NAME = "otel";

/**
* span exporter batch size
*/
public static final Setting<Integer> TRACER_EXPORTER_BATCH_SIZE_SETTING = Setting.intSetting(
"telemetry.otel.tracer.exporter.batch_size",
512,
1,
Setting.Property.NodeScope,
Setting.Property.Dynamic
);
/**
* span exporter max queue size
*/
public static final Setting<Integer> TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING = Setting.intSetting(
"telemetry.otel.tracer.exporter.max_queue_size",
2048,
1,
Setting.Property.NodeScope,
Setting.Property.Dynamic
);
/**
* span exporter delay in seconds
*/
public static final Setting<TimeValue> TRACER_EXPORTER_DELAY_SETTING = Setting.timeSetting(
"telemetry.otel.tracer.exporter.delay",
TimeValue.timeValueSeconds(2),
Setting.Property.NodeScope,
Setting.Property.Dynamic
);

private final Settings settings;

/**
Expand All @@ -71,7 +40,12 @@ public OTelTelemetryPlugin(Settings settings) {

@Override
public List<Setting<?>> getSettings() {
return Arrays.asList(TRACER_EXPORTER_BATCH_SIZE_SETTING, TRACER_EXPORTER_DELAY_SETTING, TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING);
return Arrays.asList(
OTelTelemetrySettings.TRACER_EXPORTER_BATCH_SIZE_SETTING,
OTelTelemetrySettings.TRACER_EXPORTER_DELAY_SETTING,
OTelTelemetrySettings.TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING,
OTelTelemetrySettings.OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.telemetry;

import io.opentelemetry.exporter.logging.LoggingSpanExporter;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import org.opensearch.SpecialPermission;
import org.opensearch.common.settings.Setting;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.telemetry.tracing.exporter.OTelSpanExporterFactory;

/**
* OTel specific telemetry settings.
*/
public final class OTelTelemetrySettings {

/**
* Base Constructor.
*/
private OTelTelemetrySettings() {}

/**
* span exporter batch size
*/
public static final Setting<Integer> TRACER_EXPORTER_BATCH_SIZE_SETTING = Setting.intSetting(
"telemetry.otel.tracer.exporter.batch_size",
512,
1,
Setting.Property.NodeScope,
Setting.Property.Final
);
/**
* span exporter max queue size
*/
public static final Setting<Integer> TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING = Setting.intSetting(
"telemetry.otel.tracer.exporter.max_queue_size",
2048,
1,
Setting.Property.NodeScope,
Setting.Property.Final
);
/**
* span exporter delay in seconds
*/
public static final Setting<TimeValue> TRACER_EXPORTER_DELAY_SETTING = Setting.timeSetting(
"telemetry.otel.tracer.exporter.delay",
TimeValue.timeValueSeconds(2),
Setting.Property.NodeScope,
Setting.Property.Final
);

/**
* Span Exporter type setting.
*/
@SuppressWarnings("unchecked")
public static final Setting<Class<SpanExporter>> OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING = new Setting<>(
"telemetry.otel.tracer.span.exporter.class",
LoggingSpanExporter.class.getName(),
className -> {
// Check we ourselves are not being called by unprivileged code.
SpecialPermission.check();

try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<SpanExporter>>) () -> {
final ClassLoader loader = OTelSpanExporterFactory.class.getClassLoader();
return (Class<SpanExporter>) loader.loadClass(className);
});
} catch (PrivilegedActionException ex) {
throw new IllegalStateException("Unable to load span exporter class:" + className, ex.getCause());
}
},
Setting.Property.NodeScope,
Setting.Property.Final
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
Expand All @@ -23,10 +22,11 @@
import org.opensearch.common.settings.Settings;

import java.util.concurrent.TimeUnit;
import org.opensearch.telemetry.tracing.exporter.OTelSpanExporterFactory;

import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_BATCH_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_DELAY_SETTING;
import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_BATCH_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_DELAY_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING;

/**
* This class encapsulates all OpenTelemetry related resources
Expand All @@ -42,7 +42,7 @@ private OTelResourceProvider() {}
public static OpenTelemetry get(Settings settings) {
return get(
settings,
LoggingSpanExporter.create(),
OTelSpanExporterFactory.create(settings),
ContextPropagators.create(W3CTraceContextPropagator.getInstance()),
Sampler.alwaysOn()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.telemetry.tracing.exporter;

import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.SpecialPermission;
import org.opensearch.common.settings.Settings;
import org.opensearch.telemetry.OTelTelemetrySettings;

/**
* Factory class to create the {@link SpanExporter} instance.
*/
public class OTelSpanExporterFactory {

private static final Logger logger = LogManager.getLogger(OTelSpanExporterFactory.class);

/**
* Base constructor.
*/
private OTelSpanExporterFactory() {

}

/**
* Creates the {@link SpanExporter} instances based on the OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING value.
* As of now, it expects the SpanExporter implementations to have a create factory method to instantiate the
* SpanExporter.
* @param settings settings.
* @return SpanExporter instance.
*/
public static SpanExporter create(Settings settings) {
Class<SpanExporter> spanExporterProviderClass = OTelTelemetrySettings.OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING.get(settings);
SpanExporter spanExporter = instantiateSpanExporter(spanExporterProviderClass);
logger.info("Successfully instantiated the SpanExporter class {}", spanExporterProviderClass);
return spanExporter;
}

private static SpanExporter instantiateSpanExporter(Class<SpanExporter> spanExporterProviderClass) {
try {
// Check we ourselves are not being called by unprivileged code.
SpecialPermission.check();
return AccessController.doPrivileged((PrivilegedExceptionAction<SpanExporter>) () -> {
try {
return (SpanExporter) MethodHandles.publicLookup()
.findStatic(spanExporterProviderClass, "create", MethodType.methodType(spanExporterProviderClass))
.asType(MethodType.methodType(SpanExporter.class))
.invokeExact();
} catch (Throwable e) {
if (e.getCause() instanceof NoSuchMethodException) {
throw new IllegalStateException("No create factory method exist in [" + spanExporterProviderClass.getName() + "]");
} else {
throw new IllegalStateException(
"SpanExporter instantiation failed for class [" + spanExporterProviderClass.getName() + "]",
e.getCause()
);
}
}
});
} catch (PrivilegedActionException ex) {
throw new IllegalStateException(
"SpanExporter instantiation failed for class [" + spanExporterProviderClass.getName() + "]",
ex.getCause()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

/**
* This package contains classes needed for telemetry.
*/
package org.opensearch.telemetry.tracing.exporter;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/

grant {
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "accessDeclaredMembers";
};


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

package org.opensearch.telemetry;

import org.junit.After;
import org.junit.Before;
import org.opensearch.common.settings.ClusterSettings;
import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Settings;
Expand All @@ -23,28 +25,46 @@
import java.util.Optional;

import static org.opensearch.telemetry.OTelTelemetryPlugin.OTEL_TRACER_NAME;
import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_BATCH_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_DELAY_SETTING;
import static org.opensearch.telemetry.OTelTelemetryPlugin.TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_BATCH_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_DELAY_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING;
import static org.opensearch.telemetry.OTelTelemetrySettings.OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING;

public class OTelTelemetryPluginTests extends OpenSearchTestCase {

private OTelTelemetryPlugin oTelTracerModulePlugin;
private Optional<Telemetry> telemetry;
private TracingTelemetry tracingTelemetry;

@Before
public void setup() {
// TRACER_EXPORTER_DELAY_SETTING should always be less than 10 seconds because
// io.opentelemetry.sdk.OpenTelemetrySdk.close waits only for 10 seconds for shutdown to complete.
Settings settings = Settings.builder().put(TRACER_EXPORTER_DELAY_SETTING.getKey(), "1s").build();
oTelTracerModulePlugin = new OTelTelemetryPlugin(settings);
telemetry = oTelTracerModulePlugin.getTelemetry(null);
tracingTelemetry = telemetry.get().getTracingTelemetry();
}

public void testGetTelemetry() {
Set<Setting<?>> allTracerSettings = new HashSet<>();
ClusterSettings.FEATURE_FLAGGED_CLUSTER_SETTINGS.get(List.of(FeatureFlags.TELEMETRY)).stream().forEach((allTracerSettings::add));
Settings settings = Settings.builder().build();
OTelTelemetryPlugin oTelTracerModulePlugin = new OTelTelemetryPlugin(settings);
Optional<Telemetry> tracer = oTelTracerModulePlugin.getTelemetry(null);

assertEquals(OTEL_TRACER_NAME, oTelTracerModulePlugin.getName());
TracingTelemetry tracingTelemetry = tracer.get().getTracingTelemetry();
assertTrue(tracingTelemetry instanceof OTelTracingTelemetry);
assertEquals(
Arrays.asList(TRACER_EXPORTER_BATCH_SIZE_SETTING, TRACER_EXPORTER_DELAY_SETTING, TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING),
Arrays.asList(
TRACER_EXPORTER_BATCH_SIZE_SETTING,
TRACER_EXPORTER_DELAY_SETTING,
TRACER_EXPORTER_MAX_QUEUE_SIZE_SETTING,
OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING
),
oTelTracerModulePlugin.getSettings()
);
tracingTelemetry.close();

}

@After
public void cleanup() {
tracingTelemetry.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.telemetry.tracing.exporter;

import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collection;

public class DummySpanExporter implements SpanExporter {
@Override
public CompletableResultCode export(Collection<SpanData> spans) {
return null;
}

@Override
public CompletableResultCode flush() {
return null;
}

@Override
public CompletableResultCode shutdown() {
return null;
}
}
Loading

0 comments on commit 7c8dcf2

Please sign in to comment.