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

Added integration tests support for Telemetry span validation #8444

Merged
merged 27 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9543bbb
Added integration tests support for Telemetry span validation
Jul 4, 2023
f66ae49
Added Telemetry validators
Jul 7, 2023
5837dd7
Build failures
Jul 7, 2023
8101872
Added changes desciption in changelog.md
Jul 7, 2023
7cf1dc3
Added telemetry featureflagsetting by default to integtestclass
Jul 10, 2023
5eb41e0
Renamed Telemetry IT classes and modfied span exporter
Jul 11, 2023
4081bec
Removed Logger from InMemorySpanExporter
Jul 11, 2023
3bedd34
Integrated span exporter configurable changes
Jul 11, 2023
5980564
Merge branch 'upstream-main' into HEAD
Jul 13, 2023
1654419
Build fixes
Jul 13, 2023
15dfdf0
Added wrapper on OTel plugin for Integration tests
Jul 14, 2023
a708f40
Removed telemetryPlugin() and telemetryFeatureFlagSettings()
Jul 19, 2023
a417576
Add support for InMemorySpanExporter class
Jul 18, 2023
3f7eef8
Merge branch 'upstream-main' into telemetry-IT-changes
Jul 27, 2023
7f91296
Removing Unintended change
Jul 27, 2023
39f831b
Removing Tracer factory close
Jul 27, 2023
ba54d84
Removed vcs.xml file and few other minor changes
Jul 28, 2023
7ece56c
Removed unintended change
Jul 28, 2023
6923c49
Changed opentelemetry-sdk-testing dependency scope to test
Jul 29, 2023
92f09a1
Fix integ tests
Jul 29, 2023
10d56c3
Precommit fix
Jul 29, 2023
c6296e0
Added TRACER_EXPORTER_DELAY_SETTING, more logging in TelemetryValidators
Aug 4, 2023
764f3b2
Removed AllSpansAreInOrder validator
Aug 4, 2023
9092d3f
Empty-Commit
Aug 4, 2023
2cbe9dd
Empty-Commit
Aug 4, 2023
1c159d5
Merge branch 'upstream/main' into telemetry-IT-changes
Aug 4, 2023
e5709a6
Added comment while closing span
Aug 7, 2023
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
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))
- Added Integration Tests for Distributed Tracing framework ([#8444](https://github.com/opensearch-project/OpenSearch/pull/8444))
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved
- Make Span exporter configurable ([#8620](https://github.com/opensearch-project/OpenSearch/issues/8620))
- Add wrapper tracer implementation

Expand Down
2 changes: 2 additions & 0 deletions plugins/telemetry-otel/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import org.opensearch.gradle.Architecture
import org.opensearch.gradle.OS
import org.opensearch.gradle.info.BuildParams

apply plugin: 'opensearch.internal-cluster-test'

opensearchplugin {
description 'Opentelemetry based telemetry implementation.'
classname 'org.opensearch.telemetry.OTelTelemetryPlugin'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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;

import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import org.opensearch.test.telemetry.tracing.MockSpanData;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.equalTo;

/**
* Writes the span to the list of MockSpanData, everytime a span is emitted.
*/
public class InMemorySpanExporter implements SpanExporter {
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved

private final AtomicBoolean isShutdown = new AtomicBoolean();

private static List<MockSpanData> finishedSpanItems = new ArrayList<>();

/**
* No-args constructor
*/
public InMemorySpanExporter() {}

@Override
public CompletableResultCode export(Collection<SpanData> spans) {
if (isShutdown.get()) {
return CompletableResultCode.ofFailure();
}
for (SpanData span : spans) {
finishedSpanItems.add(convertSpanDataToMockSpanData(span));
}
return CompletableResultCode.ofSuccess();
}

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

/**
* Returns All the spans generated at any point of time.
*/
public List<MockSpanData> getFinishedSpanItems() {
return finishedSpanItems;
}

@Override
public CompletableResultCode shutdown() {
assertThat("Duplicate shutdown() calls.", isShutdown.compareAndSet(false, true), equalTo(true));
return CompletableResultCode.ofSuccess();
}

private MockSpanData convertSpanDataToMockSpanData(SpanData spanData) {
MockSpanData span = new MockSpanData(
spanData.getSpanId(),
spanData.getParentSpanId(),
spanData.getTraceId(),
spanData.getStartEpochNanos(),
spanData.getEndEpochNanos(),
spanData.hasEnded(),
spanData.getName()
);
return span;
}

/**
* Used by SpanExporterFactory to instantiate InMemorySpanExporter
*/
public static InMemorySpanExporter create() {
return new InMemorySpanExporter();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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;

import io.opentelemetry.api.GlobalOpenTelemetry;
import org.opensearch.common.settings.Settings;
import org.opensearch.telemetry.OTelTelemetryPlugin;
import org.opensearch.telemetry.Telemetry;
import org.opensearch.telemetry.TelemetrySettings;

import java.util.Optional;

/**
* Telemetry plugin used for Integration tests.
*/
public class IntegrationTestOTelTelemetryPlugin extends OTelTelemetryPlugin {
/**
* Creates IntegrationTestOTelTelemetryPlugin
* @param settings cluster settings
*/
public IntegrationTestOTelTelemetryPlugin(Settings settings) {
super(settings);
}

/**
* This method overrides getTelemetry() method in OTel plugin class, so we create only one instance of global OpenTelemetry
* resetForTest() will set OpenTelemetry to null again.
* @param settings cluster settings
*/
public Optional<Telemetry> getTelemetry(TelemetrySettings settings) {
GlobalOpenTelemetry.resetForTest();
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved
return super.getTelemetry(settings);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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;

import org.opensearch.client.Client;
import org.opensearch.common.settings.Settings;
import org.opensearch.plugins.Plugin;
import org.opensearch.telemetry.OTelTelemetrySettings;
import org.opensearch.telemetry.TelemetrySettings;
import org.opensearch.test.OpenSearchIntegTestCase;

import java.util.Arrays;
import java.util.Collection;

import static org.opensearch.index.query.QueryBuilders.queryStringQuery;

@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, supportsDedicatedMasters = false, minNumDataNodes = 2)
public class TelemetryTracerDisabledSanityIT extends OpenSearchIntegTestCase {
reta marked this conversation as resolved.
Show resolved Hide resolved

@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put(
OTelTelemetrySettings.OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING.getKey(),
"org.opensearch.telemetry.tracing.InMemorySpanExporter"
)
.build();
}

@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(IntegrationTestOTelTelemetryPlugin.class);
}

@Override
protected boolean addMockTelemetryPlugin() {
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved
return false;
}

public void testSanityCheckWhenTracingDisabled() throws Exception {
Client client = client();
// DISABLE TRACING
client.admin()
.cluster()
.prepareUpdateSettings()
.setTransientSettings(Settings.builder().put(TelemetrySettings.TRACER_ENABLED_SETTING.getKey(), false))
.get();

// Create Index and ingest data
String indexName = "test-index-11";
Settings basicSettings = Settings.builder().put("number_of_shards", 3).put("number_of_replicas", 1).build();
createIndex(indexName, basicSettings);
indexRandom(true, client.prepareIndex(indexName).setId("1").setSource("field1", "t`"));

ensureGreen();
refresh();

// Make the search call;
client.prepareSearch().setQuery(queryStringQuery("fox")).get();

// Sleep for about 2s to wait for traces are published
Thread.sleep(2000);
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved

InMemorySpanExporter exporter = new InMemorySpanExporter();
assertTrue(exporter.getFinishedSpanItems().isEmpty());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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;

import org.opensearch.common.settings.Settings;
import org.opensearch.telemetry.TelemetrySettings;
import org.opensearch.test.OpenSearchIntegTestCase;
import org.opensearch.telemetry.OTelTelemetrySettings;
import org.opensearch.plugins.Plugin;
import org.opensearch.client.Client;
import org.opensearch.test.telemetry.tracing.TelemetryValidators;
import org.opensearch.test.telemetry.tracing.validators.AllSpansAreEndedProperly;
import org.opensearch.test.telemetry.tracing.validators.AllSpansAreInOrder;
import org.opensearch.test.telemetry.tracing.validators.AllSpansHaveUniqueId;
import org.opensearch.test.telemetry.tracing.validators.NumberOfTraceIDsEqualToRequests;
import org.opensearch.test.telemetry.tracing.validators.TotalParentSpansEqualToRequests;

import java.util.Arrays;
import java.util.Collection;

import static org.opensearch.index.query.QueryBuilders.queryStringQuery;

@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, minNumDataNodes = 2)
public class TelemetryTracerEnabledSanityIT extends OpenSearchIntegTestCase {

@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put(
OTelTelemetrySettings.OTEL_TRACER_SPAN_EXPORTER_CLASS_SETTING.getKey(),
"org.opensearch.telemetry.tracing.InMemorySpanExporter"
)
.build();
}

@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(IntegrationTestOTelTelemetryPlugin.class);
}

@Override
protected boolean addMockTelemetryPlugin() {
return false;
}

public void testSanityChecksWhenTracingEnabled() throws Exception {
Client client = client();
// ENABLE TRACING
client.admin()
.cluster()
.prepareUpdateSettings()
.setTransientSettings(Settings.builder().put(TelemetrySettings.TRACER_ENABLED_SETTING.getKey(), true))
.get();

// Create Index and ingest data
String indexName = "test-index-11";
Settings basicSettings = Settings.builder().put("number_of_shards", 3).put("number_of_replicas", 0).build();
createIndex(indexName, basicSettings);
indexRandom(true, client.prepareIndex(indexName).setId("1").setSource("field1", "the fox jumps in the well"));
indexRandom(true, client.prepareIndex(indexName).setId("1").setSource("field2", "another fox did the same."));

ensureGreen();
refresh();

// Make the search calls;
client.prepareSearch().setQuery(queryStringQuery("fox")).get();
client.prepareSearch().setQuery(queryStringQuery("jumps")).get();

// Sleep for about 3s to wait for traces are published
Thread.sleep(3000);
Shephalimittal marked this conversation as resolved.
Show resolved Hide resolved

TelemetryValidators validators = new TelemetryValidators(
Arrays.asList(
AllSpansAreEndedProperly.class,
AllSpansAreInOrder.class,
AllSpansHaveUniqueId.class,
NumberOfTraceIDsEqualToRequests.class,
TotalParentSpansEqualToRequests.class
)
);
InMemorySpanExporter exporter = new InMemorySpanExporter();
if (!exporter.getFinishedSpanItems().isEmpty()) {
validators.validate(exporter.getFinishedSpanItems(), 2);
}
}

}
1 change: 1 addition & 0 deletions server/src/main/java/org/opensearch/node/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,7 @@ private Node stop() {
// we should stop this last since it waits for resources to get released
// if we had scroll searchers etc or recovery going on we wait for to finish.
injector.getInstance(IndicesService.class).stop();
injector.getInstance(TracerFactory.class).close();
logger.info("stopped");

return this;
Expand Down
Loading