)
+ +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void save(io.opentelemetry.sdk.logs.data.LogRecordData)
+ +++ NEW EXCEPTION: java.io.IOException
diff --git a/exporters/.project b/exporters/.project
new file mode 100644
index 00000000000..202814df791
--- /dev/null
+++ b/exporters/.project
@@ -0,0 +1,28 @@
+
+
+ exporters
+ Project exporters created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518765
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/.settings/org.eclipse.buildship.core.prefs b/exporters/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/exporters/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/exporters/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/.settings/org.eclipse.jdt.core.prefs b/exporters/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/exporters/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/exporters/common/.classpath b/exporters/common/.classpath
new file mode 100644
index 00000000000..10652bf3bc1
--- /dev/null
+++ b/exporters/common/.classpath
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/common/.factorypath b/exporters/common/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/exporters/common/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/exporters/common/.project b/exporters/common/.project
new file mode 100644
index 00000000000..ba186609200
--- /dev/null
+++ b/exporters/common/.project
@@ -0,0 +1,34 @@
+
+
+ exporters-common
+ OpenTelemetry Exporter Common
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518774
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/common/.settings/org.eclipse.buildship.core.prefs b/exporters/common/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/common/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/common/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/common/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/common/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/common/.settings/org.eclipse.jdt.core.prefs b/exporters/common/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/common/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/common/compile-stub/.classpath b/exporters/common/compile-stub/.classpath
new file mode 100644
index 00000000000..c3b2c892493
--- /dev/null
+++ b/exporters/common/compile-stub/.classpath
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/common/compile-stub/.project b/exporters/common/compile-stub/.project
new file mode 100644
index 00000000000..b06696dcae1
--- /dev/null
+++ b/exporters/common/compile-stub/.project
@@ -0,0 +1,34 @@
+
+
+ compile-stub
+ OpenTelemetry Exporter Compile Stub
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518727
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/common/compile-stub/.settings/org.eclipse.buildship.core.prefs b/exporters/common/compile-stub/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/common/compile-stub/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/common/compile-stub/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/common/compile-stub/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/common/compile-stub/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/common/compile-stub/.settings/org.eclipse.jdt.core.prefs b/exporters/common/compile-stub/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/common/compile-stub/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/logging-otlp/.classpath b/exporters/logging-otlp/.classpath
new file mode 100644
index 00000000000..0a44d76286a
--- /dev/null
+++ b/exporters/logging-otlp/.classpath
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/logging-otlp/.project b/exporters/logging-otlp/.project
new file mode 100644
index 00000000000..25274a204f8
--- /dev/null
+++ b/exporters/logging-otlp/.project
@@ -0,0 +1,34 @@
+
+
+ logging-otlp
+ OpenTelemetry Protocol JSON Logging Exporters
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518906
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/logging-otlp/.settings/org.eclipse.buildship.core.prefs b/exporters/logging-otlp/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/logging-otlp/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/logging-otlp/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/logging-otlp/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/logging-otlp/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/logging-otlp/.settings/org.eclipse.jdt.core.prefs b/exporters/logging-otlp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/logging-otlp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/logging/.classpath b/exporters/logging/.classpath
new file mode 100644
index 00000000000..6d401e409f1
--- /dev/null
+++ b/exporters/logging/.classpath
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/logging/.project b/exporters/logging/.project
new file mode 100644
index 00000000000..4fd85d27d40
--- /dev/null
+++ b/exporters/logging/.project
@@ -0,0 +1,34 @@
+
+
+ logging
+ OpenTelemetry - Logging Exporter
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518896
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/logging/.settings/org.eclipse.buildship.core.prefs b/exporters/logging/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/logging/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/logging/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/logging/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/logging/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/logging/.settings/org.eclipse.jdt.core.prefs b/exporters/logging/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/logging/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/otlp/.project b/exporters/otlp/.project
new file mode 100644
index 00000000000..f065627639c
--- /dev/null
+++ b/exporters/otlp/.project
@@ -0,0 +1,28 @@
+
+
+ exporters-otlp
+ Project exporters-otlp created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518786
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/otlp/.settings/org.eclipse.buildship.core.prefs b/exporters/otlp/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/otlp/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/otlp/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/otlp/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/otlp/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/otlp/.settings/org.eclipse.jdt.core.prefs b/exporters/otlp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/exporters/otlp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/exporters/otlp/.settings/org.eclipse.wst.common.project.facet.core.xml b/exporters/otlp/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 00000000000..88ceb05cc3e
--- /dev/null
+++ b/exporters/otlp/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/exporters/otlp/all/.classpath b/exporters/otlp/all/.classpath
new file mode 100644
index 00000000000..eb600629b7d
--- /dev/null
+++ b/exporters/otlp/all/.classpath
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/otlp/all/.project b/exporters/otlp/all/.project
new file mode 100644
index 00000000000..257630e3068
--- /dev/null
+++ b/exporters/otlp/all/.project
@@ -0,0 +1,34 @@
+
+
+ otlp-all
+ OpenTelemetry Protocol (OTLP) Exporters
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518982
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/otlp/all/.settings/org.eclipse.buildship.core.prefs b/exporters/otlp/all/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/otlp/all/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/otlp/all/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/otlp/all/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/otlp/all/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/otlp/all/.settings/org.eclipse.jdt.core.prefs b/exporters/otlp/all/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/otlp/all/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/otlp/common/.classpath b/exporters/otlp/common/.classpath
new file mode 100644
index 00000000000..be0805e4c56
--- /dev/null
+++ b/exporters/otlp/common/.classpath
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/otlp/common/.factorypath b/exporters/otlp/common/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/exporters/otlp/common/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/exporters/otlp/common/.project b/exporters/otlp/common/.project
new file mode 100644
index 00000000000..2dbd238b891
--- /dev/null
+++ b/exporters/otlp/common/.project
@@ -0,0 +1,34 @@
+
+
+ otlp-common
+ OpenTelemetry Protocol Exporter
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518989
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/otlp/common/.settings/org.eclipse.buildship.core.prefs b/exporters/otlp/common/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/otlp/common/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/otlp/common/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/otlp/common/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/otlp/common/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/otlp/common/.settings/org.eclipse.jdt.core.prefs b/exporters/otlp/common/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/otlp/common/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/otlp/common/build.gradle.kts b/exporters/otlp/common/build.gradle.kts
index 5ad623561b2..4f854ddaf20 100644
--- a/exporters/otlp/common/build.gradle.kts
+++ b/exporters/otlp/common/build.gradle.kts
@@ -23,6 +23,7 @@ dependencies {
compileOnly(project(":sdk:trace"))
compileOnly(project(":sdk:logs"))
compileOnly(project(":api:incubator"))
+ compileOnly("com.fasterxml.jackson.core:jackson-databind")
testImplementation(project(":sdk:metrics"))
testImplementation(project(":sdk:trace"))
diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStore.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStore.java
new file mode 100644
index 00000000000..d0bd80a87d3
--- /dev/null
+++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStore.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal.otlp.logs;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.export.AuditLogStore;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Logger;
+import java.util.stream.Stream;
+import javax.annotation.Nullable;
+
+/**
+ * This class is internal and experimental. Its APIs are unstable and can change at any time. Its
+ * APIs (or a version of them) may be promoted to the public stable API in the future, but no
+ * guarantees are made.
+ *
+ * A file-based implementation of {@link AuditLogStore} that provides thread-safe concurrent
+ * reading and writing of audit log records to/from the file system.
+ */
+public final class AuditLogFileStore implements AuditLogStore {
+
+ private static final String DEFAULT_LOG_FILE_EXTENSION = ".log";
+
+ public static final String DEFAULT_LOG_FILE_NAME = "audit" + DEFAULT_LOG_FILE_EXTENSION;
+
+ private static final Logger logger = Logger.getLogger(AuditLogFileStore.class.getName());
+
+ /** Generates a unique ID for a log record based on its content. */
+ static String generateRecordId(@Nullable LogRecordData logRecord) {
+ if (logRecord == null) {
+ return "";
+ }
+ return String.valueOf(
+ (logRecord.getTimestampEpochNanos()
+ + String.valueOf(logRecord.getBodyValue())
+ + logRecord.getSeverity().toString())
+ .hashCode());
+ }
+
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ private final Path logFilePath;
+
+ private final Set loggedRecords = ConcurrentHashMap.newKeySet();
+
+ @Nullable private ObjectMapper objectMapper;
+
+ /**
+ * Creates a new AuditLogFileStore that stores logs in the specified path. If the path is a
+ * directory, logs will be stored in a default file within that directory. If the path is a file,
+ * logs will be stored directly in that file.
+ *
+ * @param path the path to the log file or directory
+ * @throws IOException if the file or directory cannot be created or accessed
+ */
+ public AuditLogFileStore(Path path) throws IOException {
+ if (Files.isDirectory(path)) {
+ this.logFilePath = path.resolve(DEFAULT_LOG_FILE_NAME);
+ } else {
+ this.logFilePath = path;
+ }
+
+ // Ensure parent directories exist
+ if (logFilePath.getParent() != null) {
+ Files.createDirectories(logFilePath.getParent());
+ }
+
+ // Create the file if it doesn't exist
+ if (!Files.exists(logFilePath)) {
+ Files.createFile(logFilePath);
+ }
+
+ // verify that we can read and write to the file
+ if (!Files.isReadable(logFilePath)) {
+ throw new IOException("Can't read: " + logFilePath);
+ }
+ if (!Files.isWritable(logFilePath)) {
+ throw new IOException("Can't write: " + logFilePath);
+ }
+
+ // Load existing log record IDs to avoid duplicates
+ loadExistingRecordIds();
+ }
+
+ /**
+ * Creates a new AuditLogFileStore that stores logs in the specified file.
+ *
+ * @param filePath the path to the log file
+ * @throws IOException if the file cannot be created or accessed
+ */
+ public AuditLogFileStore(String filePath) throws IOException {
+ this(Paths.get(filePath));
+ }
+
+ @Override
+ public Collection getAll() {
+ Collection records = new ArrayList<>();
+ lock.readLock().lock();
+ try (Stream lines = Files.lines(logFilePath)) {
+ lines.forEach(
+ line -> {
+ LogRecordData record = parseLogRecord(line);
+ if (record != null) {
+ records.add(record);
+ }
+ });
+ } catch (IOException e) {
+ logger.throwing(AuditLogFileStore.class.getName(), "getAll", e);
+ }
+ lock.readLock().unlock();
+ return records;
+ }
+
+ ObjectMapper json() {
+ if (objectMapper == null) {
+ objectMapper = new ObjectMapper();
+ }
+ return objectMapper;
+ }
+
+ /** Loads existing record IDs from the log file to prevent duplicates. */
+ private void loadExistingRecordIds() throws IOException {
+ if (!Files.exists(logFilePath) || Files.size(logFilePath) == 0) {
+ return;
+ }
+
+ lock.readLock().lock();
+ try (Stream lines = Files.lines(logFilePath)) {
+ lines.forEach(
+ line -> {
+ String recordId = generateRecordId(parseLogRecord(line));
+ if (recordId != null) {
+ loggedRecords.add(recordId);
+ }
+ });
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Parses a log record from a stored line (simplified implementation). In a production system, you
+ * might want to use JSON or another structured format.
+ */
+ @Nullable
+ LogRecordData parseLogRecord(String line) {
+ try {
+ return json().readValue(line, JsonLogRecordData.class);
+ } catch (JsonProcessingException e) {
+ logger.throwing(AuditLogFileStore.class.getName(), "parseLogRecord", e);
+ }
+ return null;
+ }
+
+ @Override
+ public void removeAll(Collection logs) {
+ lock.writeLock().lock();
+ try {
+ Set recordIdsToRemove = new HashSet<>();
+ for (LogRecordData log : logs) {
+ recordIdsToRemove.add(generateRecordId(log));
+ }
+
+ // Read all lines, filter out the ones to remove, then write back
+ Collection remainingLines = new ArrayList<>();
+ try (BufferedReader reader = Files.newBufferedReader(logFilePath)) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ String recordId = generateRecordId(parseLogRecord(line));
+ if (recordId == null || !recordIdsToRemove.contains(recordId)) {
+ remainingLines.add(line);
+ } else {
+ loggedRecords.remove(recordId);
+ }
+ }
+ } catch (IOException e) {
+ logger.throwing(AuditLogFileStore.class.getName(), "removeAll", e);
+ }
+
+ // Write the remaining lines back to the file
+ try (BufferedWriter writer =
+ Files.newBufferedWriter(
+ logFilePath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+ for (String line : remainingLines) {
+ writer.write(line);
+ writer.newLine();
+ }
+ } catch (IOException e) {
+ logger.throwing(AuditLogFileStore.class.getName(), "removeAll", e);
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void save(LogRecordData logRecord) throws IOException {
+ String recordId = generateRecordId(logRecord);
+
+ // Check if we've already logged this record
+ if (loggedRecords.contains(recordId)) {
+ return;
+ }
+
+ lock.writeLock().lock();
+ try (OutputStream out =
+ Files.newOutputStream(logFilePath, StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ LogMarshaler.create(logRecord).writeJsonTo(baos); // closes the stream!
+ out.write(baos.toByteArray());
+ out.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8));
+ loggedRecords.add(recordId);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+}
diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/JsonLogRecordData.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/JsonLogRecordData.java
new file mode 100644
index 00000000000..fe98f83ce03
--- /dev/null
+++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/JsonLogRecordData.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal.otlp.logs;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.api.trace.TraceFlags;
+import io.opentelemetry.api.trace.TraceState;
+import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.resources.Resource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nullable;
+
+/**
+ * This class is internal and experimental. Its APIs are unstable and can change at any time. Its
+ * APIs (or a version of them) may be promoted to the public stable API in the future, but no
+ * guarantees are made.
+ *
+ * A JSON-based implementation of {@link LogRecordData} that maps JSON log record fields to the
+ * corresponding OpenTelemetry SDK log record data fields.
+ *
+ * @see LogMarshaler#writeJsonTo(java.io.OutputStream)
+ */
+public class JsonLogRecordData implements LogRecordData {
+
+ static class ArrayWrapper {
+ @Nullable
+ @JsonProperty("values")
+ @JsonDeserialize(using = AttrValueArrayDeserializer.class)
+ List values;
+ }
+
+ static class AttributesWrapper {
+ @Nullable
+ @JsonProperty("key")
+ String key;
+
+ @Nullable
+ @JsonProperty("value")
+ ValueWrapper value;
+ }
+
+ /** Custom deserializer for array values that handles different value types. */
+ static class AttrValueArrayDeserializer extends JsonDeserializer> {
+ @Override
+ public List deserialize(JsonParser parser, DeserializationContext context)
+ throws IOException {
+ JsonNode arrayNode = parser.getCodec().readTree(parser);
+ List result = new ArrayList<>();
+
+ if (arrayNode.isArray()) {
+ for (JsonNode valueNode : arrayNode) {
+ Object value = extractValue(valueNode);
+ if (value != null) {
+ result.add(value);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ static Object extractValue(JsonNode valueNode) {
+ if (valueNode.has("boolValue")) {
+ return valueNode.get("boolValue").asBoolean();
+ }
+ if (valueNode.has("doubleValue")) {
+ return valueNode.get("doubleValue").asDouble();
+ }
+ if (valueNode.has("intValue")) {
+ String intStr = valueNode.get("intValue").asText();
+ try {
+ return Long.parseLong(intStr);
+ } catch (NumberFormatException e) {
+ return intStr;
+ }
+ }
+ if (valueNode.has("stringValue")) {
+ return valueNode.get("stringValue").asText();
+ }
+ if (valueNode.has("bytesValue")) {
+ return valueNode.get("bytesValue").asText();
+ }
+ return valueNode.asText();
+ }
+ }
+
+ static class BodyWrapper {
+ @Nullable
+ @JsonProperty("stringValue")
+ String stringValue;
+ }
+
+ static class ValueWrapper {
+ @Nullable
+ @JsonProperty("arrayValue")
+ ArrayWrapper arrayValue;
+
+ @Nullable
+ @JsonProperty("boolValue")
+ Boolean boolValue;
+
+ @Nullable
+ @JsonProperty("doubleValue")
+ Double doubleValue;
+
+ @Nullable
+ @JsonProperty("intValue")
+ String intValue;
+
+ @Nullable
+ @JsonProperty("stringValue")
+ String stringValue;
+ }
+
+ @Nullable
+ @JsonProperty("attributes")
+ private Collection attributes;
+
+ @Nullable
+ @JsonProperty("body")
+ private BodyWrapper body;
+
+ @JsonProperty("droppedAttributesCount")
+ private int droppedAttributesCount;
+
+ @JsonProperty("observedTimeUnixNano")
+ private long observedTimestampEpochNanos;
+
+ @Nullable @JsonIgnore private Severity severity;
+
+ @JsonProperty("severityNumber")
+ private int severityNumber;
+
+ @Nullable
+ @JsonProperty("severityText")
+ private String severityText;
+
+ @Nullable
+ @JsonProperty("spanId")
+ private String spanId;
+
+ @JsonProperty("timeUnixNano")
+ private long timestampEpochNanos;
+
+ @Nullable
+ @JsonProperty("traceId")
+ private String traceId;
+
+ @Nullable @JsonIgnore private transient Attributes attrs;
+
+ @Override
+ public Attributes getAttributes() {
+ if (attrs != null) {
+ return attrs;
+ }
+
+ AttributesBuilder builder = Attributes.builder();
+ if (attributes != null) {
+ for (AttributesWrapper attr : attributes) {
+ if (attr.key == null || attr.value == null) {
+ continue;
+ }
+ if (attr.value.stringValue != null) {
+ builder.put(attr.key, attr.value.stringValue);
+ } else if (attr.value.intValue != null) {
+ builder.put(attr.key, Long.valueOf(attr.value.intValue));
+ } else if (attr.value.boolValue != null) {
+ builder.put(attr.key, Boolean.valueOf(attr.value.boolValue));
+ } else if (attr.value.doubleValue != null) {
+ builder.put(attr.key, Double.valueOf(attr.value.doubleValue));
+ } else if (attr.value.arrayValue != null && attr.value.arrayValue.values != null) {
+ // Handle array values - convert to appropriate array types
+ List values = attr.value.arrayValue.values;
+ if (!values.isEmpty()) {
+ Object firstValue = values.get(0);
+ if (firstValue instanceof String) {
+ builder.put(attr.key, values.toArray(new String[values.size()]));
+ } else if (firstValue instanceof Long) {
+ builder.put(attr.key, values.stream().mapToLong(v -> (Long) v).toArray());
+ } else if (firstValue instanceof Double) {
+ builder.put(attr.key, values.stream().mapToDouble(v -> (Double) v).toArray());
+ } else if (firstValue instanceof Boolean) {
+ // Convert Boolean list to string representation since Attributes doesn't support
+ // Boolean arrays
+ boolean[] boolArray = new boolean[values.size()];
+ for (int i = 0; i < values.size(); i++) {
+ boolArray[i] = (Boolean) values.get(i);
+ }
+ builder.put(attr.key, boolArray);
+ }
+ }
+ }
+ }
+ }
+
+ attrs = builder.build();
+ return attrs;
+ }
+
+ @Override
+ @Deprecated
+ public io.opentelemetry.sdk.logs.data.Body getBody() {
+ return new io.opentelemetry.sdk.logs.data.Body() {
+ @Override
+ public String asString() {
+ if (body == null || body.stringValue == null) {
+ return "";
+ }
+ return body.stringValue;
+ }
+
+ @Override
+ public Type getType() {
+ return io.opentelemetry.sdk.logs.data.Body.Type.STRING;
+ }
+ };
+ }
+
+ /**
+ * Returns the empty instrumentation scope.
+ *
+ * @return {@link InstrumentationScopeInfo#empty()}.
+ */
+ @Override
+ public InstrumentationScopeInfo getInstrumentationScopeInfo() {
+ return InstrumentationScopeInfo.empty();
+ }
+
+ @Override
+ public long getObservedTimestampEpochNanos() {
+ return observedTimestampEpochNanos;
+ }
+
+ @Override
+ public Resource getResource() {
+ return Resource.empty();
+ }
+
+ @Override
+ public Severity getSeverity() {
+ if (severity != null) {
+ return severity;
+ }
+ for (Severity s : Severity.values()) {
+ if (s.getSeverityNumber() == severityNumber) {
+ severity = s;
+ return severity;
+ }
+ }
+
+ return Severity.UNDEFINED_SEVERITY_NUMBER;
+ }
+
+ @Override
+ public String getSeverityText() {
+ if (severityText == null || severityText.isEmpty()) {
+ return getSeverity().name();
+ }
+ return severityText;
+ }
+
+ @Override
+ public SpanContext getSpanContext() {
+ if (traceId == null || traceId.isEmpty() || spanId == null || spanId.isEmpty()) {
+ return SpanContext.getInvalid();
+ }
+ return SpanContext.create(traceId, spanId, TraceFlags.getDefault(), TraceState.getDefault());
+ }
+
+ @Override
+ public long getTimestampEpochNanos() {
+ return timestampEpochNanos;
+ }
+
+ @Override
+ public int getTotalAttributeCount() {
+ if (droppedAttributesCount < 0) {
+ return getAttributes().size() + droppedAttributesCount;
+ }
+ return getAttributes().size();
+ }
+}
diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStoreTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStoreTest.java
new file mode 100644
index 00000000000..608b1a05f0f
--- /dev/null
+++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/AuditLogFileStoreTest.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.exporter.internal.otlp.logs;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.AttributeType;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.api.trace.SpanId;
+import io.opentelemetry.api.trace.TraceFlags;
+import io.opentelemetry.api.trace.TraceId;
+import io.opentelemetry.api.trace.TraceState;
+import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.export.AuditLogStore;
+import io.opentelemetry.sdk.resources.Resource;
+import io.opentelemetry.sdk.testing.logs.TestLogRecordData;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+class AuditLogFileStoreTest {
+
+ @TempDir Path tempDir;
+
+ private AuditLogStore auditLogStore;
+ private Path logFilePath;
+
+ @BeforeEach
+ void setUp() throws IOException {
+ logFilePath = tempDir.resolve("test-audit.log");
+ auditLogStore = new AuditLogFileStore(logFilePath);
+ }
+
+ @Test
+ void constructor_withFilePath_createsFile() throws IOException {
+ Path newLogFile = tempDir.resolve("new-audit.log");
+
+ new AuditLogFileStore(newLogFile.toString());
+
+ assertThat(Files.exists(newLogFile)).isTrue();
+ }
+
+ @Test
+ void constructor_withDirectory_createsDefaultFile() throws IOException {
+ Path dirPath = tempDir.resolve("audit-logs");
+ Files.createDirectories(dirPath);
+
+ new AuditLogFileStore(dirPath);
+
+ assertThat(Files.exists(dirPath.resolve("audit.log"))).isTrue();
+ }
+
+ @Test
+ void constructor_withNonExistentDirectory_createsDirectoriesAndFile() throws IOException {
+ Path dirPath =
+ tempDir
+ .resolve("nested")
+ .resolve("audit-logs")
+ .resolve(AuditLogFileStore.DEFAULT_LOG_FILE_NAME);
+ Path filePath = dirPath.resolve(AuditLogFileStore.DEFAULT_LOG_FILE_NAME);
+
+ new AuditLogFileStore(filePath);
+
+ assertThat(Files.exists(dirPath.resolve(AuditLogFileStore.DEFAULT_LOG_FILE_NAME))).isTrue();
+ }
+
+ @Test
+ void save_singleLogRecord_storesSuccessfully() throws IOException {
+ LogRecordData logRecord = createTestLogRecord("Test message", Severity.INFO, 1000L);
+
+ auditLogStore.save(logRecord);
+
+ Collection storedRecords = auditLogStore.getAll();
+ assertThat(storedRecords).hasSize(1);
+ // Note: The current implementation returns a basic LogRecordData with limited field mapping
+ assertThat(storedRecords.iterator().next().getBodyValue().getValue().toString())
+ .contains("Test message");
+ }
+
+ @Test
+ void save_duplicateLogRecord_ignoresDuplicate() throws IOException {
+ LogRecordData logRecord = createTestLogRecord("Test message", Severity.INFO, 1000L);
+
+ auditLogStore.save(logRecord);
+ auditLogStore.save(logRecord); // Same record
+
+ Collection storedRecords = auditLogStore.getAll();
+ assertThat(storedRecords).hasSize(1);
+ }
+
+ @Test
+ void save_multipleUniqueLogRecords_storesAll() throws IOException {
+ LogRecordData logRecord1 = createTestLogRecord("Message 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Message 2", Severity.WARN, 2000L);
+ LogRecordData logRecord3 = createTestLogRecord("Message 3", Severity.ERROR, 3000L);
+
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+ auditLogStore.save(logRecord3);
+
+ Collection storedRecords = auditLogStore.getAll();
+ assertThat(storedRecords).hasSize(3);
+ }
+
+ @Test
+ void save_concurrentWrites_handlesCorrectly() {
+ LogRecordData logRecord1 = createTestLogRecord("Concurrent 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Concurrent 2", Severity.WARN, 2000L);
+
+ assertDoesNotThrow(
+ () -> {
+ Thread thread1 =
+ new Thread(
+ () -> {
+ try {
+ auditLogStore.save(logRecord1);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ Thread thread2 =
+ new Thread(
+ () -> {
+ try {
+ auditLogStore.save(logRecord2);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+ });
+
+ Collection storedRecords = auditLogStore.getAll();
+ assertThat(storedRecords).hasSize(2);
+ }
+
+ @Test
+ void getAll_emptyStore_returnsEmptyCollection() {
+ Collection records = auditLogStore.getAll();
+
+ assertThat(records).isEmpty();
+ }
+
+ @Test
+ void getAll_withStoredRecords_returnsAllRecords() throws IOException {
+ LogRecordData logRecord1 = createTestLogRecord("Message 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Message 2", Severity.WARN, 2000L);
+
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+
+ Collection records = auditLogStore.getAll();
+
+ assertThat(records).hasSize(2);
+ }
+
+ @Test
+ void removeAll_emptyCollection_doesNotThrow() {
+ assertDoesNotThrow(() -> auditLogStore.removeAll(Collections.emptyList()));
+ }
+
+ @Test
+ void removeAll_nonExistentRecords_doesNotThrow() {
+ LogRecordData nonExistentRecord = createTestLogRecord("Non-existent", Severity.INFO, 9999L);
+
+ assertDoesNotThrow(() -> auditLogStore.removeAll(Arrays.asList(nonExistentRecord)));
+ }
+
+ @Test
+ void removeAll_existingRecords_removesSuccessfully() throws IOException {
+ LogRecordData logRecord1 = createTestLogRecord("Message 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Message 2", Severity.WARN, 2000L);
+ LogRecordData logRecord3 = createTestLogRecord("Message 3", Severity.ERROR, 3000L);
+
+ // Save all records
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+ auditLogStore.save(logRecord3);
+
+ // Remove two records
+ auditLogStore.removeAll(Arrays.asList(logRecord1, logRecord3));
+
+ Collection remainingRecords = auditLogStore.getAll();
+ assertThat(remainingRecords).hasSize(1);
+ assertThat(remainingRecords.iterator().next().getSeverityText())
+ .contains(String.valueOf(Severity.WARN));
+ }
+
+ @Test
+ void removeAll_allRecords_leavesEmptyStore() throws IOException {
+ LogRecordData logRecord1 = createTestLogRecord("Message 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Message 2", Severity.WARN, 2000L);
+
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+
+ auditLogStore.removeAll(Arrays.asList(logRecord1, logRecord2));
+
+ Collection remainingRecords = auditLogStore.getAll();
+ assertThat(remainingRecords).isEmpty();
+ }
+
+ @Test
+ void interfaceContract_saveRetrieveRemove_worksEndToEnd() throws IOException {
+ // Test the complete AuditLogStore interface contract
+ LogRecordData logRecord1 = createTestLogRecord("End-to-end 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("End-to-end 2", Severity.WARN, 2000L);
+ LogRecordData logRecord3 = createTestLogRecord("End-to-end 3", Severity.ERROR, 3000L);
+
+ // Initially empty
+ assertThat(auditLogStore.getAll()).isEmpty();
+
+ // Save records
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+ auditLogStore.save(logRecord3);
+
+ // Verify all saved
+ assertThat(auditLogStore.getAll()).hasSize(3);
+
+ // Remove some records
+ auditLogStore.removeAll(Arrays.asList(logRecord1, logRecord3));
+
+ // Verify only one remains
+ Collection remainingRecords = auditLogStore.getAll();
+ assertThat(remainingRecords).hasSize(1);
+
+ // Remove all remaining
+ auditLogStore.removeAll(remainingRecords);
+
+ // Verify empty
+ assertThat(auditLogStore.getAll()).isEmpty();
+ }
+
+ @Test
+ void generateRecordId_sameContent_generatesSameId() {
+ LogRecordData logRecord1 = createTestLogRecord("Same message", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Same message", Severity.INFO, 1000L);
+
+ String id1 = AuditLogFileStore.generateRecordId(logRecord1);
+ String id2 = AuditLogFileStore.generateRecordId(logRecord2);
+
+ assertThat(id1).isEqualTo(id2);
+ }
+
+ @Test
+ void generateRecordId_differentContent_generatesDifferentIds() {
+ LogRecordData logRecord1 = createTestLogRecord("Message 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("Message 2", Severity.INFO, 1000L);
+
+ String id1 = AuditLogFileStore.generateRecordId(logRecord1);
+ String id2 = AuditLogFileStore.generateRecordId(logRecord2);
+
+ assertThat(id1).isNotEqualTo(id2);
+ }
+
+ @Test
+ void persistence_acrossInstances_maintainsData() throws IOException {
+ LogRecordData logRecord = createTestLogRecord("Persistent message", Severity.INFO, 1000L);
+
+ // Save with first instance
+ auditLogStore.save(logRecord);
+
+ // Create new instance pointing to same file
+ AuditLogStore newInstance = new AuditLogFileStore(logFilePath);
+
+ // Verify data is still there
+ Collection records = newInstance.getAll();
+ assertThat(records).hasSize(1);
+ }
+
+ static LogRecordData createTestLogRecord(String message, Severity severity, long timestampNanos) {
+
+ AttributesBuilder attr = Attributes.builder();
+ // iterate over all available AttributeTypes and create attributes for each type
+ for (AttributeType type : AttributeType.values()) {
+ switch (type) {
+ case STRING:
+ attr.put(AttributeKey.stringKey("stringAttr"), "stringValue");
+ break;
+ case LONG:
+ attr.put(AttributeKey.longKey("longAttr"), 12345L);
+ break;
+ case DOUBLE:
+ attr.put(AttributeKey.doubleKey("doubleAttr"), 123.45);
+ break;
+ case BOOLEAN:
+ attr.put(AttributeKey.booleanKey("booleanAttr"), true);
+ break;
+ case STRING_ARRAY:
+ attr.put(
+ AttributeKey.stringArrayKey("stringArrayAttr"), Arrays.asList("one", "two", "three"));
+ break;
+ case LONG_ARRAY:
+ attr.put(AttributeKey.longArrayKey("longArrayAttr"), Arrays.asList(1L, 2L, 3L));
+ break;
+ case DOUBLE_ARRAY:
+ attr.put(AttributeKey.doubleArrayKey("doubleArrayAttr"), Arrays.asList(1.1, 2.2, 3.3));
+ break;
+ case BOOLEAN_ARRAY:
+ attr.put(
+ AttributeKey.booleanArrayKey("booleanArrayAttr"), Arrays.asList(true, false, true));
+ break;
+ }
+ }
+
+ return TestLogRecordData.builder()
+ .setResource(Resource.getDefault())
+ .setInstrumentationScopeInfo(InstrumentationScopeInfo.create("test"))
+ .setTimestamp(timestampNanos, TimeUnit.NANOSECONDS)
+ .setObservedTimestamp(timestampNanos, TimeUnit.NANOSECONDS)
+ .setSeverity(severity)
+ .setSeverityText(severity.name())
+ .setBody(message)
+ .setAttributes(attr.build())
+ .setTotalAttributeCount(attr.build().size())
+ .setSpanContext(
+ SpanContext.create(
+ TraceId.fromLongs(0, 1),
+ SpanId.fromLong(1),
+ TraceFlags.getDefault(),
+ TraceState.getDefault()))
+ .build();
+ }
+
+ /*
+ * Let's test our deserialization logic as well, by first serializing a LogRecordData to JSON using the SDK and then deserializing it back using our JsonLogRecordData class.
+ */
+ @Test
+ void serializationDeserialization_cycle_worksCorrectly() throws IOException {
+ LogRecordData logRecord1 = createTestLogRecord("End-to-end 1", Severity.INFO, 1000L);
+ LogRecordData logRecord2 = createTestLogRecord("End-to-end 2", Severity.WARN, 2000L);
+ LogRecordData logRecord3 = createTestLogRecord("End-to-end 3", Severity.ERROR, 3000L);
+
+ // Initially empty
+ assertThat(auditLogStore.getAll()).isEmpty();
+
+ // Save records
+ auditLogStore.save(logRecord1);
+ auditLogStore.save(logRecord2);
+ auditLogStore.save(logRecord3);
+
+ // Verify all saved
+ Collection storedRecords = auditLogStore.getAll();
+ assertThat(storedRecords).hasSize(3);
+
+ // create another AuditLogFileStore instance to write to the same file
+ Path otherFilePath = tempDir.resolve("other-audit.log");
+ AuditLogStore anotherInstance = new AuditLogFileStore(otherFilePath);
+ for (LogRecordData record : storedRecords) {
+ anotherInstance.save(record);
+ }
+
+ // Verify that both files have the same byte content
+ byte[] originalFileBytes = Files.readAllBytes(logFilePath);
+ byte[] otherFileBytes = Files.readAllBytes(otherFilePath);
+
+ // Uncomment to debug content differences
+ // System.out.println("Org file content:\n" + new String(originalFileBytes));
+ // System.out.println("Oth file content:\n" + new String(otherFileBytes));
+ assertThat(originalFileBytes).isEqualTo(otherFileBytes);
+ }
+}
diff --git a/exporters/otlp/profiles/.classpath b/exporters/otlp/profiles/.classpath
new file mode 100644
index 00000000000..584f5d9a8e0
--- /dev/null
+++ b/exporters/otlp/profiles/.classpath
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/otlp/profiles/.factorypath b/exporters/otlp/profiles/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/exporters/otlp/profiles/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/exporters/otlp/profiles/.project b/exporters/otlp/profiles/.project
new file mode 100644
index 00000000000..897e001f533
--- /dev/null
+++ b/exporters/otlp/profiles/.project
@@ -0,0 +1,34 @@
+
+
+ profiles
+ OpenTelemetry - Profiles Exporter
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519009
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/otlp/profiles/.settings/org.eclipse.buildship.core.prefs b/exporters/otlp/profiles/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/otlp/profiles/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/otlp/profiles/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/otlp/profiles/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/otlp/profiles/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/otlp/profiles/.settings/org.eclipse.jdt.core.prefs b/exporters/otlp/profiles/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..164ab938d2b
--- /dev/null
+++ b/exporters/otlp/profiles/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,15 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/otlp/testing-internal/.classpath b/exporters/otlp/testing-internal/.classpath
new file mode 100644
index 00000000000..f47c32d1881
--- /dev/null
+++ b/exporters/otlp/testing-internal/.classpath
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/otlp/testing-internal/.project b/exporters/otlp/testing-internal/.project
new file mode 100644
index 00000000000..315a83a73a5
--- /dev/null
+++ b/exporters/otlp/testing-internal/.project
@@ -0,0 +1,34 @@
+
+
+ otlp-testing-internal
+ OpenTelemetry Exporter Testing (Internal)
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518995
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/otlp/testing-internal/.settings/org.eclipse.buildship.core.prefs b/exporters/otlp/testing-internal/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/otlp/testing-internal/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.core.prefs b/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/otlp/testing-internal/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java
index 908dd454631..2897b448e3b 100644
--- a/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java
+++ b/exporters/otlp/testing-internal/src/main/java/io/opentelemetry/exporter/otlp/testing/internal/AbstractGrpcTelemetryExporterTest.java
@@ -478,6 +478,7 @@ void connectTimeout() {
.extracting("delegate.grpcSender")
.matches(sender -> sender.getClass().getSimpleName().equals("OkHttpGrpcSender"));
+ // TODO: debug why connecting to localhost with a very short timeout doesn't trigger retry!
try (TelemetryExporter exporter =
exporterBuilder()
// Connecting to a non-routable IP address to trigger connection error
diff --git a/exporters/prometheus/.classpath b/exporters/prometheus/.classpath
new file mode 100644
index 00000000000..f4b173c0669
--- /dev/null
+++ b/exporters/prometheus/.classpath
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/prometheus/.project b/exporters/prometheus/.project
new file mode 100644
index 00000000000..f65e7173c5c
--- /dev/null
+++ b/exporters/prometheus/.project
@@ -0,0 +1,34 @@
+
+
+ prometheus
+ OpenTelemetry Prometheus Exporter
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519015
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/prometheus/.settings/org.eclipse.buildship.core.prefs b/exporters/prometheus/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/prometheus/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/prometheus/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/prometheus/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/prometheus/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/prometheus/.settings/org.eclipse.jdt.core.prefs b/exporters/prometheus/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/prometheus/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/sender/.project b/exporters/sender/.project
new file mode 100644
index 00000000000..06bfb1087ff
--- /dev/null
+++ b/exporters/sender/.project
@@ -0,0 +1,28 @@
+
+
+ sender
+ Project sender created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519059
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/sender/.settings/org.eclipse.buildship.core.prefs b/exporters/sender/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/sender/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/sender/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/sender/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/sender/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/sender/.settings/org.eclipse.jdt.core.prefs b/exporters/sender/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/exporters/sender/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/exporters/sender/grpc-managed-channel/.classpath b/exporters/sender/grpc-managed-channel/.classpath
new file mode 100644
index 00000000000..a3b20a28427
--- /dev/null
+++ b/exporters/sender/grpc-managed-channel/.classpath
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/sender/grpc-managed-channel/.project b/exporters/sender/grpc-managed-channel/.project
new file mode 100644
index 00000000000..b69cd93d7a9
--- /dev/null
+++ b/exporters/sender/grpc-managed-channel/.project
@@ -0,0 +1,34 @@
+
+
+ grpc-managed-channel
+ OpenTelemetry gRPC Upstream Sender
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518830
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/sender/grpc-managed-channel/.settings/org.eclipse.buildship.core.prefs b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.core.prefs b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/sender/grpc-managed-channel/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/sender/jdk/.classpath b/exporters/sender/jdk/.classpath
new file mode 100644
index 00000000000..8b7ca245ba4
--- /dev/null
+++ b/exporters/sender/jdk/.classpath
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/sender/jdk/.project b/exporters/sender/jdk/.project
new file mode 100644
index 00000000000..22dbff2f078
--- /dev/null
+++ b/exporters/sender/jdk/.project
@@ -0,0 +1,34 @@
+
+
+ jdk
+ OpenTelemetry JDK HttpSender
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518880
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/sender/jdk/.settings/org.eclipse.buildship.core.prefs b/exporters/sender/jdk/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/sender/jdk/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/sender/jdk/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/sender/jdk/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/sender/jdk/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/sender/jdk/.settings/org.eclipse.jdt.core.prefs b/exporters/sender/jdk/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/sender/jdk/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/sender/okhttp/.classpath b/exporters/sender/okhttp/.classpath
new file mode 100644
index 00000000000..671f1cc9982
--- /dev/null
+++ b/exporters/sender/okhttp/.classpath
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/sender/okhttp/.project b/exporters/sender/okhttp/.project
new file mode 100644
index 00000000000..bab7a0e095d
--- /dev/null
+++ b/exporters/sender/okhttp/.project
@@ -0,0 +1,34 @@
+
+
+ okhttp
+ OpenTelemetry OkHttp Senders
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518928
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/sender/okhttp/.settings/org.eclipse.buildship.core.prefs b/exporters/sender/okhttp/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..98da5219f1f
--- /dev/null
+++ b/exporters/sender/okhttp/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../../..
+eclipse.preferences.version=1
diff --git a/exporters/sender/okhttp/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/sender/okhttp/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/sender/okhttp/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/sender/okhttp/.settings/org.eclipse.jdt.core.prefs b/exporters/sender/okhttp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/sender/okhttp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/RetryInterceptor.java b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/RetryInterceptor.java
index 988c8277c26..f79b3a04c67 100644
--- a/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/RetryInterceptor.java
+++ b/exporters/sender/okhttp/src/main/java/io/opentelemetry/exporter/sender/okhttp/internal/RetryInterceptor.java
@@ -13,6 +13,7 @@
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
+import java.util.Locale;
import java.util.StringJoiner;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -170,6 +171,24 @@ static boolean isRetryableException(IOException e) {
} else if (e instanceof SocketException) {
return true;
}
+
+ Throwable cause = e.getCause();
+ if (cause != null) {
+ logger.log(Level.WARNING, cause.getMessage(), cause);
+ }
+ if (cause instanceof InterruptedException) {
+ // The request was cancelled.
+ return true;
+ }
+
+ if (e.getMessage() != null) {
+ logger.log(Level.WARNING, e.getMessage(), e);
+ String msg = e.getMessage().toLowerCase(Locale.ROOT);
+ return msg.contains("connection aborted")
+ || msg.contains("canceled")
+ || msg.contains("connection reset by peer")
+ || msg.contains("socket closed");
+ }
return false;
}
diff --git a/exporters/zipkin/.classpath b/exporters/zipkin/.classpath
new file mode 100644
index 00000000000..43e466cb72d
--- /dev/null
+++ b/exporters/zipkin/.classpath
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exporters/zipkin/.project b/exporters/zipkin/.project
new file mode 100644
index 00000000000..54156336236
--- /dev/null
+++ b/exporters/zipkin/.project
@@ -0,0 +1,34 @@
+
+
+ zipkin
+ OpenTelemetry - Zipkin Exporter
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519113
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/exporters/zipkin/.settings/org.eclipse.buildship.core.prefs b/exporters/zipkin/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/exporters/zipkin/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/exporters/zipkin/.settings/org.eclipse.jdt.apt.core.prefs b/exporters/zipkin/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/exporters/zipkin/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/exporters/zipkin/.settings/org.eclipse.jdt.core.prefs b/exporters/zipkin/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/exporters/zipkin/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/extensions/.project b/extensions/.project
new file mode 100644
index 00000000000..0efbcfc9a43
--- /dev/null
+++ b/extensions/.project
@@ -0,0 +1,28 @@
+
+
+ extensions
+ Project extensions created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518801
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/extensions/.settings/org.eclipse.buildship.core.prefs b/extensions/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/extensions/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/extensions/.settings/org.eclipse.jdt.apt.core.prefs b/extensions/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/extensions/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/extensions/.settings/org.eclipse.jdt.core.prefs b/extensions/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/extensions/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/extensions/kotlin/.classpath b/extensions/kotlin/.classpath
new file mode 100644
index 00000000000..6308dbfc670
--- /dev/null
+++ b/extensions/kotlin/.classpath
@@ -0,0 +1,362 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/kotlin/.project b/extensions/kotlin/.project
new file mode 100644
index 00000000000..f20d5dad6af
--- /dev/null
+++ b/extensions/kotlin/.project
@@ -0,0 +1,34 @@
+
+
+ kotlin
+ OpenTelemetry Kotlin Extensions
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518888
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/extensions/kotlin/.settings/org.eclipse.buildship.core.prefs b/extensions/kotlin/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/extensions/kotlin/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/extensions/kotlin/.settings/org.eclipse.jdt.apt.core.prefs b/extensions/kotlin/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/extensions/kotlin/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/extensions/kotlin/.settings/org.eclipse.jdt.core.prefs b/extensions/kotlin/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..1b6cb7d0bc6
--- /dev/null
+++ b/extensions/kotlin/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#
+#Fri Oct 24 16:43:00 CEST 2025
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.compliance=17
diff --git a/extensions/trace-propagators/.classpath b/extensions/trace-propagators/.classpath
new file mode 100644
index 00000000000..60a4d5f9c27
--- /dev/null
+++ b/extensions/trace-propagators/.classpath
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/trace-propagators/.project b/extensions/trace-propagators/.project
new file mode 100644
index 00000000000..a4849368393
--- /dev/null
+++ b/extensions/trace-propagators/.project
@@ -0,0 +1,34 @@
+
+
+ trace-propagators
+ OpenTelemetry Extension : Trace Propagators
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519081
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/extensions/trace-propagators/.settings/org.eclipse.buildship.core.prefs b/extensions/trace-propagators/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/extensions/trace-propagators/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/extensions/trace-propagators/.settings/org.eclipse.jdt.apt.core.prefs b/extensions/trace-propagators/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/extensions/trace-propagators/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/extensions/trace-propagators/.settings/org.eclipse.jdt.core.prefs b/extensions/trace-propagators/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/extensions/trace-propagators/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/gradle.properties b/gradle.properties
index eec3cefe1fb..e2fad7c2ec3 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -13,3 +13,8 @@ systemProp.org.gradle.internal.http.connectionTimeout=120000
systemProp.org.gradle.internal.http.socketTimeout=120000
systemProp.org.gradle.internal.repository.max.retries=10
systemProp.org.gradle.internal.repository.initial.backoff=500
+
+org.gradle.java.home=C:\\Program Files\\SapMachine\\JDK\\21
+org.gradle.configuration-cache=false
+# org.gradle.java.installations.auto-detect=false
+# org.gradle.java.installations.fromEnv=JAVA_HOME
\ No newline at end of file
diff --git a/integration-tests/.classpath b/integration-tests/.classpath
new file mode 100644
index 00000000000..beaaf26ae23
--- /dev/null
+++ b/integration-tests/.classpath
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/.project b/integration-tests/.project
new file mode 100644
index 00000000000..ec5723a96d6
--- /dev/null
+++ b/integration-tests/.project
@@ -0,0 +1,34 @@
+
+
+ integration-tests
+ OpenTelemetry Integration Tests
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518843
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/integration-tests/.settings/org.eclipse.buildship.core.prefs b/integration-tests/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/integration-tests/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/integration-tests/.settings/org.eclipse.jdt.apt.core.prefs b/integration-tests/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/integration-tests/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/integration-tests/.settings/org.eclipse.jdt.core.prefs b/integration-tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/integration-tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/integration-tests/graal-incubating/.classpath b/integration-tests/graal-incubating/.classpath
new file mode 100644
index 00000000000..500c18331ce
--- /dev/null
+++ b/integration-tests/graal-incubating/.classpath
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/graal-incubating/.project b/integration-tests/graal-incubating/.project
new file mode 100644
index 00000000000..64d44c70833
--- /dev/null
+++ b/integration-tests/graal-incubating/.project
@@ -0,0 +1,34 @@
+
+
+ graal-incubating
+ OpenTelemetry Graal Integration Tests (Incubating)
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518822
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/integration-tests/graal-incubating/.settings/org.eclipse.buildship.core.prefs b/integration-tests/graal-incubating/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/integration-tests/graal-incubating/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/integration-tests/graal-incubating/.settings/org.eclipse.jdt.apt.core.prefs b/integration-tests/graal-incubating/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/integration-tests/graal-incubating/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/integration-tests/graal-incubating/.settings/org.eclipse.jdt.core.prefs b/integration-tests/graal-incubating/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/integration-tests/graal-incubating/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/integration-tests/graal/.classpath b/integration-tests/graal/.classpath
new file mode 100644
index 00000000000..a8a91ddd821
--- /dev/null
+++ b/integration-tests/graal/.classpath
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/graal/.project b/integration-tests/graal/.project
new file mode 100644
index 00000000000..e6c1f9c15e4
--- /dev/null
+++ b/integration-tests/graal/.project
@@ -0,0 +1,34 @@
+
+
+ graal
+ OpenTelemetry Graal Integration Tests
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518811
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/integration-tests/graal/.settings/org.eclipse.buildship.core.prefs b/integration-tests/graal/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/integration-tests/graal/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/integration-tests/graal/.settings/org.eclipse.jdt.apt.core.prefs b/integration-tests/graal/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/integration-tests/graal/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/integration-tests/graal/.settings/org.eclipse.jdt.core.prefs b/integration-tests/graal/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/integration-tests/graal/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/integration-tests/otlp/.classpath b/integration-tests/otlp/.classpath
new file mode 100644
index 00000000000..1c5fd97f4a7
--- /dev/null
+++ b/integration-tests/otlp/.classpath
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/otlp/.project b/integration-tests/otlp/.project
new file mode 100644
index 00000000000..a4566be0462
--- /dev/null
+++ b/integration-tests/otlp/.project
@@ -0,0 +1,34 @@
+
+
+ integration-tests-otlp
+ OTLP Exporter Integration Tests
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518857
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/integration-tests/otlp/.settings/org.eclipse.buildship.core.prefs b/integration-tests/otlp/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/integration-tests/otlp/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/integration-tests/otlp/.settings/org.eclipse.jdt.apt.core.prefs b/integration-tests/otlp/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/integration-tests/otlp/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/integration-tests/otlp/.settings/org.eclipse.jdt.core.prefs b/integration-tests/otlp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/integration-tests/otlp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/integration-tests/tracecontext/.classpath b/integration-tests/tracecontext/.classpath
new file mode 100644
index 00000000000..c8377ee2ce8
--- /dev/null
+++ b/integration-tests/tracecontext/.classpath
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/tracecontext/.project b/integration-tests/tracecontext/.project
new file mode 100644
index 00000000000..aba3bf99e0d
--- /dev/null
+++ b/integration-tests/tracecontext/.project
@@ -0,0 +1,34 @@
+
+
+ tracecontext
+ OpenTelemetry W3C Context Propagation Integration Tests
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519100
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/integration-tests/tracecontext/.settings/org.eclipse.buildship.core.prefs b/integration-tests/tracecontext/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/integration-tests/tracecontext/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/integration-tests/tracecontext/.settings/org.eclipse.jdt.apt.core.prefs b/integration-tests/tracecontext/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/integration-tests/tracecontext/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/integration-tests/tracecontext/.settings/org.eclipse.jdt.core.prefs b/integration-tests/tracecontext/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/integration-tests/tracecontext/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/javadoc-crawler/.classpath b/javadoc-crawler/.classpath
new file mode 100644
index 00000000000..6af84c891d1
--- /dev/null
+++ b/javadoc-crawler/.classpath
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/javadoc-crawler/.project b/javadoc-crawler/.project
new file mode 100644
index 00000000000..77b49bb90f7
--- /dev/null
+++ b/javadoc-crawler/.project
@@ -0,0 +1,34 @@
+
+
+ javadoc-crawler
+ OpenTelemetry Javadoc Crawler
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518874
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/javadoc-crawler/.settings/org.eclipse.buildship.core.prefs b/javadoc-crawler/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/javadoc-crawler/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/javadoc-crawler/.settings/org.eclipse.jdt.apt.core.prefs b/javadoc-crawler/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/javadoc-crawler/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/javadoc-crawler/.settings/org.eclipse.jdt.core.prefs b/javadoc-crawler/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/javadoc-crawler/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/opencensus-shim/.classpath b/opencensus-shim/.classpath
new file mode 100644
index 00000000000..3e4c320fcb3
--- /dev/null
+++ b/opencensus-shim/.classpath
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/opencensus-shim/.project b/opencensus-shim/.project
new file mode 100644
index 00000000000..63c1585fee9
--- /dev/null
+++ b/opencensus-shim/.project
@@ -0,0 +1,34 @@
+
+
+ opencensus-shim
+ OpenTelemetry OpenCensus Shim
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518935
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/opencensus-shim/.settings/org.eclipse.buildship.core.prefs b/opencensus-shim/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/opencensus-shim/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/opencensus-shim/.settings/org.eclipse.jdt.apt.core.prefs b/opencensus-shim/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/opencensus-shim/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/opencensus-shim/.settings/org.eclipse.jdt.core.prefs b/opencensus-shim/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/opencensus-shim/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/opentracing-shim/.classpath b/opentracing-shim/.classpath
new file mode 100644
index 00000000000..cee03568ab8
--- /dev/null
+++ b/opentracing-shim/.classpath
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/opentracing-shim/.factorypath b/opentracing-shim/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/opentracing-shim/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/opentracing-shim/.project b/opentracing-shim/.project
new file mode 100644
index 00000000000..3785ab5647b
--- /dev/null
+++ b/opentracing-shim/.project
@@ -0,0 +1,34 @@
+
+
+ opentracing-shim
+ OpenTelemetry OpenTracing Bridge
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518976
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/opentracing-shim/.settings/org.eclipse.buildship.core.prefs b/opentracing-shim/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/opentracing-shim/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/opentracing-shim/.settings/org.eclipse.jdt.apt.core.prefs b/opentracing-shim/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/opentracing-shim/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/opentracing-shim/.settings/org.eclipse.jdt.core.prefs b/opentracing-shim/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/opentracing-shim/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/perf-harness/.classpath b/perf-harness/.classpath
new file mode 100644
index 00000000000..22e1c1951b3
--- /dev/null
+++ b/perf-harness/.classpath
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/perf-harness/.project b/perf-harness/.project
new file mode 100644
index 00000000000..0f92be2c515
--- /dev/null
+++ b/perf-harness/.project
@@ -0,0 +1,34 @@
+
+
+ perf-harness
+ Performance Testing Harness
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519003
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/perf-harness/.settings/org.eclipse.buildship.core.prefs b/perf-harness/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/perf-harness/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/perf-harness/.settings/org.eclipse.jdt.apt.core.prefs b/perf-harness/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/perf-harness/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/perf-harness/.settings/org.eclipse.jdt.core.prefs b/perf-harness/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/perf-harness/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk-extensions/.project b/sdk-extensions/.project
new file mode 100644
index 00000000000..18a5170dea7
--- /dev/null
+++ b/sdk-extensions/.project
@@ -0,0 +1,28 @@
+
+
+ sdk-extensions
+ Project sdk-extensions created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519042
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk-extensions/.settings/org.eclipse.buildship.core.prefs b/sdk-extensions/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/sdk-extensions/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/sdk-extensions/.settings/org.eclipse.jdt.apt.core.prefs b/sdk-extensions/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk-extensions/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk-extensions/.settings/org.eclipse.jdt.core.prefs b/sdk-extensions/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/sdk-extensions/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/sdk-extensions/autoconfigure-spi/.classpath b/sdk-extensions/autoconfigure-spi/.classpath
new file mode 100644
index 00000000000..d80d37f5a47
--- /dev/null
+++ b/sdk-extensions/autoconfigure-spi/.classpath
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk-extensions/autoconfigure-spi/.project b/sdk-extensions/autoconfigure-spi/.project
new file mode 100644
index 00000000000..9feeb46a1c7
--- /dev/null
+++ b/sdk-extensions/autoconfigure-spi/.project
@@ -0,0 +1,34 @@
+
+
+ autoconfigure-spi
+ OpenTelemetry SDK Auto-configuration SPI
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518694
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.buildship.core.prefs b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.apt.core.prefs b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.core.prefs b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk-extensions/autoconfigure-spi/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk-extensions/autoconfigure/.classpath b/sdk-extensions/autoconfigure/.classpath
new file mode 100644
index 00000000000..5a31b206a5b
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.classpath
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk-extensions/autoconfigure/.factorypath b/sdk-extensions/autoconfigure/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk-extensions/autoconfigure/.project b/sdk-extensions/autoconfigure/.project
new file mode 100644
index 00000000000..0b517194df1
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.project
@@ -0,0 +1,34 @@
+
+
+ autoconfigure
+ OpenTelemetry SDK Auto-configuration
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518678
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk-extensions/autoconfigure/.settings/org.eclipse.buildship.core.prefs b/sdk-extensions/autoconfigure/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.apt.core.prefs b/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.core.prefs b/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk-extensions/autoconfigure/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk-extensions/incubator/.classpath b/sdk-extensions/incubator/.classpath
new file mode 100644
index 00000000000..5929df03307
--- /dev/null
+++ b/sdk-extensions/incubator/.classpath
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk-extensions/incubator/.factorypath b/sdk-extensions/incubator/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk-extensions/incubator/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk-extensions/incubator/.project b/sdk-extensions/incubator/.project
new file mode 100644
index 00000000000..2ce3bdf58d9
--- /dev/null
+++ b/sdk-extensions/incubator/.project
@@ -0,0 +1,34 @@
+
+
+ sdk-extensions-incubator
+ OpenTelemetry SDK Incubator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519052
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk-extensions/incubator/.settings/org.eclipse.buildship.core.prefs b/sdk-extensions/incubator/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk-extensions/incubator/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk-extensions/incubator/.settings/org.eclipse.jdt.apt.core.prefs b/sdk-extensions/incubator/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk-extensions/incubator/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk-extensions/incubator/.settings/org.eclipse.jdt.core.prefs b/sdk-extensions/incubator/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk-extensions/incubator/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java
deleted file mode 100644
index 317091fbf19..00000000000
--- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.sdk.extension.incubator.fileconfig;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import com.google.common.collect.ImmutableMap;
-import io.opentelemetry.api.incubator.config.DeclarativeConfigException;
-import io.opentelemetry.internal.testing.CleanupExtension;
-import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
-import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.component.SamplerComponentProvider;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOffSamplerModel;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOnSamplerModel;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.JaegerRemoteSamplerModel;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ParentBasedSamplerModel;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SamplerModel;
-import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TraceIdRatioBasedSamplerModel;
-import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler;
-import java.io.Closeable;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-// Suppress logs from JaegerRemoteSampler
-@SuppressLogger(
- loggerName = "io.opentelemetry.sdk.extension.trace.jaeger.sampler.OkHttpGrpcService")
-class SamplerFactoryTest {
-
- @RegisterExtension CleanupExtension cleanup = new CleanupExtension();
-
- private final DeclarativeConfigContext context =
- new DeclarativeConfigContext(SpiHelper.create(SamplerFactoryTest.class.getClassLoader()));
-
- @ParameterizedTest
- @MethodSource("createArguments")
- void create(
- @Nullable SamplerModel model, io.opentelemetry.sdk.trace.samplers.Sampler expectedSampler) {
- // Some samplers like JaegerRemoteSampler are Closeable - ensure these get cleaned up
- if (expectedSampler instanceof Closeable) {
- cleanup.addCloseable((Closeable) expectedSampler);
- }
-
- List closeables = new ArrayList<>();
- io.opentelemetry.sdk.trace.samplers.Sampler sampler =
- SamplerFactory.getInstance().create(model, context);
- cleanup.addCloseables(closeables);
-
- assertThat(sampler.toString()).isEqualTo(expectedSampler.toString());
- }
-
- private static Stream createArguments() {
- return Stream.of(
- Arguments.of(
- new SamplerModel().withAlwaysOn(new AlwaysOnSamplerModel()),
- io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOn()),
- Arguments.of(
- new SamplerModel().withAlwaysOff(new AlwaysOffSamplerModel()),
- io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOff()),
- Arguments.of(
- new SamplerModel().withTraceIdRatioBased(new TraceIdRatioBasedSamplerModel()),
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(1.0d)),
- Arguments.of(
- new SamplerModel()
- .withTraceIdRatioBased(new TraceIdRatioBasedSamplerModel().withRatio(0.5d)),
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.5)),
- Arguments.of(
- new SamplerModel().withParentBased(new ParentBasedSamplerModel()),
- io.opentelemetry.sdk.trace.samplers.Sampler.parentBased(
- io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOn())),
- Arguments.of(
- new SamplerModel()
- .withParentBased(
- new ParentBasedSamplerModel()
- .withRoot(
- new SamplerModel()
- .withTraceIdRatioBased(
- new TraceIdRatioBasedSamplerModel().withRatio(0.1d)))
- .withRemoteParentSampled(
- new SamplerModel()
- .withTraceIdRatioBased(
- new TraceIdRatioBasedSamplerModel().withRatio(0.2d)))
- .withRemoteParentNotSampled(
- new SamplerModel()
- .withTraceIdRatioBased(
- new TraceIdRatioBasedSamplerModel().withRatio(0.3d)))
- .withLocalParentSampled(
- new SamplerModel()
- .withTraceIdRatioBased(
- new TraceIdRatioBasedSamplerModel().withRatio(0.4d)))
- .withLocalParentNotSampled(
- new SamplerModel()
- .withTraceIdRatioBased(
- new TraceIdRatioBasedSamplerModel().withRatio(0.5d)))),
- io.opentelemetry.sdk.trace.samplers.Sampler.parentBasedBuilder(
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.1d))
- .setRemoteParentSampled(
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.2d))
- .setRemoteParentNotSampled(
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.3d))
- .setLocalParentSampled(
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.4d))
- .setLocalParentNotSampled(
- io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.5d))
- .build()),
- Arguments.of(
- new SamplerModel()
- .withJaegerRemote(
- new JaegerRemoteSamplerModel()
- .withEndpoint("http://jaeger-remote-endpoint")
- .withInterval(10_000)
- .withInitialSampler(
- new SamplerModel().withAlwaysOff(new AlwaysOffSamplerModel()))),
- JaegerRemoteSampler.builder()
- .setEndpoint("http://jaeger-remote-endpoint")
- .setPollingInterval(Duration.ofSeconds(10))
- .setInitialSampler(io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOff())
- .build()));
- }
-
- @Test
- void create_SpiExporter_Unknown() {
- List closeables = new ArrayList<>();
-
- assertThatThrownBy(
- () ->
- SamplerFactory.getInstance()
- .create(
- new SamplerModel()
- .withAdditionalProperty(
- "unknown_key", ImmutableMap.of("key1", "value1")),
- context))
- .isInstanceOf(DeclarativeConfigException.class)
- .hasMessage(
- "No component provider detected for io.opentelemetry.sdk.trace.samplers.Sampler with name \"unknown_key\".");
- cleanup.addCloseables(closeables);
- }
-
- @Test
- void create_SpiExporter_Valid() {
- io.opentelemetry.sdk.trace.samplers.Sampler sampler =
- SamplerFactory.getInstance()
- .create(
- new SamplerModel()
- .withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
- context);
- assertThat(sampler).isInstanceOf(SamplerComponentProvider.TestSampler.class);
- assertThat(((SamplerComponentProvider.TestSampler) sampler).config.getString("key1"))
- .isEqualTo("value1");
- }
-}
diff --git a/sdk-extensions/jaeger-remote-sampler/.classpath b/sdk-extensions/jaeger-remote-sampler/.classpath
new file mode 100644
index 00000000000..d4b28a396c9
--- /dev/null
+++ b/sdk-extensions/jaeger-remote-sampler/.classpath
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk-extensions/jaeger-remote-sampler/.project b/sdk-extensions/jaeger-remote-sampler/.project
new file mode 100644
index 00000000000..516dfa61b2b
--- /dev/null
+++ b/sdk-extensions/jaeger-remote-sampler/.project
@@ -0,0 +1,34 @@
+
+
+ jaeger-remote-sampler
+ OpenTelemetry - Jaeger Remote sampler
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518864
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.buildship.core.prefs b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.apt.core.prefs b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.core.prefs b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk-extensions/jaeger-remote-sampler/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/OkHttpGrpcService.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/OkHttpGrpcService.java
index ca1455ad3f3..5fdab67f268 100644
--- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/OkHttpGrpcService.java
+++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/OkHttpGrpcService.java
@@ -67,6 +67,7 @@ public SamplingStrategyResponseUnMarshaler execute(
// be gRPC status information available handled below though, so ignore this exception
// and continue through gRPC error handling logic. In the worst case we will record the
// HTTP error.
+ logger.log(Level.FINE, ignored.getMessage(), ignored);
}
String status = grpcStatus(response);
diff --git a/sdk/.project b/sdk/.project
new file mode 100644
index 00000000000..a4d680398df
--- /dev/null
+++ b/sdk/.project
@@ -0,0 +1,28 @@
+
+
+ sdk
+ Project sdk created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519023
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/.settings/org.eclipse.buildship.core.prefs b/sdk/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/sdk/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/sdk/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/.settings/org.eclipse.jdt.core.prefs b/sdk/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..18a4adcfa8d
--- /dev/null
+++ b/sdk/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=17
diff --git a/sdk/all/.classpath b/sdk/all/.classpath
new file mode 100644
index 00000000000..058c39c1aa5
--- /dev/null
+++ b/sdk/all/.classpath
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/all/.project b/sdk/all/.project
new file mode 100644
index 00000000000..988a68318ad
--- /dev/null
+++ b/sdk/all/.project
@@ -0,0 +1,34 @@
+
+
+ sdk-all
+ OpenTelemetry SDK
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519028
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/all/.settings/org.eclipse.buildship.core.prefs b/sdk/all/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/all/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/all/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/all/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/all/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/all/.settings/org.eclipse.jdt.core.prefs b/sdk/all/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk/all/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/common/.classpath b/sdk/common/.classpath
new file mode 100644
index 00000000000..fe4c094a3bc
--- /dev/null
+++ b/sdk/common/.classpath
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/common/.factorypath b/sdk/common/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk/common/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk/common/.project b/sdk/common/.project
new file mode 100644
index 00000000000..c251624172b
--- /dev/null
+++ b/sdk/common/.project
@@ -0,0 +1,34 @@
+
+
+ sdk-common
+ OpenTelemetry SDK Common
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519034
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/common/.settings/org.eclipse.buildship.core.prefs b/sdk/common/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/common/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/common/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/common/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/common/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/common/.settings/org.eclipse.jdt.core.prefs b/sdk/common/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk/common/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/common/build.gradle.kts b/sdk/common/build.gradle.kts
index c092ec21448..cc51a205c3e 100644
--- a/sdk/common/build.gradle.kts
+++ b/sdk/common/build.gradle.kts
@@ -13,7 +13,7 @@ otelJava.moduleName.set("io.opentelemetry.sdk.common")
dependencies {
api(project(":api:all"))
- compileOnly(project(":api:incubator"))
+ api(project(":api:incubator"))
annotationProcessor("com.google.auto.value:auto-value")
diff --git a/sdk/logs/.classpath b/sdk/logs/.classpath
new file mode 100644
index 00000000000..99880bf55f9
--- /dev/null
+++ b/sdk/logs/.classpath
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/logs/.factorypath b/sdk/logs/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk/logs/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk/logs/.project b/sdk/logs/.project
new file mode 100644
index 00000000000..8d7a36acbaf
--- /dev/null
+++ b/sdk/logs/.project
@@ -0,0 +1,34 @@
+
+
+ logs
+ OpenTelemetry Log SDK
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518912
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/logs/.settings/org.eclipse.buildship.core.prefs b/sdk/logs/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/logs/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/logs/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/logs/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/logs/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/logs/.settings/org.eclipse.jdt.core.prefs b/sdk/logs/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..164ab938d2b
--- /dev/null
+++ b/sdk/logs/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,15 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/logs/build.gradle.kts b/sdk/logs/build.gradle.kts
index b205b03e90e..14508b2714f 100644
--- a/sdk/logs/build.gradle.kts
+++ b/sdk/logs/build.gradle.kts
@@ -12,7 +12,7 @@ otelJava.moduleName.set("io.opentelemetry.sdk.logs")
dependencies {
api(project(":api:all"))
api(project(":sdk:common"))
- compileOnly(project(":api:incubator"))
+ api(project(":api:incubator"))
annotationProcessor("com.google.auto.value:auto-value")
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditException.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditException.java
new file mode 100644
index 00000000000..02330524dde
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditException.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import java.util.Collection;
+import java.util.Collections;
+import javax.annotation.Nullable;
+
+public class AuditException extends RuntimeException {
+
+ private static final long serialVersionUID = 5791873097754062413L;
+
+ @Nullable public Context context;
+
+ public Collection logRecords;
+
+ private AuditException(@Nullable String message, @Nullable Throwable cause) {
+ super(message, cause);
+ logRecords = Collections.emptyList();
+ }
+
+ AuditException(String message, @Nullable Throwable cause, Collection logs) {
+ this(message, cause);
+ this.logRecords = logs;
+ }
+
+ AuditException(Throwable cause, Context context, Collection logs) {
+ super(cause);
+ this.logRecords = logs;
+ this.context = context;
+ }
+}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditExceptionHandler.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditExceptionHandler.java
new file mode 100644
index 00000000000..c9fe7ec60aa
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditExceptionHandler.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+public interface AuditExceptionHandler {
+
+ void handle(AuditException exception);
+}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessor.java
new file mode 100644
index 00000000000..61ae3ebafb6
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessor.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.LongCounter;
+import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.common.export.RetryPolicy;
+import io.opentelemetry.sdk.logs.LogRecordProcessor;
+import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Queue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nullable;
+
+/**
+ * An implementation of {@link LogRecordProcessor} that processes logs for auditing purposes. It has
+ * an automatic retry mechanism implemented, in case the exporter takes longer or throws exceptions.
+ * Internally it uses a priority (-> LogLevel) queue for the log messages and the given {@link
+ * AuditLogStore} for persistence, which holds the logs until they are successfully exported. At
+ * startup, it loads all previously persisted logs from the {@link AuditLogStore} and adds them to
+ * the queue for processing. Logs with higher severity are processed first. The processor
+ * periodically checks the queue and exports logs in batches, regardless of the queue size. If the
+ * queue reaches a certain size, it triggers an immediate export. If an export fails, it retries
+ * exporting the logs with exponential backoff. When the maximum number of retry attempts is
+ * reached, it either throws an {@link AuditException} or calls the provided {@link
+ * AuditExceptionHandler}.
+ */
+public final class AuditLogRecordProcessor implements LogRecordProcessor {
+
+ /**
+ * Returns a new Builder for {@link AuditLogRecordProcessor}.
+ *
+ * @param logRecordExporter the {@link LogRecordExporter} to which the Logs are pushed.
+ * OtlpGrpcLogRecordExporter is a good choice.
+ * @return a new {@link AuditLogRecordProcessor}.
+ * @throws NullPointerException if the {@code logRecordExporter} is {@code null}.
+ */
+ public static AuditLogRecordProcessorBuilder builder(
+ LogRecordExporter logRecordExporter, AuditLogStore logStore) {
+ return new AuditLogRecordProcessorBuilder(logRecordExporter, logStore);
+ }
+
+ /** Current retry attempt counter. */
+ private final AtomicInteger currentRetryAttempt = new AtomicInteger(0);
+
+ /** The exporter to export logs. OtlpGrpcLogRecordExporter is recommended. */
+ private final LogRecordExporter exporter;
+
+ private final ScheduledFuture> future;
+
+ /** The exception handler to handle exceptions during log export. */
+ @Nullable private final AuditExceptionHandler handler;
+
+ @Nullable private CompletableResultCode lastResultCode;
+
+ /** Last retry timestamp to implement backpressure. */
+ private final AtomicLong lastRetryTimestamp = new AtomicLong(0);
+
+ /** The persistent storage for logs. */
+ private final AuditLogStore persistency;
+
+ private final Object storeLock = new Object();
+
+ /** The PriorityBlockingQueue to hold the logs before exporting. */
+ private final Queue queue;
+
+ /** The retry policy for handling failed exports. */
+ private final RetryPolicy retryPolicy;
+
+ private final ScheduledExecutorService scheduler;
+
+ /** A flag to indicate whether the processor is shutdown. */
+ private final AtomicBoolean shutdown = new AtomicBoolean(false);
+
+ /** The maximum number of logs to export in a single batch. */
+ private final int size;
+
+ /** The timeout for exporting logs in nanoseconds. */
+ private final long timeout;
+
+ /** Whether to wait for each export try to complete. */
+ private final boolean waitOnExport;
+
+ private final LongCounter processedLogsCounter;
+ private final LongCounter exportedLogsCounter;
+ private final LongCounter failedLogsCounter;
+
+ /** Attributes for metrics associated with the AuditLogRecordProcessor. */
+ private static final Attributes meterAttr =
+ Attributes.of(
+ BatchLogRecordProcessor.LOG_RECORD_PROCESSOR_TYPE_LABEL,
+ AuditLogRecordProcessor.class.getSimpleName());
+
+ /**
+ * Creates a new AuditLogRecordProcessor with the given parameters.
+ *
+ * @param logRecordExporter the {@link LogRecordExporter} to which the Logs are pushed.
+ * @param exceptionHandler the {@link AuditExceptionHandler} to handle exceptions during log
+ * export.
+ * @param scheduleDelayNanos the delay in nanoseconds between periodic exports.
+ * @param maxExportBatchSize the maximum number of logs to export in a single batch.
+ * @param exporterTimeoutNanos the timeout for exporting logs in nanoseconds.
+ * @param retryPolicy the retry policy for handling failed exports.
+ * @param waitOnExport whether to wait for the export to complete.
+ */
+ AuditLogRecordProcessor(
+ LogRecordExporter logRecordExporter,
+ @Nullable AuditExceptionHandler exceptionHandler,
+ AuditLogStore logStore,
+ MeterProvider meterProvider,
+ long scheduleDelayNanos,
+ int maxExportBatchSize,
+ long exporterTimeoutNanos,
+ RetryPolicy retryPolicy,
+ boolean waitOnExport) {
+ exporter = logRecordExporter;
+ size = maxExportBatchSize;
+ timeout = exporterTimeoutNanos;
+ handler = exceptionHandler;
+ this.retryPolicy = retryPolicy;
+ this.waitOnExport = waitOnExport;
+ queue =
+ new PriorityBlockingQueue<>(
+ maxExportBatchSize,
+ (record1, record2) -> {
+ // compare by severity, higher severity first
+ int severity =
+ Integer.compare(
+ record2.getSeverity().getSeverityNumber(),
+ record1.getSeverity().getSeverityNumber());
+ if (severity != 0) {
+ return severity;
+ }
+ // if severity is the same, compare by timestamp, older first
+ return Long.compare(
+ record1.getTimestampEpochNanos(), record2.getTimestampEpochNanos());
+ });
+ persistency = logStore;
+
+ Meter meter = meterProvider.meterBuilder("io.opentelemetry.sdk.logs").build();
+ meter
+ .gaugeBuilder("queueSize")
+ .ofLongs()
+ .setDescription("The number of items queued")
+ .setUnit("1")
+ .buildWithCallback(result -> result.record(queue.size(), meterAttr));
+ meter
+ .gaugeBuilder("persistencySize")
+ .ofLongs()
+ .setDescription("The number of persisted items")
+ .setUnit("1")
+ .buildWithCallback(result -> result.record(persistency.size(), meterAttr));
+ meter
+ .gaugeBuilder("retryAttempt")
+ .ofLongs()
+ .setDescription("The number of retry attempts made for the last export")
+ .setUnit("1")
+ .buildWithCallback(result -> result.record(currentRetryAttempt.get(), meterAttr));
+ processedLogsCounter =
+ meter
+ .counterBuilder("receivedLogs")
+ .setUnit("1")
+ .setDescription("The number of logs received for processing via onEmit().")
+ .build();
+ exportedLogsCounter =
+ meter
+ .counterBuilder("exportedLogs")
+ .setUnit("1")
+ .setDescription("The number of exported logs.")
+ .build();
+ failedLogsCounter =
+ meter
+ .counterBuilder("failedLogs")
+ .setUnit("1")
+ .setDescription("The number of logs that failed to be exported in the first place.")
+ .build();
+
+ // Get all logs from persistent storage and add them to the queue
+ queue.addAll(persistency.getAll());
+ // export logs immediately to ensure no logs are missed
+ if (!queue.isEmpty()) {
+ new Thread(this::exportLogs, "persisted-log-export-at-startup").start();
+ }
+
+ scheduler = Executors.newSingleThreadScheduledExecutor();
+ future =
+ scheduler.scheduleAtFixedRate(
+ () -> {
+ exportLogs(); // export logs periodically, regardless of the queue size
+ },
+ scheduleDelayNanos,
+ scheduleDelayNanos,
+ TimeUnit.NANOSECONDS);
+ }
+
+ private void addMissingToQueue(Collection logs) {
+ for (LogRecordData log : logs) {
+ if (!queue.contains(log)) {
+ queue.add(log);
+ }
+ }
+ }
+
+ /**
+ * Calculates the retry delay using exponential backoff with jitter.
+ *
+ * @param attemptNumber the current attempt number (1-based)
+ * @return delay in milliseconds
+ */
+ private long calculateRetryDelay(int attemptNumber) {
+ long delay =
+ (long)
+ (retryPolicy.getInitialBackoff().toMillis()
+ * Math.pow(retryPolicy.getBackoffMultiplier(), attemptNumber - 1));
+
+ // Cap the delay to maximum
+ delay = Math.min(delay, retryPolicy.getMaxBackoff().toMillis());
+
+ // Add jitter to prevent thundering herd (±25% random variation)
+ double jitter = 0.25 * delay * (Math.random() - 0.5);
+ delay += (long) jitter;
+
+ return Math.max(delay, 0); // Ensure non-negative delay
+ }
+
+ /**
+ * Exports logs from the queue to the exporter. If the queue is empty, it does nothing. If the
+ * export fails, it retries exporting logs with exponential backoff and handles exceptions using
+ * the provided handler.
+ */
+ void exportLogs() {
+ if (queue.isEmpty()) {
+ return;
+ }
+
+ // Check if we're in a backpressure period
+ long currentTime = System.currentTimeMillis();
+ if (currentRetryAttempt.get() > 0) {
+ long timeSinceLastRetry = currentTime - lastRetryTimestamp.get();
+ long requiredDelay = calculateRetryDelay(currentRetryAttempt.get());
+
+ if (timeSinceLastRetry < requiredDelay) {
+ // Still in backpressure period, skip this export attempt
+ return;
+ }
+ }
+
+ synchronized (queue) {
+ Collection results = new ArrayList<>();
+ Collection allFailedLogs = new HashSet<>();
+
+ while (!queue.isEmpty()) {
+ // Create a collection of LogRecordData from the queue with a maximum size
+ Object[] arr = queue.stream().limit(size).toArray();
+ Collection logs = new ArrayList<>(arr.length);
+ for (Object o : arr) {
+ logs.add((LogRecordData) o);
+ }
+
+ CompletableResultCode export = tryExport(logs);
+ export.whenComplete(
+ () -> {
+ if (export.isSuccess()) {
+ // Reset retry counter on successful export
+ exportedLogsCounter.add(logs.size(), meterAttr);
+ currentRetryAttempt.set(0);
+ lastRetryTimestamp.set(0);
+ synchronized (storeLock) {
+ // ensure no two threads write to persistency at the same time
+ // remove logs from persistency only on successful export
+ persistency.removeAll(logs);
+ }
+ } else {
+ failedLogsCounter.add(logs.size(), meterAttr);
+ allFailedLogs.addAll(
+ logs); // TODO evaluate partial failures and only add failed logs
+ }
+ });
+ results.add(export);
+
+ // Remove logs from queue regardless of success/failure to prevent infinite loops
+ queue.removeAll(logs);
+ }
+
+ CompletableResultCode all = CompletableResultCode.ofAll(results);
+ if (waitOnExport) {
+ all.join(timeout * results.size(), TimeUnit.NANOSECONDS);
+ }
+
+ if (all.isDone() && !all.isSuccess()) {
+ if (waitOnExport) {
+ // Export failed, prepare for retry if attempts remain
+ if (currentRetryAttempt.getAndAdd(1) < retryPolicy.getMaxAttempts()) {
+ lastRetryTimestamp.set(System.currentTimeMillis());
+ addMissingToQueue(allFailedLogs);
+ try {
+ Thread.sleep(calculateRetryDelay(currentRetryAttempt.get()));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ exportLogs(); // retry exporting failed logs
+ return;
+ }
+ }
+ // only, when we wait on export, we can really retry
+ handleExportFailure(allFailedLogs, all.getFailureThrowable());
+ }
+ lastResultCode = all;
+ }
+ }
+
+ /**
+ * Exports logs immediately, regardless of the queue size. This is useful for flushing logs when
+ * the processor is shutdown.
+ *
+ * @return {@link CompletableResultCode#ofSuccess()}.
+ */
+ @Override
+ public CompletableResultCode forceFlush() {
+ exportLogs();
+ return lastResultCode != null ? lastResultCode : CompletableResultCode.ofSuccess();
+ }
+
+ /**
+ * Returns the last export operation ({@link #exportLogs()}) result. If the processor was never
+ * triggered, it returns null. Useful to wait for the last export to finish via
+ * {@link CompletableResultCode#join(long, TimeUnit)}.
+ *
+ * @return CompletableResultCode from {@link LogRecordExporter#export(Collection)} of {@link
+ * #exporter}.
+ */
+ @Nullable
+ public CompletableResultCode getLastResultCode() {
+ return lastResultCode;
+ }
+
+ /**
+ * Handles export failure by updating retry state and potentially throwing exceptions.
+ *
+ * @param failedLogs the logs that failed to export
+ * @param cause the cause of the failure
+ */
+ private void handleExportFailure(
+ Collection failedLogs, @Nullable Throwable cause) {
+ // Re-add failed logs to the queue for potential retry
+ addMissingToQueue(failedLogs);
+ if (!waitOnExport && handler != null) {
+ handler.handle(new AuditException("Export failed", cause, failedLogs));
+ return;
+ }
+ if (currentRetryAttempt.get() < retryPolicy.getMaxAttempts()) {
+ // If retries haven't been exhausted, the retry logic will handle the next attempt
+ return;
+ }
+
+ // Max retries exceeded, reset counter and handle as final failure
+ currentRetryAttempt.set(0);
+ lastRetryTimestamp.set(0);
+
+ String message =
+ String.format(
+ Locale.ENGLISH,
+ "Export failed after %d retry attempts. Last error: %s",
+ retryPolicy.getMaxAttempts(),
+ cause != null ? cause.getMessage() : "Unknown error");
+
+ if (handler != null) {
+ handler.handle(new AuditException(message, cause, failedLogs));
+ } else {
+ throw new AuditException(message, cause, failedLogs);
+ }
+ }
+
+ /**
+ * Accepts a log record and adds it to the queue. If the processor is shutdown, it throws an
+ * exception or calls the handler.
+ *
+ * @param context the context of the log record.
+ * @param logRecord the log record to be processed.
+ */
+ @Override
+ public void onEmit(Context context, ReadWriteLogRecord logRecord) {
+ if (logRecord == null) {
+ return;
+ }
+
+ processedLogsCounter.add(1, meterAttr);
+
+ if (shutdown.get()) {
+ AuditException exception =
+ new AuditException(
+ new IllegalStateException(
+ "AuditLogRecordProcessor is shutdown, cannot accept new logs."),
+ context,
+ Collections.singletonList(logRecord.toLogRecordData()));
+ if (handler != null) {
+ handler.handle(exception);
+ } else {
+ throw exception;
+ }
+ }
+
+ try {
+ LogRecordData data = logRecord.toLogRecordData();
+ synchronized (storeLock) {
+ // ensure no two threads write to persistency at the same time
+ persistency.save(data);
+ }
+ queue.add(data);
+ } catch (IOException e) {
+ AuditException exception =
+ new AuditException(e, context, Collections.singletonList(logRecord.toLogRecordData()));
+ if (handler != null) {
+ handler.handle(exception);
+ } else {
+ throw exception;
+ }
+ }
+
+ if (queue.size() >= size) {
+ // when we have reached certain size, we export logs immediately
+ new Thread(this::exportLogs, "queue-size-reached-log-export").start();
+ }
+ }
+
+ /**
+ * Shuts down the processor. This method will export all remaining logs in the queue before
+ * shutting down. If this method is called multiple times, it will only export logs once.
+ *
+ * @return {@link CompletableResultCode#ofSuccess()}.
+ */
+ @Override
+ public CompletableResultCode shutdown() {
+ if (!shutdown.getAndSet(true)) {
+ // First time shutdown is called, we export all remaining logs
+ future.cancel(false);
+ scheduler.shutdown();
+ return forceFlush();
+ }
+ return lastResultCode != null ? lastResultCode : CompletableResultCode.ofSuccess();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("AuditLogRecordProcessor [exporter=");
+ builder.append(exporter);
+ builder.append(", handler=");
+ builder.append(handler);
+ builder.append(", queue=");
+ builder.append(queue);
+ builder.append(", shutdown=");
+ builder.append(shutdown);
+ builder.append(", size=");
+ builder.append(size);
+ builder.append(", timeout=");
+ builder.append(timeout);
+ builder.append(", retryPolicy=");
+ builder.append(retryPolicy);
+ builder.append(", persistency=");
+ builder.append(persistency);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /**
+ * Exports logs with retry logic and exponential backoff.
+ *
+ * @param logs the collection of logs to export
+ * @return CompletableResultCode representing the final result after all retry attempts
+ */
+ private CompletableResultCode tryExport(Collection logs) {
+ CompletableResultCode result = CompletableResultCode.ofFailure();
+ try {
+ result = exporter.export(logs);
+ // Wait for the export to complete with timeout
+ if (waitOnExport) {
+ result.join(timeout, TimeUnit.NANOSECONDS);
+ }
+ } catch (RuntimeException e) {
+ return CompletableResultCode.ofExceptionalFailure(e);
+ }
+ return result;
+ }
+}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorBuilder.java
new file mode 100644
index 00000000000..d8a5abe578b
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorBuilder.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+import static io.opentelemetry.api.internal.Utils.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import io.opentelemetry.api.metrics.MeterProvider;
+import io.opentelemetry.sdk.common.export.RetryPolicy;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Builder class for {@link AuditLogRecordProcessor}.
+ *
+ * @since 1.27.0
+ */
+public final class AuditLogRecordProcessorBuilder {
+
+ // Visible for testing
+ public static final int DEFAULT_EXPORT_TIMEOUT_MILLIS = 30_000;
+ // Visible for testing
+ public static final int DEFAULT_MAX_EXPORT_BATCH_SIZE = 512;
+ // Visible for testing
+ public static final long DEFAULT_SCHEDULE_DELAY_MILLIS = 1000;
+
+ @Nullable private AuditExceptionHandler exceptionHandler;
+
+ private long exporterTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(DEFAULT_EXPORT_TIMEOUT_MILLIS);
+
+ @Nonnull private final LogRecordExporter logRecordExporter;
+
+ @Nonnull private final AuditLogStore logStore;
+
+ private int maxExportBatchSize = DEFAULT_MAX_EXPORT_BATCH_SIZE;
+
+ private RetryPolicy retryPolicy = RetryPolicy.getDefault();
+
+ private MeterProvider meterProvider = MeterProvider.noop();
+
+ private long scheduleDelayNanos = TimeUnit.MILLISECONDS.toNanos(DEFAULT_SCHEDULE_DELAY_MILLIS);
+
+ private boolean waitOnExport = false;
+
+ AuditLogRecordProcessorBuilder(
+ @Nonnull LogRecordExporter logRecordExporter, @Nonnull AuditLogStore logStore) {
+ this.logRecordExporter = requireNonNull(logRecordExporter, "logRecordExporter");
+ this.logStore = requireNonNull(logStore, "logStore");
+ }
+
+ /**
+ * Returns a new {@link AuditLogRecordProcessor} that batches, then forwards them to the given
+ * {@code logRecordExporter}.
+ *
+ * @return a new {@link AuditLogRecordProcessor}.
+ */
+ public AuditLogRecordProcessor build() {
+ return new AuditLogRecordProcessor(
+ logRecordExporter,
+ exceptionHandler,
+ logStore,
+ meterProvider,
+ scheduleDelayNanos,
+ maxExportBatchSize,
+ exporterTimeoutNanos,
+ retryPolicy,
+ waitOnExport);
+ }
+
+ @Nullable
+ AuditExceptionHandler getExceptionHandler() {
+ return exceptionHandler;
+ }
+
+ // Visible for testing
+ long getExporterTimeoutNanos() {
+ return exporterTimeoutNanos;
+ }
+
+ AuditLogStore getLogStore() {
+ return logStore;
+ }
+
+ // Visible for testing
+ int getMaxExportBatchSize() {
+ return maxExportBatchSize;
+ }
+
+ // Visible for testing
+ RetryPolicy getRetryPolicy() {
+ return retryPolicy;
+ }
+
+ // Visible for testing
+ long getScheduleDelayNanos() {
+ return scheduleDelayNanos;
+ }
+
+ boolean isWaitOnExport() {
+ return waitOnExport;
+ }
+
+ public AuditLogRecordProcessorBuilder setExceptionHandler(
+ @Nonnull AuditExceptionHandler exceptionHandler) {
+ requireNonNull(exceptionHandler, "exceptionHandler");
+ this.exceptionHandler = exceptionHandler;
+ return this;
+ }
+
+ /**
+ * Sets the maximum time an export will be allowed to run before being cancelled. If unset,
+ * defaults to {@value DEFAULT_EXPORT_TIMEOUT_MILLIS}ms.
+ */
+ public AuditLogRecordProcessorBuilder setExporterTimeout(long timeout, @Nonnull TimeUnit unit) {
+ requireNonNull(unit, "unit");
+ checkArgument(timeout >= 0, "timeout must be non-negative");
+ exporterTimeoutNanos = timeout == 0 ? Long.MAX_VALUE : unit.toNanos(timeout);
+ return this;
+ }
+
+ /**
+ * Sets the maximum batch size for every export. This must be smaller or equal to {@code
+ * maxQueueSize}.
+ *
+ * Default value is {@code 512}.
+ *
+ * @param maxExportBatchSize the maximum batch size for every export.
+ * @return this.
+ * @see AuditLogRecordProcessorBuilder#DEFAULT_MAX_EXPORT_BATCH_SIZE
+ */
+ public AuditLogRecordProcessorBuilder setMaxExportBatchSize(int maxExportBatchSize) {
+ checkArgument(maxExportBatchSize > 0, "maxExportBatchSize must be positive.");
+ this.maxExportBatchSize = maxExportBatchSize;
+ return this;
+ }
+
+ /**
+ * Sets the retry policy for failed exports. If unset, defaults to {@link
+ * RetryPolicy#getDefault()}.
+ *
+ * @param retryPolicy the retry policy to use for failed exports
+ * @return this
+ */
+ public AuditLogRecordProcessorBuilder setRetryPolicy(@Nonnull RetryPolicy retryPolicy) {
+ requireNonNull(retryPolicy, "retryPolicy");
+ this.retryPolicy = retryPolicy;
+ return this;
+ }
+
+ /**
+ * Sets the {@link MeterProvider} to use to collect metrics related to batch export. If not set,
+ * metrics will not be collected.
+ */
+ public AuditLogRecordProcessorBuilder setMeterProvider(MeterProvider meterProvider) {
+ requireNonNull(meterProvider, "meterProvider");
+ this.meterProvider = meterProvider;
+ return this;
+ }
+
+ /**
+ * Sets the delay interval between two consecutive exports. If unset, defaults to {@value
+ * DEFAULT_SCHEDULE_DELAY_MILLIS}ms.
+ */
+ public AuditLogRecordProcessorBuilder setScheduleDelay(long delay, TimeUnit unit) {
+ requireNonNull(unit, "unit");
+ checkArgument(delay >= 0, "delay must be non-negative");
+ scheduleDelayNanos = unit.toNanos(delay);
+ return this;
+ }
+
+ /**
+ * Sets whether to wait for the export to complete before processing new logs. If unset, defaults
+ * to {@code false}.
+ */
+ public AuditLogRecordProcessorBuilder setWaitOnExport(boolean waitOnExport) {
+ this.waitOnExport = waitOnExport;
+ return this;
+ }
+}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogStore.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogStore.java
new file mode 100644
index 00000000000..49a553c6ab2
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/AuditLogStore.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import java.io.IOException;
+import java.util.Collection;
+
+public interface AuditLogStore {
+
+ void save(LogRecordData logRecord) throws IOException;
+
+ void removeAll(Collection logs);
+
+ Collection getAll();
+
+ /**
+ * Delegates to size of {@link #getAll()}.
+ *
+ * @return Returns the number of log records in the store.
+ */
+ default int size() {
+ return getAll().size();
+ }
+
+ /**
+ * Delegates to {@link #size()} == 0.
+ *
+ * @return Returns true if the store contains no log records.
+ */
+ default boolean isEmpty() {
+ return size() == 0;
+ }
+}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
index 601bfdfa208..fecfcf55cdf 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessor.java
@@ -44,7 +44,7 @@ public final class BatchLogRecordProcessor implements LogRecordProcessor {
private static final String WORKER_THREAD_NAME =
BatchLogRecordProcessor.class.getSimpleName() + "_WorkerThread";
- private static final AttributeKey LOG_RECORD_PROCESSOR_TYPE_LABEL =
+ static final AttributeKey LOG_RECORD_PROCESSOR_TYPE_LABEL =
AttributeKey.stringKey("processorType");
private static final AttributeKey LOG_RECORD_PROCESSOR_DROPPED_LABEL =
AttributeKey.booleanKey("dropped");
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java
index 33d1a1b726a..0fa6a97a0e8 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/MultiLogRecordExporter.java
@@ -36,23 +36,21 @@ private MultiLogRecordExporter(LogRecordExporter[] logRecordExporters) {
* @return the aggregate log exporter
*/
static LogRecordExporter create(List logRecordExporters) {
- return new MultiLogRecordExporter(logRecordExporters.toArray(new LogRecordExporter[0]));
+ return new MultiLogRecordExporter(
+ logRecordExporters.toArray(new LogRecordExporter[logRecordExporters.size()]));
}
@Override
public CompletableResultCode export(Collection logs) {
List results = new ArrayList<>(logRecordExporters.length);
for (LogRecordExporter logRecordExporter : logRecordExporters) {
- CompletableResultCode exportResult;
try {
- exportResult = logRecordExporter.export(logs);
+ results.add(logRecordExporter.export(logs));
} catch (RuntimeException e) {
// If an exception was thrown by the exporter
logger.log(Level.WARNING, "Exception thrown by the export.", e);
- results.add(CompletableResultCode.ofFailure());
- continue;
+ results.add(CompletableResultCode.ofExceptionalFailure(e));
}
- results.add(exportResult);
}
return CompletableResultCode.ofAll(results);
}
@@ -66,16 +64,13 @@ public CompletableResultCode export(Collection logs) {
public CompletableResultCode flush() {
List results = new ArrayList<>(logRecordExporters.length);
for (LogRecordExporter logRecordExporter : logRecordExporters) {
- CompletableResultCode flushResult;
try {
- flushResult = logRecordExporter.flush();
+ results.add(logRecordExporter.flush());
} catch (RuntimeException e) {
// If an exception was thrown by the exporter
logger.log(Level.WARNING, "Exception thrown by the flush.", e);
- results.add(CompletableResultCode.ofFailure());
- continue;
+ results.add(CompletableResultCode.ofExceptionalFailure(e));
}
- results.add(flushResult);
}
return CompletableResultCode.ofAll(results);
}
@@ -84,16 +79,13 @@ public CompletableResultCode flush() {
public CompletableResultCode shutdown() {
List results = new ArrayList<>(logRecordExporters.length);
for (LogRecordExporter logRecordExporter : logRecordExporters) {
- CompletableResultCode shutdownResult;
try {
- shutdownResult = logRecordExporter.shutdown();
+ results.add(logRecordExporter.shutdown());
} catch (RuntimeException e) {
// If an exception was thrown by the exporter
logger.log(Level.WARNING, "Exception thrown by the shutdown.", e);
- results.add(CompletableResultCode.ofFailure());
- continue;
+ results.add(CompletableResultCode.ofExceptionalFailure(e));
}
- results.add(shutdownResult);
}
return CompletableResultCode.ofAll(results);
}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorTest.java
new file mode 100644
index 00000000000..e9539b4305d
--- /dev/null
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/AuditLogRecordProcessorTest.java
@@ -0,0 +1,572 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.export;
+
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode;
+import static org.awaitility.Awaitility.await;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.logs.Logger;
+import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
+import io.opentelemetry.sdk.common.CompletableResultCode;
+import io.opentelemetry.sdk.common.export.RetryPolicy;
+import io.opentelemetry.sdk.logs.SdkLoggerProvider;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessorTest.CompletableLogRecordExporter;
+import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessorTest.WaitingLogRecordExporter;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nonnull;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+@SuppressWarnings("PreferJavaTimeOverload")
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class AuditLogRecordProcessorTest {
+
+ // Simple in-memory implementation for testing
+ static class InMemoryAuditLogStore implements AuditLogStore {
+ private final List logs = new ArrayList<>();
+
+ @Override
+ public Collection getAll() {
+ return logs;
+ }
+
+ @Override
+ public void removeAll(@Nonnull Collection logs) {
+ this.logs.removeAll(logs);
+ }
+
+ @Override
+ public void save(@Nonnull LogRecordData logRecord) {
+ logs.add(logRecord);
+ }
+ }
+
+ private static final String LOG_MESSAGE_1 = "Hello audit world 1!";
+ private static final String LOG_MESSAGE_2 = "Hello audit world 2!";
+
+ private static final long MAX_SCHEDULE_DELAY_MILLIS = 100;
+
+ private final AtomicLong logCount = new AtomicLong(0);
+ @Mock private AuditExceptionHandler mockExceptionHandler;
+ @Mock private LogRecordExporter mockLogRecordExporter;
+
+ @Mock private AuditLogStore mockLogStore;
+
+ @Test
+ void builderDefaults() {
+ AuditLogRecordProcessorBuilder builder =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore);
+ assertThat(builder.getScheduleDelayNanos())
+ .isEqualTo(
+ TimeUnit.MILLISECONDS.toNanos(
+ AuditLogRecordProcessorBuilder.DEFAULT_SCHEDULE_DELAY_MILLIS));
+ assertThat(builder.getMaxExportBatchSize())
+ .isEqualTo(AuditLogRecordProcessorBuilder.DEFAULT_MAX_EXPORT_BATCH_SIZE);
+ assertThat(builder.getExporterTimeoutNanos())
+ .isEqualTo(
+ TimeUnit.MILLISECONDS.toNanos(
+ AuditLogRecordProcessorBuilder.DEFAULT_EXPORT_TIMEOUT_MILLIS));
+ assertThat(builder.getRetryPolicy()).isEqualTo(RetryPolicy.getDefault());
+ }
+
+ @Test
+ void builderInvalidConfig() {
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setScheduleDelay(-1, TimeUnit.MILLISECONDS))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("delay must be non-negative");
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setScheduleDelay(1, null))
+ .isInstanceOf(NullPointerException.class)
+ .hasMessage("unit");
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setExporterTimeout(-1, TimeUnit.MILLISECONDS))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("timeout must be non-negative");
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setExporterTimeout(1, null))
+ .isInstanceOf(NullPointerException.class)
+ .hasMessage("unit");
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setMaxExportBatchSize(0))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("maxExportBatchSize must be positive.");
+ assertThatThrownBy(
+ () ->
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setRetryPolicy(null))
+ .isInstanceOf(NullPointerException.class)
+ .hasMessage("retryPolicy");
+ }
+
+ private void emitLog(SdkLoggerProvider sdkLoggerProvider, String message) {
+ Logger logger = sdkLoggerProvider.loggerBuilder(getClass().getName()).build();
+ logger
+ .logRecordBuilder()
+ .setBody(message)
+ .setAttribute(AttributeKey.longKey("logNo#"), logCount.incrementAndGet())
+ .emit();
+ }
+
+ @Test
+ void emitLogsToMultipleExporters() {
+ WaitingLogRecordExporter waitingLogRecordExporter1 =
+ new WaitingLogRecordExporter(2, CompletableResultCode.ofSuccess());
+ WaitingLogRecordExporter waitingLogRecordExporter2 =
+ new WaitingLogRecordExporter(2, CompletableResultCode.ofSuccess());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor(
+ AuditLogRecordProcessor.builder(
+ LogRecordExporter.composite(
+ Arrays.asList(waitingLogRecordExporter1, waitingLogRecordExporter2)),
+ logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .build())
+ .build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_2);
+ List exported1 = waitingLogRecordExporter1.waitForExport();
+ List exported2 = waitingLogRecordExporter2.waitForExport();
+ assertThat(exported1)
+ .hasSize(2)
+ .satisfiesExactly(
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1),
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_2));
+ assertThat(exported2)
+ .hasSize(2)
+ .satisfiesExactly(
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1),
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_2));
+ }
+
+ @Test
+ void emitMoreLogsThanBufferSize() {
+ CompletableLogRecordExporter logRecordExporter = new CompletableLogRecordExporter();
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor(
+ AuditLogRecordProcessor.builder(logRecordExporter, logStore)
+ .setMaxExportBatchSize(2)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .build())
+ .build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ logRecordExporter.succeed();
+
+ await()
+ .untilAsserted(
+ () ->
+ assertThat(logRecordExporter.getExported())
+ .hasSize(6)
+ .allSatisfy(logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1)));
+ }
+
+ @Test
+ void emitMultipleLogs() {
+ WaitingLogRecordExporter waitingLogRecordExporter =
+ new WaitingLogRecordExporter(2, CompletableResultCode.ofSuccess());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ SdkLoggerProvider loggerProvider =
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor(
+ AuditLogRecordProcessor.builder(waitingLogRecordExporter, logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .build())
+ .build();
+
+ emitLog(loggerProvider, LOG_MESSAGE_1);
+ emitLog(loggerProvider, LOG_MESSAGE_2);
+ List exported = waitingLogRecordExporter.waitForExport();
+ assertThat(exported)
+ .satisfiesExactly(
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1),
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_2));
+ }
+
+ @Test
+ void exceptionHandlerCalledOnStorageFailure() throws IOException {
+ doThrow(new IOException("Storage failed")).when(mockLogStore).save(any());
+
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, mockLogStore)
+ .setExceptionHandler(mockExceptionHandler)
+ .build();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ verify(mockExceptionHandler, times(1)).handle(any(AuditException.class));
+ }
+
+ @Test
+ @SuppressLogger(MultiLogRecordExporter.class)
+ void exporterThrowsException() throws Exception {
+ WaitingLogRecordExporter waitingLogRecordExporter =
+ new WaitingLogRecordExporter(1, CompletableResultCode.ofSuccess(), 10);
+ doThrow(new IllegalArgumentException("No export for you."))
+ .when(mockLogRecordExporter)
+ .export(anyList());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ AtomicBoolean wasCalled = new AtomicBoolean(false);
+ AuditExceptionHandler exceptionHandler =
+ exception -> {
+ wasCalled.set(true);
+ assertThat(exception.logRecords).isNotNull();
+ assertThat(exception.logRecords).isNotEmpty();
+ };
+
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(
+ LogRecordExporter.composite(
+ Arrays.asList(mockLogRecordExporter, waitingLogRecordExporter)),
+ logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .setExceptionHandler(exceptionHandler)
+ .build();
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ List exported = waitingLogRecordExporter.waitForExport();
+ waitOn(processor);
+
+ assertThat(wasCalled.get()).isTrue();
+
+ assertThat(exported)
+ .satisfiesExactly(logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1));
+ waitingLogRecordExporter.reset();
+ wasCalled.set(false);
+ // Continue to export after the exception was received.
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_2);
+
+ exported = waitingLogRecordExporter.waitForExport();
+ // both log records should be exported now, because the first one was not successfully exported
+ // due to the IllegalArgumentException
+ assertThat(exported)
+ .satisfiesExactly(
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_1),
+ logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_2));
+
+ assertThat(wasCalled.get()).isTrue();
+ }
+
+ @Test
+ void exporterThrowsException2() throws Exception {
+ doThrow(new IllegalArgumentException("No export for you."))
+ .when(mockLogRecordExporter)
+ .export(anyList());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ AtomicBoolean wasCalled = new AtomicBoolean(false);
+ AuditExceptionHandler exceptionHandler =
+ exception -> {
+ wasCalled.set(true);
+ assertThat(exception.logRecords).isNotNull();
+ assertThat(exception.logRecords).isNotEmpty();
+ };
+
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .setExceptionHandler(exceptionHandler)
+ .build();
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ waitOn(processor);
+
+ assertThat(wasCalled.get()).isTrue();
+ }
+
+ @Test
+ void forceFlush() {
+ WaitingLogRecordExporter waitingLogRecordExporter =
+ new WaitingLogRecordExporter(100, CompletableResultCode.ofSuccess(), 1);
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ AuditLogRecordProcessor auditLogRecordProcessor =
+ AuditLogRecordProcessor.builder(waitingLogRecordExporter, logStore)
+ .setScheduleDelay(1, TimeUnit.MINUTES)
+ .build();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(auditLogRecordProcessor).build();
+
+ for (int i = 0; i < 50; i++) {
+ emitLog(sdkLoggerProvider, "notExported");
+ }
+ List exported = waitingLogRecordExporter.waitForExport();
+ assertThat(exported).isNotNull();
+ assertThat(exported.size()).isEqualTo(0); // timer based export did not happen yet
+
+ // Force a flush, which should export all logs.
+ auditLogRecordProcessor.forceFlush().join(10, TimeUnit.SECONDS);
+
+ exported = waitingLogRecordExporter.waitForExport();
+ assertThat(exported).isNotNull();
+ assertThat(exported.size()).isEqualTo(50);
+ }
+
+ @Test
+ void ignoresNullLogs() {
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+ try (AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore).build()) {
+ assertThatCode(() -> processor.onEmit(null, null)).doesNotThrowAnyException();
+ processor.shutdown();
+ }
+ }
+
+ @BeforeEach
+ void setUp() {
+ when(mockLogRecordExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess());
+ when(mockLogStore.getAll()).thenReturn(new ArrayList<>());
+ }
+
+ @Test
+ void shutdownAfterEmitThrowsException() {
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore)
+ .setExceptionHandler(mockExceptionHandler)
+ .build();
+
+ processor.shutdown();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ verify(mockExceptionHandler, times(1)).handle(any(AuditException.class));
+ }
+
+ @Test
+ @Timeout(10)
+ void shutdownFlushes() {
+ WaitingLogRecordExporter waitingLogRecordExporter =
+ new WaitingLogRecordExporter(1, CompletableResultCode.ofSuccess());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder()
+ .addLogRecordProcessor(
+ AuditLogRecordProcessor.builder(waitingLogRecordExporter, logStore)
+ .setScheduleDelay(10, TimeUnit.SECONDS)
+ .build())
+ .build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_2);
+
+ // Force a shutdown, which forces processing of all remaining logs.
+ sdkLoggerProvider.shutdown().join(10, TimeUnit.SECONDS);
+
+ List exported = waitingLogRecordExporter.getExported();
+ assertThat(exported)
+ .satisfiesExactly(logRecordData -> assertThat(logRecordData).hasBody(LOG_MESSAGE_2));
+ }
+
+ @Test
+ void shutdownPropagatesFailure() {
+ when(mockLogRecordExporter.shutdown()).thenReturn(CompletableResultCode.ofFailure());
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+ try (AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore).build()) {
+ CompletableResultCode result = processor.shutdown();
+ result.join(1, TimeUnit.SECONDS);
+ assertThat(result.isSuccess()).isTrue();
+ }
+ }
+
+ @Test
+ void shutdownPropagatesSuccess() throws IOException {
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore).build();
+ CompletableResultCode result = processor.shutdown();
+ result.join(1, TimeUnit.SECONDS);
+ assertThat(result.isSuccess()).isTrue();
+ }
+
+ @Test
+ void testRetry() throws Exception {
+ when(mockLogRecordExporter.export(anyList()))
+ .thenThrow(new IllegalArgumentException("No export for you.")) // first call, fails
+ .thenThrow(new IllegalArgumentException("No export for you again.")) // second call, fails
+ .thenReturn(CompletableResultCode.ofSuccess());
+
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ AtomicBoolean wasCalled = new AtomicBoolean(false);
+ AuditExceptionHandler exceptionHandler =
+ exception -> {
+ wasCalled.set(true);
+ assertThat(exception.logRecords).isNotNull();
+ assertThat(exception.logRecords).isNotEmpty();
+ };
+
+ RetryPolicy retryPolicy =
+ RetryPolicy.builder()
+ .setMaxAttempts(3)
+ .setInitialBackoff(Duration.ofMillis(1))
+ .setMaxBackoff(Duration.ofMillis(1))
+ .build();
+
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .setExceptionHandler(exceptionHandler)
+ .setWaitOnExport(true) // enable
+ // waiting
+ // on
+ // export
+ // to
+ // ensure
+ // retries
+ // are
+ // attempted
+ .setMaxExportBatchSize(1) // ensure each log is exported individually
+ .setRetryPolicy(retryPolicy)
+ .build();
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ waitOn(processor);
+
+ assertThat(processor.getLastResultCode().isDone()).isTrue();
+ assertThat(processor.getLastResultCode().isSuccess()).isTrue();
+ assertThat(wasCalled.get()).isFalse(); // should be false as the third attempt should succeed
+ }
+
+ @Test
+ void testRetryFails() throws Exception {
+ doThrow(new IllegalArgumentException("No export for you."))
+ .when(mockLogRecordExporter)
+ .export(anyList());
+
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+
+ AtomicBoolean wasCalled = new AtomicBoolean(false);
+ AuditExceptionHandler exceptionHandler =
+ exception -> {
+ wasCalled.set(true);
+ assertThat(exception.logRecords).isNotNull();
+ assertThat(exception.logRecords).isNotEmpty();
+ };
+
+ RetryPolicy retryPolicy =
+ RetryPolicy.builder()
+ .setMaxAttempts(2) // Only 1 retry attempt (2 total attempts)
+ .setInitialBackoff(Duration.ofMillis(1))
+ .setMaxBackoff(Duration.ofMillis(1))
+ .build();
+
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore)
+ .setScheduleDelay(MAX_SCHEDULE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
+ .setExceptionHandler(exceptionHandler)
+ .setWaitOnExport(true) // enable
+ // waiting
+ // on
+ // export
+ // to
+ // ensure
+ // retries
+ // are
+ // attempted
+ .setMaxExportBatchSize(1) // ensure each log is exported individually
+ .setRetryPolicy(retryPolicy)
+ .build();
+ SdkLoggerProvider sdkLoggerProvider =
+ SdkLoggerProvider.builder().addLogRecordProcessor(processor).build();
+
+ emitLog(sdkLoggerProvider, LOG_MESSAGE_1);
+
+ waitOn(processor);
+
+ assertThat(wasCalled.get()).isTrue(); // should be true as all retry attempts fail
+ assertThat(processor.getLastResultCode().isDone()).isTrue();
+ assertThat(processor.getLastResultCode().isSuccess()).isFalse();
+ }
+
+ // Helper classes similar to BatchLogRecordProcessorTest
+
+ @Test
+ void toString_Valid() throws IOException {
+ when(mockLogRecordExporter.toString()).thenReturn("MockLogRecordExporter");
+ InMemoryAuditLogStore logStore = new InMemoryAuditLogStore();
+ AuditLogRecordProcessor processor =
+ AuditLogRecordProcessor.builder(mockLogRecordExporter, logStore).build();
+
+ String result = processor.toString();
+ assertThat(result).contains("AuditLogRecordProcessor");
+ assertThat(result).contains("MockLogRecordExporter");
+ }
+
+ void waitOn(AuditLogRecordProcessor processor) throws InterruptedException {
+ while (processor.getLastResultCode() == null) {
+ Thread.sleep(MAX_SCHEDULE_DELAY_MILLIS);
+ }
+ processor.getLastResultCode().join(1, TimeUnit.SECONDS);
+ }
+}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
index 4f388a5ca49..51bc99aecea 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogRecordProcessorTest.java
@@ -546,7 +546,7 @@ private void unblock() {
}
}
- private static class CompletableLogRecordExporter implements LogRecordExporter {
+ static class CompletableLogRecordExporter implements LogRecordExporter {
private final List results = new ArrayList<>();
@@ -657,6 +657,7 @@ public CompletableResultCode shutdown() {
public void reset() {
this.countDownLatch = new CountDownLatch(numberToWaitFor);
+ logRecordDataList.clear();
}
}
}
diff --git a/sdk/metrics/.classpath b/sdk/metrics/.classpath
new file mode 100644
index 00000000000..08399e9d924
--- /dev/null
+++ b/sdk/metrics/.classpath
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/metrics/.factorypath b/sdk/metrics/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk/metrics/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk/metrics/.project b/sdk/metrics/.project
new file mode 100644
index 00000000000..265222caea5
--- /dev/null
+++ b/sdk/metrics/.project
@@ -0,0 +1,34 @@
+
+
+ metrics
+ OpenTelemetry SDK Metrics
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518918
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/metrics/.settings/org.eclipse.buildship.core.prefs b/sdk/metrics/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/metrics/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/metrics/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/metrics/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/metrics/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/metrics/.settings/org.eclipse.jdt.core.prefs b/sdk/metrics/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..164ab938d2b
--- /dev/null
+++ b/sdk/metrics/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,15 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/testing/.classpath b/sdk/testing/.classpath
new file mode 100644
index 00000000000..f9f14a4dd29
--- /dev/null
+++ b/sdk/testing/.classpath
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/testing/.factorypath b/sdk/testing/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk/testing/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk/testing/.project b/sdk/testing/.project
new file mode 100644
index 00000000000..4289560b9f9
--- /dev/null
+++ b/sdk/testing/.project
@@ -0,0 +1,34 @@
+
+
+ testing
+ OpenTelemetry SDK Testing utilities
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519067
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/testing/.settings/org.eclipse.buildship.core.prefs b/sdk/testing/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/testing/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/testing/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/testing/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/testing/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/testing/.settings/org.eclipse.jdt.core.prefs b/sdk/testing/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk/testing/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/trace-shaded-deps/.classpath b/sdk/trace-shaded-deps/.classpath
new file mode 100644
index 00000000000..5509f8b33d4
--- /dev/null
+++ b/sdk/trace-shaded-deps/.classpath
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/trace-shaded-deps/.project b/sdk/trace-shaded-deps/.project
new file mode 100644
index 00000000000..b6d1be3038d
--- /dev/null
+++ b/sdk/trace-shaded-deps/.project
@@ -0,0 +1,34 @@
+
+
+ trace-shaded-deps
+ Internal use only - shaded dependencies of OpenTelemetry SDK for Tracing
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519091
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/trace-shaded-deps/.settings/org.eclipse.buildship.core.prefs b/sdk/trace-shaded-deps/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/trace-shaded-deps/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.core.prefs b/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk/trace-shaded-deps/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/sdk/trace/.classpath b/sdk/trace/.classpath
new file mode 100644
index 00000000000..da0fb2a31c0
--- /dev/null
+++ b/sdk/trace/.classpath
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/trace/.factorypath b/sdk/trace/.factorypath
new file mode 100644
index 00000000000..41ab5d87ea0
--- /dev/null
+++ b/sdk/trace/.factorypath
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/sdk/trace/.project b/sdk/trace/.project
new file mode 100644
index 00000000000..cd016dac984
--- /dev/null
+++ b/sdk/trace/.project
@@ -0,0 +1,34 @@
+
+
+ trace
+ OpenTelemetry SDK For Tracing
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184519073
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/sdk/trace/.settings/org.eclipse.buildship.core.prefs b/sdk/trace/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..62e3e7e80d9
--- /dev/null
+++ b/sdk/trace/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=../..
+eclipse.preferences.version=1
diff --git a/sdk/trace/.settings/org.eclipse.jdt.apt.core.prefs b/sdk/trace/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/sdk/trace/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/sdk/trace/.settings/org.eclipse.jdt.core.prefs b/sdk/trace/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/sdk/trace/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21
diff --git a/testing-internal/.classpath b/testing-internal/.classpath
new file mode 100644
index 00000000000..6c2713bb3d3
--- /dev/null
+++ b/testing-internal/.classpath
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing-internal/.project b/testing-internal/.project
new file mode 100644
index 00000000000..078544b4652
--- /dev/null
+++ b/testing-internal/.project
@@ -0,0 +1,34 @@
+
+
+ opentelemetry-java-testing-internal
+ OpenTelemetry Testing (Internal)
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ 1762184518970
+
+ 30
+
+ org.eclipse.core.resources.regexFilterMatcher
+ node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
+
+
+
+
diff --git a/testing-internal/.settings/org.eclipse.buildship.core.prefs b/testing-internal/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 00000000000..b1886adb46c
--- /dev/null
+++ b/testing-internal/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,2 @@
+connection.project.dir=..
+eclipse.preferences.version=1
diff --git a/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs b/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 00000000000..fa6bcfb3fdb
--- /dev/null
+++ b/testing-internal/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=.apt_generated
+org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
+org.eclipse.jdt.apt.reconcileEnabled=true
diff --git a/testing-internal/.settings/org.eclipse.jdt.core.prefs b/testing-internal/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..074474fbe12
--- /dev/null
+++ b/testing-internal/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=21