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

x-pack/plugin/otel: introduce x-pack-otel plugin #111091

Merged
merged 53 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
96c5c22
Add YamlTemplateRegistry and OtelIndexTemplateRegistry with resource …
gregkalapos Jul 18, 2024
d5861bb
Fix traces-otel template
gregkalapos Jul 18, 2024
e58d359
Adding first yml tests
gregkalapos Jul 18, 2024
4b7414c
Base APMIndexTemplateRegistry on YamlTemplateRegistry
gregkalapos Jul 19, 2024
b65bb90
Update OTelPlugin.java
gregkalapos Jul 19, 2024
fc82339
Update APMIndexTemplateRegistry.java
gregkalapos Jul 19, 2024
72a6769
Update YamlIngestPipelineConfig.java
gregkalapos Jul 19, 2024
9cd50ee
Adding traces tests
gregkalapos Jul 22, 2024
953968f
Update x-pack/plugin/otel-data/src/main/resources/component-templates…
gregkalapos Jul 22, 2024
6206ab3
Add mapper-version
gregkalapos Jul 25, 2024
c7ee94c
Fix code-style
gregkalapos Jul 25, 2024
effc9c3
Rename `status.status_code` to `status.code`
gregkalapos Jul 25, 2024
ae4fc40
Update otel@mappings.yaml
gregkalapos Jul 25, 2024
909a8dd
Move dynamic_templates to metrics@mappings in core
gregkalapos Jul 25, 2024
68ff941
Run gradlew :x-pack:plugin:core:spotlessApply
gregkalapos Jul 25, 2024
f0f4e46
Update x-pack/plugin/otel-data/src/main/resources/component-templates…
gregkalapos Jul 26, 2024
595d344
Update 20_metic_tests.yml
gregkalapos Jul 26, 2024
9348218
Update CODEOWNERS
gregkalapos Jul 26, 2024
3c680b0
Change dynamic: strict to false
gregkalapos Jul 26, 2024
e61b441
Skip "Reject invalid top level field" test
gregkalapos Jul 26, 2024
ecee377
Update 20_metic_tests.yml
gregkalapos Jul 29, 2024
36be656
Add boolean as dimension test (skipping it for now)
gregkalapos Jul 30, 2024
1476c2c
Add booleans_to_keywords and enable corresponding test
gregkalapos Jul 30, 2024
1487373
Remove processor.event top level mapping
gregkalapos Jul 31, 2024
c47e086
Remove booleans_to_keywords
gregkalapos Jul 31, 2024
42673ce
Add alias service.language.name -> telemetry.sdk.language
gregkalapos Aug 1, 2024
140bec0
cleanup
gregkalapos Aug 5, 2024
1c61929
Update README.md
gregkalapos Aug 5, 2024
63690ed
Update README.md
gregkalapos Aug 5, 2024
c9b617f
Update docs/changelog/111091.yaml
gregkalapos Aug 6, 2024
f427564
Move traces@settings and traces@mappings to core
gregkalapos Aug 6, 2024
7e06131
Update traces-otel@mappings.yaml
gregkalapos Aug 6, 2024
717a29a
Review feedback
gregkalapos Aug 7, 2024
d5de2a1
Adapt `match` style in tests
gregkalapos Aug 7, 2024
4ca5a21
Update docs/changelog/111091.yaml
gregkalapos Aug 7, 2024
65bfd0b
Apply suggestions from code review
gregkalapos Aug 7, 2024
10287a7
Update x-pack/plugin/otel-data/src/main/resources/component-templates…
gregkalapos Aug 7, 2024
a6baf46
Changing trace_flags to long
gregkalapos Aug 8, 2024
7989b12
Remove trace_flags
gregkalapos Aug 9, 2024
2a44ecd
Apply suggestions from code review
gregkalapos Aug 9, 2024
a3837fc
Review feedback
gregkalapos Aug 9, 2024
90c8252
Merge branch 'main' into otel_plugin
elasticmachine Aug 9, 2024
846db1d
Add store_array_source for span links
gregkalapos Aug 12, 2024
e1adb6a
Define constant `data_stream.type` in `template.yaml`s
gregkalapos Aug 12, 2024
dfdcf70
Create package-info.java
gregkalapos Aug 12, 2024
16234d7
Move ecs-tsdb@mappings to index template
felixbarny Aug 13, 2024
0389c37
Update metrics@mappings.json
gregkalapos Aug 13, 2024
9b93b75
Move clusterService.getClusterSettings().addSettingsUpdateConsumer to…
gregkalapos Aug 13, 2024
3152f99
Fix code-style
gregkalapos Aug 13, 2024
680e519
Update x-pack/plugin/otel-data/src/yamlRestTest/resources/rest-api-sp…
gregkalapos Aug 14, 2024
ef3468f
Enable logsdb
gregkalapos Aug 14, 2024
3bb6737
Update traces@settings.json
gregkalapos Aug 14, 2024
9f18034
Merge branch 'main' into otel_plugin
elasticmachine Aug 19, 2024
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
8 changes: 6 additions & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ libs/logstash-bridge @elastic/logstash
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/KibanaOwnedReservedRoleDescriptors.java @elastic/kibana-security

# APM Data index templates, etc.
x-pack/plugin/apm-data/src/main/resources @elastic/apm-server
x-pack/plugin/apm-data/src/yamlRestTest/resources @elastic/apm-server
x-pack/plugin/apm-data/src/main/resources @elastic/obs-ds-intake-services
x-pack/plugin/apm-data/src/yamlRestTest/resources @elastic/obs-ds-intake-services

# OTel
x-pack/plugin/otel-data/src/main/resources @elastic/obs-ds-intake-services
x-pack/plugin/otel-data/src/yamlRestTest/resources @elastic/obs-ds-intake-services
felixbarny marked this conversation as resolved.
Show resolved Hide resolved

# Delivery
gradle @elastic/es-delivery
Expand Down
5 changes: 5 additions & 0 deletions docs/changelog/111091.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 111091
summary: "X-pack/plugin/otel: introduce x-pack-otel plugin"
area: Data streams
type: feature
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,22 @@

package org.elasticsearch.xpack.apmdata;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.features.FeatureService;
import org.elasticsearch.features.NodeFeature;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.yaml.YamlXContent;
import org.elasticsearch.xpack.core.ClientHelper;
import org.elasticsearch.xpack.core.template.IndexTemplateRegistry;
import org.elasticsearch.xpack.core.template.IngestPipelineConfig;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.elasticsearch.xpack.apmdata.ResourceUtils.APM_TEMPLATE_VERSION_VARIABLE;
import static org.elasticsearch.xpack.apmdata.ResourceUtils.loadResource;
import static org.elasticsearch.xpack.apmdata.ResourceUtils.loadVersionedResourceUTF8;
import org.elasticsearch.xpack.core.template.YamlTemplateRegistry;

/**
* Creates all index templates and ingest pipelines that are required for using Elastic APM.
*/
public class APMIndexTemplateRegistry extends IndexTemplateRegistry {
private static final Logger logger = LogManager.getLogger(APMIndexTemplateRegistry.class);
// this node feature is a redefinition of {@link DataStreamFeatures#DATA_STREAM_LIFECYCLE} and it's meant to avoid adding a
// dependency to the data-streams module just for this
public static final NodeFeature DATA_STREAM_LIFECYCLE = new NodeFeature("data_stream.lifecycle");
private final int version;
public class APMIndexTemplateRegistry extends YamlTemplateRegistry {

private final Map<String, ComponentTemplate> componentTemplates;
private final Map<String, ComposableIndexTemplate> composableIndexTemplates;
private final List<IngestPipelineConfig> ingestPipelines;
private final FeatureService featureService;
private volatile boolean enabled;
public static final String APM_TEMPLATE_VERSION_VARIABLE = "xpack.apmdata.template.version";

@SuppressWarnings("unchecked")
public APMIndexTemplateRegistry(
Settings nodeSettings,
ClusterService clusterService,
Expand All @@ -62,133 +31,21 @@ public APMIndexTemplateRegistry(
NamedXContentRegistry xContentRegistry,
FeatureService featureService
) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry);

try {
final Map<String, Object> apmResources = XContentHelper.convertToMap(
YamlXContent.yamlXContent,
loadResource("/resources.yaml"),
false
);
version = (((Number) apmResources.get("version")).intValue());
final List<Object> componentTemplateNames = (List<Object>) apmResources.get("component-templates");
final List<Object> indexTemplateNames = (List<Object>) apmResources.get("index-templates");
final List<Object> ingestPipelineConfigs = (List<Object>) apmResources.get("ingest-pipelines");

componentTemplates = componentTemplateNames.stream()
.map(o -> (String) o)
.collect(Collectors.toMap(name -> name, name -> loadComponentTemplate(name, version)));
composableIndexTemplates = indexTemplateNames.stream()
.map(o -> (String) o)
.collect(Collectors.toMap(name -> name, name -> loadIndexTemplate(name, version)));
ingestPipelines = ingestPipelineConfigs.stream().map(o -> (Map<String, Map<String, Object>>) o).map(map -> {
Map.Entry<String, Map<String, Object>> pipelineConfig = map.entrySet().iterator().next();
return loadIngestPipeline(pipelineConfig.getKey(), version, (List<String>) pipelineConfig.getValue().get("dependencies"));
}).collect(Collectors.toList());
this.featureService = featureService;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public int getVersion() {
return version;
}

void setEnabled(boolean enabled) {
logger.info("APM index template registry is {}", enabled ? "enabled" : "disabled");
this.enabled = enabled;
}

public boolean isEnabled() {
return enabled;
}

public void close() {
clusterService.removeListener(this);
}

@Override
protected String getOrigin() {
return ClientHelper.APM_ORIGIN;
super(nodeSettings, clusterService, threadPool, client, xContentRegistry, featureService);
}

@Override
protected boolean isClusterReady(ClusterChangedEvent event) {
// Ensure current version of the components are installed only after versions that support data stream lifecycle
// due to the use of the feature in all the `@lifecycle` component templates
return featureService.clusterHasFeature(event.state(), DATA_STREAM_LIFECYCLE);
public String getName() {
return "apm";
}

@Override
protected boolean requiresMasterNode() {
return true;
protected String getVersionProperty() {
return APM_TEMPLATE_VERSION_VARIABLE;
}

@Override
protected Map<String, ComponentTemplate> getComponentTemplateConfigs() {
if (enabled) {
return componentTemplates;
} else {
return Map.of();
}
}

@Override
protected Map<String, ComposableIndexTemplate> getComposableTemplateConfigs() {
if (enabled) {
return composableIndexTemplates;
} else {
return Map.of();
}
}

@Override
protected List<IngestPipelineConfig> getIngestPipelines() {
if (enabled) {
return ingestPipelines;
} else {
return Collections.emptyList();
}
}

private static ComponentTemplate loadComponentTemplate(String name, int version) {
try {
final byte[] content = loadVersionedResourceUTF8("/component-templates/" + name + ".yaml", version);
try (var parser = YamlXContent.yamlXContent.createParser(XContentParserConfiguration.EMPTY, content)) {
return ComponentTemplate.parse(parser);
}
} catch (Exception e) {
throw new RuntimeException("failed to load APM Ingest plugin's component template: " + name, e);
}
}

private static ComposableIndexTemplate loadIndexTemplate(String name, int version) {
try {
final byte[] content = loadVersionedResourceUTF8("/index-templates/" + name + ".yaml", version);
try (var parser = YamlXContent.yamlXContent.createParser(XContentParserConfiguration.EMPTY, content)) {
return ComposableIndexTemplate.parse(parser);
}
} catch (Exception e) {
throw new RuntimeException("failed to load APM Ingest plugin's index template: " + name, e);
}
}

private static IngestPipelineConfig loadIngestPipeline(String name, int version, @Nullable List<String> dependencies) {
if (dependencies == null) {
dependencies = Collections.emptyList();
}
return new YamlIngestPipelineConfig(
name,
"/ingest-pipelines/" + name + ".yaml",
version,
APM_TEMPLATE_VERSION_VARIABLE,
dependencies
);
}

@Override
protected boolean applyRolloverAfterTemplateV2Upgrade() {
return true;
protected String getOrigin() {
return ClientHelper.APM_ORIGIN;
}
}

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion x-pack/plugin/apm-data/src/main/resources/resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ component-templates:
- metrics-apm.service_summary@mappings
- metrics-apm.service_transaction@mappings
- metrics-apm.transaction@mappings
- traces@mappings
- traces-apm@mappings
- traces-apm.rum@mappings

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
public class APMIndexTemplateRegistryTests extends ESTestCase {
private APMIndexTemplateRegistry apmIndexTemplateRegistry;
private StackTemplateRegistryAccessor stackTemplateRegistryAccessor;
private ClusterService clusterService;
private ThreadPool threadPool;
private VerifyingClient client;

Expand All @@ -89,7 +88,7 @@ public void createRegistryAndClient() {

threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool);
clusterService = ClusterServiceUtils.createClusterService(threadPool, clusterSettings);
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool, clusterSettings);
FeatureService featureService = new FeatureService(List.of(new DataStreamFeatures()));
stackTemplateRegistryAccessor = new StackTemplateRegistryAccessor(
new StackTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY, featureService)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ private static String maybeRewriteSingleAuthenticationHeaderForVersion(
public static final String CONNECTORS_ORIGIN = "connectors";
public static final String INFERENCE_ORIGIN = "inference";
public static final String APM_ORIGIN = "apm";
public static final String OTEL_ORIGIN = "otel";

private ClientHelper() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ public Iterator<Setting<?>> settings() {
/** Setting for enabling or disabling APM Data. Defaults to true. */
public static final Setting<Boolean> APM_DATA_ENABLED = Setting.boolSetting("xpack.apm_data.enabled", true, Setting.Property.NodeScope);

/** Setting for enabling or disabling OTel Data. Defaults to true. */
public static final Setting<Boolean> OTEL_DATA_ENABLED = Setting.boolSetting(
"xpack.otel_data.enabled",
true,
Setting.Property.NodeScope
);

/** Setting for enabling or disabling enterprise search. Defaults to true. */
public static final Setting<Boolean> ENTERPRISE_SEARCH_ENABLED = Setting.boolSetting(
"xpack.ent_search.enabled",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.template;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;

public class ResourceUtils {
static byte[] loadVersionedResourceUTF8(Class<?> clazz, String name, int version, String versionProperty) {
return loadVersionedResourceUTF8(clazz, name, version, versionProperty, Map.of());
}

static byte[] loadVersionedResourceUTF8(
Class<?> clazz,
String name,
int version,
String versionProperty,
Map<String, String> variables
) {
try {
String content = loadResource(clazz, name);
content = TemplateUtils.replaceVariables(content, String.valueOf(version), versionProperty, variables);
return content.getBytes(StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static String loadResource(Class<?> clazz, String name) throws IOException {
InputStream is = clazz.getResourceAsStream(name);
if (is == null) {
throw new IOException("Resource [" + name + "] not found in classpath.");
}
return new String(is.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
}

}
Loading