Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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