Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize instrumentation-api and introduce jApiCmp checks #6566

Merged
Merged
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
12 changes: 12 additions & 0 deletions .github/workflows/reusable-assemble.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ jobs:
exit 1
fi

- name: Check for jApiCmp diffs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only run assemble above (not check or build), maybe add assemble jApiCmp above, or run jApiCmp on assemble (or even compileJava?) instead of on check

run: |
if git diff --quiet
then
echo "No diff detected."
else
echo "Diff detected - did you run './gradlew jApiCmp'?"
echo $(git diff --name-only)
echo $(git diff)
exit 1
fi

- name: Upload deadlock detector artifacts if any
if: always()
uses: actions/upload-artifact@v3
Expand Down
14 changes: 14 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ and deadlocks.
(note that if this is not a patch release then the change log on main may already be up-to-date,
in which case no pull request will be created).

## Update release versions in documentations

After releasing is done, you need to first update the docs. This needs to happen after artifacts have propagated
to Maven Central so should probably be done an hour or two after the release workflow finishes.

```sh
./gradlew japicmp -PapiBaseVersion=a.b.c -PapiNewVersion=x.y.z
./gradlew --refresh-dependencies japicmp
```

Where `x.y.z` is the version just released and `a.b.c` is the previous version.

Create a PR to mark the new release in docs on the main branch.

## Credentials

Same as the core repo, see [opentelemetry-java/RELEASING.md#credentials](https://github.com/open-telemetry/opentelemetry-java/blob/main/RELEASING.md#credentials).
83 changes: 56 additions & 27 deletions conventions/src/main/kotlin/otel.japicmp-conventions.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import japicmp.model.JApiChangeStatus
import me.champeau.gradle.japicmp.JapicmpTask
import me.champeau.gradle.japicmp.report.stdrules.RecordSeenMembersSetup
import me.champeau.gradle.japicmp.report.stdrules.SourceCompatibleRule
import me.champeau.gradle.japicmp.report.stdrules.UnchangedMemberRule

plugins {
base
Expand Down Expand Up @@ -43,36 +47,61 @@ fun findArtifact(version: String): File {
}
}

tasks {
val jApiCmp by registering(JapicmpTask::class) {
dependsOn("jar")
// generate the api diff report for any module that is stable
if (project.findProperty("otel.stable") == "true") {
afterEvaluate {
tasks {
val jApiCmp by registering(JapicmpTask::class) {
dependsOn("jar")

// the japicmp "new" version is either the user-specified one, or the locally built jar.
val apiNewVersion: String? by project
val newArtifact = apiNewVersion?.let { findArtifact(it) }
?: file(getByName<Jar>("jar").archiveFile)
newClasspath.from(files(newArtifact))
// the japicmp "new" version is either the user-specified one, or the locally built jar.
val apiNewVersion: String? by project
val newArtifact = apiNewVersion?.let { findArtifact(it) }
?: file(getByName<Jar>("jar").archiveFile)
newClasspath.from(files(newArtifact))

// only output changes, not everything
onlyModified.set(true)
// only output changes, not everything
onlyModified.set(true)

// the japicmp "old" version is either the user-specified one, or the latest release.
val apiBaseVersion: String? by project
val baselineVersion = apiBaseVersion ?: latestReleasedVersion
oldClasspath.from(try {
files(findArtifact(baselineVersion))
} catch (e: Exception) {
// if we can't find the baseline artifact, this is probably one that's never been published before,
// so publish the whole API. We do that by flipping this flag, and comparing the current against nothing.
onlyModified.set(false)
files()
})
// the japicmp "old" version is either the user-specified one, or the latest release.
val apiBaseVersion: String? by project
val baselineVersion = apiBaseVersion ?: latestReleasedVersion
oldClasspath.from(
try {
files(findArtifact(baselineVersion))
} catch (e: Exception) {
// if we can't find the baseline artifact, this is probably one that's never been published before,
// so publish the whole API. We do that by flipping this flag, and comparing the current against nothing.
onlyModified.set(false)
files()
}
)

// this is needed so that we only consider the current artifact, and not dependencies
ignoreMissingClasses.set(true)
packageExcludes.addAll("*.internal", "*.internal.*")
val baseVersionString = if (apiBaseVersion == null) "latest" else baselineVersion
val newVersionString = if (apiNewVersion == null) "current" else apiNewVersion
txtOutputFile.set(file("$rootDir/docs/apidiffs/${newVersionString}_vs_$baseVersionString/${base.archivesName.get()}.txt"))
// Reproduce defaults from https://github.com/melix/japicmp-gradle-plugin/blob/09f52739ef1fccda6b4310cf3f4b19dc97377024/src/main/java/me/champeau/gradle/japicmp/report/ViolationsGenerator.java#L130
// only changing the BinaryIncompatibleRule to our custom one that allows new default methods
// on interfaces, and adding default implementations to interface methods previously
// abstract.
richReport {
addSetupRule(RecordSeenMembersSetup::class.java)
addRule(JApiChangeStatus.NEW, SourceCompatibleRule::class.java)
addRule(JApiChangeStatus.MODIFIED, SourceCompatibleRule::class.java)
addRule(JApiChangeStatus.UNCHANGED, UnchangedMemberRule::class.java)
addRule(SourceCompatibleRule::class.java)
}

// this is needed so that we only consider the current artifact, and not dependencies
ignoreMissingClasses.set(true)
packageExcludes.addAll("*.internal", "*.internal.*")
val baseVersionString = if (apiBaseVersion == null) "latest" else baselineVersion
txtOutputFile.set(
apiNewVersion?.let { file("$rootDir/docs/apidiffs/${apiNewVersion}_vs_$baselineVersion/${base.archivesName.get()}.txt") }
?: file("$rootDir/docs/apidiffs/current_vs_$baseVersionString/${base.archivesName.get()}.txt")
)
}
// have the check task depend on the api comparison task, to make it more likely it will get used.
named("check") {
dependsOn(jApiCmp)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
Comparing source compatibility of against
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor constant(io.opentelemetry.api.common.AttributeKey, java.lang.Object)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void onEnd(io.opentelemetry.api.common.AttributesBuilder, io.opentelemetry.context.Context, java.lang.Object, java.lang.Object, java.lang.Throwable)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void onStart(io.opentelemetry.api.common.AttributesBuilder, io.opentelemetry.context.Context, java.lang.Object)
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.context.Context onStart(io.opentelemetry.context.Context, java.lang.Object, io.opentelemetry.api.common.Attributes)
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.Throwable extract(java.lang.Throwable)
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor jdk()
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW CLASS: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder builder(io.opentelemetry.api.OpenTelemetry, java.lang.String, io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor)
+++ NEW METHOD: PUBLIC(+) void end(io.opentelemetry.context.Context, java.lang.Object, java.lang.Object, java.lang.Throwable)
+++ NEW METHOD: PUBLIC(+) boolean shouldStart(io.opentelemetry.context.Context, java.lang.Object)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.context.Context start(io.opentelemetry.context.Context, java.lang.Object)
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addAttributesExtractor(io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addAttributesExtractors(java.lang.Iterable)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addContextCustomizer(io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addOperationListener(io.opentelemetry.instrumentation.api.instrumenter.OperationListener)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addOperationMetrics(io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder addSpanLinksExtractor(io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildClientInstrumenter(io.opentelemetry.context.propagation.TextMapSetter)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildConsumerInstrumenter(io.opentelemetry.context.propagation.TextMapGetter)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildInstrumenter()
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildInstrumenter(io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildProducerInstrumenter(io.opentelemetry.context.propagation.TextMapSetter)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.Instrumenter buildServerInstrumenter(io.opentelemetry.context.propagation.TextMapGetter)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder setEnabled(boolean)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder setErrorCauseExtractor(io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder setInstrumentationVersion(java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder setSchemaUrl(java.lang.String)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder setSpanStatusExtractor(io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor)
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.api.trace.Span current()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.api.trace.Span fromContext(io.opentelemetry.context.Context)
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.api.trace.Span fromContextOrNull(io.opentelemetry.context.Context)
+++ NEW ANNOTATION: javax.annotation.Nullable
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.OperationListener (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void onEnd(io.opentelemetry.context.Context, io.opentelemetry.api.common.Attributes, long)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.context.Context onStart(io.opentelemetry.context.Context, io.opentelemetry.api.common.Attributes, long)
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.OperationListener create(io.opentelemetry.api.metrics.Meter)
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor alwaysClient()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor alwaysConsumer()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor alwaysInternal()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor alwaysProducer()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor alwaysServer()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.api.trace.SpanKind extract(java.lang.Object)
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanLinksBuilder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanLinksBuilder addLink(io.opentelemetry.api.trace.SpanContext)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanLinksBuilder addLink(io.opentelemetry.api.trace.SpanContext, io.opentelemetry.api.common.Attributes)
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void extract(io.opentelemetry.instrumentation.api.instrumenter.SpanLinksBuilder, io.opentelemetry.context.Context, java.lang.Object)
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanLinksExtractor extractFromRequest(io.opentelemetry.context.propagation.TextMapPropagator, io.opentelemetry.context.propagation.TextMapGetter)
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.String extract(java.lang.Object)
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder setStatus(io.opentelemetry.api.trace.StatusCode)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder setStatus(io.opentelemetry.api.trace.StatusCode, java.lang.String)
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void extract(io.opentelemetry.instrumentation.api.instrumenter.SpanStatusBuilder, java.lang.Object, java.lang.Object, java.lang.Throwable)
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor getDefault()
+++ NEW ANNOTATION: java.lang.FunctionalInterface
+++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.instrumentation.api.util.ClassNames (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String simpleName(java.lang.Class)
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.instrumentation.api.util.VirtualField (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW CONSTRUCTOR: PUBLIC(+) VirtualField()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.instrumentation.api.util.VirtualField find(java.lang.Class, java.lang.Class)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.lang.Object get(java.lang.Object)
+++ NEW ANNOTATION: javax.annotation.Nullable
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(java.lang.Object, java.lang.Object)
1 change: 1 addition & 0 deletions instrumentation-api/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
otel.stable=true
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import static java.util.Collections.singleton;

import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressor.BySpanKey;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressor.DelegateBySpanKind;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressor.Noop;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressors.BySpanKey;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressors.DelegateBySpanKind;
import io.opentelemetry.instrumentation.api.instrumenter.SpanSuppressors.Noop;
import io.opentelemetry.instrumentation.api.internal.SpanKey;
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
import java.util.EnumMap;
Expand Down
Loading