Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
ed766f2
declarative config
zeitlinger Jun 18, 2025
3a3043c
isolate map converter
zeitlinger Jun 18, 2025
044433e
embedded config file
zeitlinger Jun 18, 2025
0972c1e
embedded config file
zeitlinger Jun 18, 2025
8344e12
config bridge
zeitlinger Jun 18, 2025
40e9c0b
config bridge
zeitlinger Jun 18, 2025
c968953
use InstrumentationConfig for encapsulation
zeitlinger Jun 18, 2025
5e43d80
use InstrumentationConfig for encapsulation
zeitlinger Jun 18, 2025
dfa3a18
use InstrumentationConfig for encapsulation
zeitlinger Jun 18, 2025
84ea974
use InstrumentationConfig for encapsulation
zeitlinger Jun 18, 2025
e31415d
create component loader directly (doesn't work otherwise)
zeitlinger Jun 19, 2025
5a74c33
fix disabled config
zeitlinger Jun 19, 2025
6dd4547
add test
zeitlinger Jun 19, 2025
8ba2846
add test
zeitlinger Jun 19, 2025
e76e778
add test
zeitlinger Jun 19, 2025
f2ce7bb
add test
zeitlinger Jun 19, 2025
20df168
add test
zeitlinger Jun 19, 2025
be56cdf
add test
zeitlinger Jun 19, 2025
1711ec0
add test
zeitlinger Jun 19, 2025
5928865
add test
zeitlinger Jun 19, 2025
2ea3d99
add test
zeitlinger Jun 19, 2025
1c84d6d
add test
zeitlinger Jun 19, 2025
83927b1
cleanup
zeitlinger Jun 19, 2025
4aa3f48
cleanup
zeitlinger Jun 19, 2025
bd4ae2e
format
zeitlinger Jun 19, 2025
2498d45
fix rebase
zeitlinger Jun 30, 2025
f03306c
fix rebase
zeitlinger Jun 30, 2025
b6b48ca
./gradlew spotlessApply
otelbot[bot] Jun 30, 2025
1bc33d8
fix rebase
zeitlinger Jul 7, 2025
c4ec3a5
extract condition
zeitlinger Jul 7, 2025
9eef35d
use _
zeitlinger Jul 8, 2025
798ac68
use declarative config properties
zeitlinger Jul 8, 2025
4ab0d7f
use declarative config properties
zeitlinger Jul 8, 2025
db2f8af
fix rebase
zeitlinger Aug 15, 2025
d0fd405
fix rebase
zeitlinger Aug 16, 2025
995ded2
fix rebase
zeitlinger Aug 29, 2025
67d7832
fix rebase
zeitlinger Aug 29, 2025
18b1dbf
fix test
zeitlinger Sep 5, 2025
091f3a1
bug was fixed
zeitlinger Sep 17, 2025
80a4cf4
add distro
zeitlinger Sep 17, 2025
59f2e17
map default enabled
zeitlinger Sep 17, 2025
e90fa68
simplify
zeitlinger Sep 29, 2025
38d6858
api diff
zeitlinger Sep 29, 2025
6a04cdf
fix
zeitlinger Sep 30, 2025
3f11e71
fix
zeitlinger Sep 30, 2025
8a2eb52
add test condition
jaydeluca Oct 7, 2025
7cbc109
reorder
zeitlinger Oct 7, 2025
76c195d
pr review
zeitlinger Oct 8, 2025
5bfc03a
fix rebase
zeitlinger Oct 28, 2025
aa43d07
api diff
zeitlinger Oct 29, 2025
3055852
comment
zeitlinger Oct 29, 2025
f70d4b9
null check
zeitlinger Oct 29, 2025
28fa59c
fix test
zeitlinger Oct 29, 2025
31ab1be
no need to suppress warning
zeitlinger Nov 6, 2025
cec9107
support multiple yaml files (for profiles)
zeitlinger Nov 6, 2025
632e596
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
51d8834
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
a83d6ec
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
8854dee
local
zeitlinger Nov 7, 2025
ecd84ba
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
6a19643
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
2dd89c8
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
02aadd0
support multiple yaml files (for profiles)
zeitlinger Nov 7, 2025
520aa35
spring config provider
zeitlinger Nov 7, 2025
6d031e8
coerce types
zeitlinger Nov 7, 2025
08be383
coerce types
zeitlinger Nov 7, 2025
9b9f4dd
rename
zeitlinger Nov 8, 2025
9e251b8
cleanup
zeitlinger Nov 8, 2025
b7cbaa6
fix rebase
zeitlinger Nov 8, 2025
d803eb5
cleanup
zeitlinger Nov 8, 2025
11089d0
pr review
zeitlinger Nov 10, 2025
5476821
use access class
zeitlinger Nov 10, 2025
c3d8931
pr review
zeitlinger Nov 10, 2025
5bf76ed
pr review
zeitlinger Nov 10, 2025
29012f9
pr review
zeitlinger Nov 10, 2025
65606af
pr review
zeitlinger Nov 10, 2025
fa73f33
pr review
zeitlinger Nov 10, 2025
bfafc1d
fix
zeitlinger Nov 10, 2025
68ee9a6
fix
zeitlinger Nov 10, 2025
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
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
Comparing source compatibility of opentelemetry-spring-boot-autoconfigure-2.22.0-SNAPSHOT.jar against opentelemetry-spring-boot-autoconfigure-2.21.0.jar
No changes.
=== UNCHANGED CLASS: PUBLIC io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
--- REMOVED ANNOTATION: org.springframework.boot.context.properties.EnableConfigurationProperties
--- REMOVED ELEMENT: value=io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties,io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties,io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelSpringProperties (-)
+++ NEW CLASS: PUBLIC(+) io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationAccess (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) com.fasterxml.jackson.databind.ObjectMapper getObjectMapper()
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ dependencies {
library("org.springframework.boot:spring-boot-starter-data-jdbc:$springBootVersion")

implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
implementation("io.opentelemetry:opentelemetry-sdk-extension-incubator")
implementation(project(":sdk-autoconfigure-support"))
implementation(project(":declarative-config-bridge"))
compileOnly("io.opentelemetry:opentelemetry-extension-trace-propagators")
compileOnly("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
compileOnly("io.opentelemetry:opentelemetry-exporter-logging")
Expand All @@ -80,6 +82,7 @@ dependencies {
testLibrary("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
exclude("org.junit.vintage", "junit-vintage-engine")
}

testImplementation("javax.servlet:javax.servlet-api:3.1.0")
testImplementation("jakarta.servlet:jakarta.servlet-api:5.0.0")
testRuntimeOnly("com.h2database:h2:1.4.197")
Expand Down Expand Up @@ -171,6 +174,17 @@ testing {
}
}
}

val testDeclarativeConfig by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
exclude("org.junit.vintage", "junit-vintage-engine")
}
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.spring.autoconfigure;

import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationAccess;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

class EmbeddedConfigFile {

private static final Pattern ARRAY_PATTERN = Pattern.compile("(.+)\\[(\\d+)]$");

private EmbeddedConfigFile() {}

static OpenTelemetryConfigurationModel extractModel(ConfigurableEnvironment environment) {
Map<String, String> props = extractSpringProperties(environment);
return convertToOpenTelemetryConfigurationModel(props);
}

private static Map<String, String> extractSpringProperties(ConfigurableEnvironment environment) {
MutablePropertySources propertySources = environment.getPropertySources();

Map<String, String> props = new HashMap<>();
for (PropertySource<?> propertySource : propertySources) {
if (propertySource instanceof EnumerablePropertySource<?>) {
for (String propertyName :
((EnumerablePropertySource<?>) propertySource).getPropertyNames()) {
if (propertyName.startsWith("otel.")) {
String property = environment.getProperty(propertyName);
if (Objects.equals(property, "")) {
property = null; // spring returns empty string for yaml null
}
props.put(propertyName.substring("otel.".length()), property);
}
}
}
}

if (props.isEmpty()) {
throw new IllegalStateException(
"No properties found with prefix 'otel.' - this should not happen, because we checked "
+ "'environment.getProperty(\"otel.file_format\", String.class) != null' earlier");
}
return props;
}

static OpenTelemetryConfigurationModel convertToOpenTelemetryConfigurationModel(
Map<String, String> flatProps) {
Map<String, Object> nested = convertFlatPropsToNested(flatProps);

return DeclarativeConfigurationAccess.getObjectMapper()
.convertValue(nested, OpenTelemetryConfigurationModel.class);
}

/**
* Convert flat property map to nested structure. e.g. "otel.instrumentation.java.list[0]" = "one"
* and "otel.instrumentation.java.list[1]" = "two" becomes: {otel: {instrumentation: {java: {list:
* ["one", "two"]}}}}
*/
@SuppressWarnings("unchecked")
static Map<String, Object> convertFlatPropsToNested(Map<String, String> flatProps) {
Map<String, Object> result = new HashMap<>();

for (Map.Entry<String, String> entry : flatProps.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();

// Split the key by dots
String[] parts = key.split("\\.");
Map<String, Object> current = result;

for (int i = 0; i < parts.length; i++) {
String part = parts[i];
boolean isLast = (i == parts.length - 1);

// Check if this part contains an array index like "list[0]"
Matcher matcher = ARRAY_PATTERN.matcher(part);
if (matcher.matches()) {
String arrayName = matcher.group(1);
int index = Integer.parseInt(matcher.group(2));

ArrayList<Object> list =
(ArrayList<Object>) current.computeIfAbsent(arrayName, k -> new ArrayList<>());

// Ensure the list is large enough
list.ensureCapacity(index + 1);
while (list.size() <= index) {
list.add(null);
}

if (isLast) {
list.set(index, value);
} else {
// Need to create a nested map at this index
if (list.get(index) == null) {
list.set(index, new HashMap<String, Object>());
}
current = (Map<String, Object>) list.get(index);
}
} else {
// Regular property (not an array)
if (isLast) {
current.put(part, value);
} else {
// Need to create a nested map
if (!current.containsKey(part)) {
current.put(part, new HashMap<String, Object>());
}
current = (Map<String, Object>) current.get(part);
}
}
}
}
return result;
}
}
Loading
Loading