Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/all/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
description = "OpenTelemetry API"
otelJava.moduleName.set("io.opentelemetry.api")
base.archivesName.set("opentelemetry-api")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.sdk.autoconfigure", "io.opentelemetry.api.incubator"))

dependencies {
api(project(":context"))
Expand Down
1 change: 1 addition & 0 deletions api/incubator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {

description = "OpenTelemetry API Incubator"
otelJava.moduleName.set("io.opentelemetry.api.incubator")
otelJava.osgiOptionalPackages.set(listOf("com.fasterxml.jackson.databind"))

dependencies {
api(project(":api:all"))
Expand Down
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ repositories {
}

dependencies {
implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:7.2.0")
implementation(enforcedPlatform("com.squareup.wire:wire-bom:5.4.0"))
implementation("com.google.auto.value:auto-value-annotations:1.11.1")
// When updating, update above in plugins too
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
package io.opentelemetry.gradle

import org.gradle.api.JavaVersion
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property

abstract class OtelJavaExtension {
abstract val moduleName: Property<String>

abstract val osgiOptionalPackages: ListProperty<String>

abstract val minJavaVersionSupported: Property<JavaVersion>

init {
minJavaVersionSupported.convention(JavaVersion.VERSION_1_8)
osgiOptionalPackages.convention(emptyList<String>())
}
}
20 changes: 20 additions & 0 deletions buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
eclipse
idea

id("biz.aQute.bnd.builder")
id("otel.errorprone-conventions")
id("otel.jacoco-conventions")
id("otel.spotless-conventions")
Expand Down Expand Up @@ -142,6 +143,25 @@ tasks {
}
}

named<Jar>("jar") {
// Configure OSGi metadata
bundle {
// Compute import packages.
// Certain packages like javax.annotation.* are always optional.
// Modules may have additional optional packages, typically corresponding to compileOnly dependencies.
// Append wildcard "*" last to import any other referenced packages
val optionalPackages = mutableListOf("javax.annotation")
optionalPackages.addAll(otelJava.osgiOptionalPackages.get())
val importPackages = optionalPackages.joinToString(",") { it + ".*;resolution:=optional;version\"\${@}\"" } + ",*"

bnd(mapOf(
// Once https://github.com/open-telemetry/opentelemetry-java/issues/6970 is resolved, exclude .internal packages
"-exportcontents" to "io.opentelemetry.*",
"Import-Package" to importPackages
))
}
}

withType<Jar>().configureEach {
inputs.property("moduleName", otelJava.moduleName)

Expand Down
3 changes: 3 additions & 0 deletions dependencyManagement/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ val DEPENDENCY_BOMS = listOf(
"io.zipkin.brave:brave-bom:6.3.0",
"io.zipkin.reporter2:zipkin-reporter-bom:3.5.1",
"org.assertj:assertj-bom:3.27.6",
"org.osgi:org.osgi.test.bom:1.2.1",
"org.testcontainers:testcontainers-bom:2.0.3",
"org.snakeyaml:snakeyaml-engine:2.10"
)
Expand Down Expand Up @@ -87,12 +88,14 @@ val DEPENDENCIES = listOf(
"io.opentracing:opentracing-noop:0.33.0",
"junit:junit:4.13.2",
"nl.jqno.equalsverifier:equalsverifier:3.19.4",
"org.apache.felix:org.apache.felix.framework:7.0.5",
"org.awaitility:awaitility:4.3.0",
"org.bouncycastle:bcpkix-jdk15on:1.70",
"org.codehaus.mojo:animal-sniffer-annotations:1.26",
"org.jctools:jctools-core:4.0.5",
"org.junit-pioneer:junit-pioneer:1.9.1",
"org.mock-server:mockserver-netty:5.15.0:shaded",
"org.osgi:osgi.core:8.0.0",
"org.skyscreamer:jsonassert:1.5.3",
"com.android.tools:desugar_jdk_libs:2.1.5",
)
Expand Down
99 changes: 99 additions & 0 deletions integration-tests/osgi/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import aQute.bnd.gradle.Bundle
import aQute.bnd.gradle.Resolve
import aQute.bnd.gradle.TestOSGi

plugins {
id("otel.java-conventions")
}

description = "OpenTelemetry OSGi Integration Tests"
otelJava.moduleName.set("io.opentelemetry.integration.tests.osgi")

// For similar test examples see:
// https://github.com/micrometer-metrics/micrometer/tree/main/micrometer-osgi-test
// https://github.com/eclipse-osgi-technology/osgi-test/tree/main/examples/osgi-test-example-gradle

configurations.all {
resolutionStrategy {
// BND not compatible with JUnit 5.13+; see https://github.com/bndtools/bnd/issues/6651
val junitVersion = "5.12.2"
val junitLauncherVersion = "1.12.1"
force("org.junit.jupiter:junit-jupiter:$junitVersion")
force("org.junit.jupiter:junit-jupiter-api:$junitVersion")
force("org.junit.jupiter:junit-jupiter-params:$junitVersion")
force("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
force("org.junit.platform:junit-platform-launcher:$junitLauncherVersion")
}
}

dependencies {
// Testing the "kitchen sink" hides OSGi configuration issues. For example, opentelemetry-api has
// optional dependencies on :sdk-extensions:autoconfigure and :api:incubator. If we only test a
// bundle which includes those, then mask the fact that OSGi fails when using a bundle without those
// until opentelemetry-api OSGi configuration is updated to indicate that they are optional.

// TODO (jack-berg): Add additional test bundles with dependency combinations reflecting popular use cases:
// - with OTLP exporters
// - with autoconfigure
// - with file configuration
testImplementation(project(":sdk:all"))

// For some reason, changing this to testImplementation causes the tests to pass even when failures are present.
// Probably some dependency resolution interplay with otel.java-conventions but I couldn't figure it out.
implementation("org.junit.jupiter:junit-jupiter")

testCompileOnly("org.osgi:osgi.core")
testImplementation("org.osgi:org.osgi.test.junit5")
testImplementation("org.osgi:org.osgi.test.assertj.framework")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testRuntimeOnly("org.apache.felix:org.apache.felix.framework")
}

val testingBundleTask = tasks.register<Bundle>("testingBundle") {
archiveClassifier.set("testing")
from(sourceSets.test.get().output)
bundle {
bnd(
"Test-Cases: \${classes;HIERARCHY_INDIRECTLY_ANNOTATED;org.junit.platform.commons.annotation.Testable;CONCRETE}",
"Import-Package: javax.annotation.*;resolution:=optional;version=\"\${@}\",*"
)
}
}

val resolveTask = tasks.register<Resolve>("resolve") {
dependsOn(testingBundleTask)
project.ext.set("osgiRunee", "JavaSE-${java.toolchain.languageVersion.get()}")
description = "Resolve test.bndrun"
group = JavaBasePlugin.VERIFICATION_GROUP
bndrun = file("test.bndrun")
outputBndrun = layout.buildDirectory.file("test.bndrun")
bundles = files(sourceSets.test.get().runtimeClasspath, testingBundleTask.get().archiveFile)
}

val testOSGiTask = tasks.register<TestOSGi>("testOSGi") {
description = "OSGi Test test.bndrun"
group = JavaBasePlugin.VERIFICATION_GROUP
bndrun = resolveTask.flatMap { it.outputBndrun }
bundles = files(sourceSets.test.get().runtimeClasspath, testingBundleTask.get().archiveFile)
}

tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME) {
dependsOn(testOSGiTask)
}

tasks {
jar {
enabled = false
}
test {
// We need to replace junit testing with the testOSGi task, so we clear test actions and add a dependency on testOSGi.
// As a result, running :test runs only :testOSGi.
actions.clear()
dependsOn(testOSGiTask)
}
}

// Skip OWASP check
dependencyCheck {
skip = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.integrationtest.osgi;

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
import io.opentelemetry.sdk.metrics.InstrumentType;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collection;
import javax.annotation.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.osgi.framework.BundleContext;
import org.osgi.test.common.annotation.InjectBundleContext;
import org.osgi.test.junit5.context.BundleContextExtension;
import org.osgi.test.junit5.service.ServiceExtension;

@ExtendWith(BundleContextExtension.class)
@ExtendWith(ServiceExtension.class)
public class OpenTelemetryOsgiTest {

@InjectBundleContext @Nullable BundleContext bundleContext;

@BeforeEach
void setup() {
// Verify we're in an OSGi environment
assertThat(bundleContext).isNotNull();
}

@Test
public void vanillaSdkInitializes() {
OpenTelemetrySdk sdk =
OpenTelemetrySdk.builder()
.setMeterProvider(
SdkMeterProvider.builder()
.registerMetricReader(
PeriodicMetricReader.create(
new MetricExporter() {
@Override
public CompletableResultCode export(Collection<MetricData> metrics) {
return CompletableResultCode.ofSuccess();
}

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

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

@Override
public AggregationTemporality getAggregationTemporality(
InstrumentType instrumentType) {
return AggregationTemporality.CUMULATIVE;
}
}))
.build())
.setLoggerProvider(
SdkLoggerProvider.builder()
.addLogRecordProcessor(
SimpleLogRecordProcessor.create(
new LogRecordExporter() {
@Override
public CompletableResultCode export(Collection<LogRecordData> logs) {
return CompletableResultCode.ofSuccess();
}

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

@Override
public CompletableResultCode shutdown() {
return CompletableResultCode.ofSuccess();
}
}))
.build())
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(
SimpleSpanProcessor.create(
new SpanExporter() {
@Override
public CompletableResultCode export(Collection<SpanData> spans) {
return CompletableResultCode.ofSuccess();
}

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

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

assertThat(sdk).isNotNull();

// Verify Context API is available
Context current = Context.current();
assertThat(current).isNotNull();
}
}
8 changes: 8 additions & 0 deletions integration-tests/osgi/test.bndrun
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-tester: biz.aQute.tester.junit-platform
-runfw: org.apache.felix.framework
-runee: ${project.osgiRunee}

-runrequires: \
bnd.identity;id='opentelemetry-osgi-testing',\
bnd.identity;id='junit-jupiter-engine',\
bnd.identity;id='junit-platform-launcher'
1 change: 1 addition & 0 deletions sdk-extensions/autoconfigure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {

description = "OpenTelemetry SDK Auto-configuration"
otelJava.moduleName.set("io.opentelemetry.sdk.autoconfigure")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.sdk.extension.incubator"))

dependencies {
api(project(":sdk:all"))
Expand Down
1 change: 1 addition & 0 deletions sdk/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ apply<OtelVersionClassPlugin>()

description = "OpenTelemetry SDK Common"
otelJava.moduleName.set("io.opentelemetry.sdk.common")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.api.incubator"))

dependencies {
api(project(":api:all"))
Expand Down
1 change: 1 addition & 0 deletions sdk/logs/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {

description = "OpenTelemetry Log SDK"
otelJava.moduleName.set("io.opentelemetry.sdk.logs")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.api.incubator"))

dependencies {
api(project(":api:all"))
Expand Down
1 change: 1 addition & 0 deletions sdk/metrics/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {

description = "OpenTelemetry SDK Metrics"
otelJava.moduleName.set("io.opentelemetry.sdk.metrics")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.api.incubator"))

dependencies {
api(project(":api:all"))
Expand Down
1 change: 1 addition & 0 deletions sdk/trace/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {

description = "OpenTelemetry SDK For Tracing"
otelJava.moduleName.set("io.opentelemetry.sdk.trace")
otelJava.osgiOptionalPackages.set(listOf("io.opentelemetry.api.incubator"))

sourceSets {
main {
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ include(":integration-tests:otlp")
include(":integration-tests:tracecontext")
include(":integration-tests:graal")
include(":integration-tests:graal-incubating")
include(":integration-tests:osgi")
include(":javadoc-crawler")
include(":opencensus-shim")
include(":opentracing-shim")
Expand Down
Loading