Skip to content

Commit

Permalink
Stabilize instrumentation-api and introduce jApiCmp checks (open-tele…
Browse files Browse the repository at this point in the history
…metry#6566)

* Stabilize instrumentation-api and introduce jApiCmp checks

* Update

Co-authored-by: Trask Stalnaker <[email protected]>
  • Loading branch information
2 people authored and LironKS committed Oct 31, 2022
1 parent 3b94edc commit fb2e7bd
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 101 deletions.
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
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)
}
}
}
}
111 changes: 111 additions & 0 deletions docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt
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

0 comments on commit fb2e7bd

Please sign in to comment.