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 .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@
/dd-java-agent/instrumentation/datadog/openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-smoke-tests/openfeature/ @DataDog/feature-flagging-and-experimentation-sdk
/dd-smoke-tests/openfeature-legacy/ @DataDog/feature-flagging-and-experimentation-sdk
/products/feature-flagging/ @DataDog/feature-flagging-and-experimentation-sdk

# @DataDog/profiling-java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
1 datadog.opentracing.*
1 datadog.slf4j.*
1 datadog.trace.*
# Legacy OpenFeature providers need compatibility advice after their bootstrap API was removed.
0 datadog.trace.api.openfeature.Provider
# remove this once https://github.com/raphw/byte-buddy/issues/558 is fixed
0 datadog.trace.bootstrap.instrumentation.java.concurrent.RunnableWrapper
1 datadog.trace.core.*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import static org.gradle.api.JavaVersion.VERSION_11

plugins {
id 'dd-trace-java.module.instrumentation'
}

// The providers released before the SDK bridge, linked to the agent bootstrap API it removed.
muzzle {
pass {
group = 'com.datadoghq'
module = 'dd-openfeature'
versions = '[1.56.0,1.69.0)'
}
}

tracerJava {
addSourceSetFor(VERSION_11)
}

dependencies {
main_java11CompileOnly 'com.datadoghq:dd-openfeature:1.56.0'
}

tasks.named("compileMain_java11Java", JavaCompile) {
configureCompiler(it, VERSION_11)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
# To regenerate this file, run: ./gradlew :dd-java-agent:instrumentation:datadog:openfeature:dd-openfeature-1.56:dependencies --write-locks
cafe.cryptography:curve25519-elisabeth:0.1.0=testRuntimeClasspath
cafe.cryptography:ed25519-elisabeth:0.1.0=testRuntimeClasspath
ch.qos.logback:logback-classic:1.2.13=testCompileClasspath,testRuntimeClasspath
ch.qos.logback:logback-core:1.2.13=testCompileClasspath,testRuntimeClasspath
com.blogspot.mydailyjava:weak-lock-free:0.17=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.datadoghq.okhttp3:okhttp:3.12.15=testCompileClasspath,testRuntimeClasspath
com.datadoghq.okio:okio:1.17.6=testCompileClasspath,testRuntimeClasspath
com.datadoghq:dd-instrument-java:0.0.6=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.datadoghq:dd-javac-plugin-client:0.2.2=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.datadoghq:dd-openfeature:1.56.0=main_java11CompileClasspath
com.datadoghq:dd-openfeature:1.67.0=legacySdk
com.datadoghq:java-dogstatsd-client:4.4.5=testRuntimeClasspath
com.datadoghq:sketches-java:0.8.3=testRuntimeClasspath
com.github.javaparser:javaparser-core:3.25.6=codenarc
com.github.jnr:jffi:1.3.15=testRuntimeClasspath
com.github.jnr:jnr-a64asm:1.0.0=testRuntimeClasspath
com.github.jnr:jnr-constants:0.10.4=testRuntimeClasspath
com.github.jnr:jnr-enxio:0.32.20=testRuntimeClasspath
com.github.jnr:jnr-ffi:2.2.19=testRuntimeClasspath
com.github.jnr:jnr-posix:3.1.22=testRuntimeClasspath
com.github.jnr:jnr-unixsocket:0.38.25=testRuntimeClasspath
com.github.jnr:jnr-x86asm:1.0.2=testRuntimeClasspath
com.github.spotbugs:spotbugs-annotations:4.10.4=compileClasspath,spotbugs
com.github.spotbugs:spotbugs:4.10.4=spotbugs
com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,testAnnotationProcessor,testCompileClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,testAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.14.0=spotbugs
com.google.errorprone:error_prone_annotations:2.18.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.47.0=testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.48.0=spotbugs
com.google.guava:failureaccess:1.0.1=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:32.0.1-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.6.0-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:2.8=annotationProcessor,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:3.1=testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.8=testRuntimeClasspath
com.squareup.moshi:moshi:1.11.0=testCompileClasspath,testRuntimeClasspath
com.squareup.okhttp3:logging-interceptor:3.12.12=testCompileClasspath,testRuntimeClasspath
com.squareup.okhttp3:okhttp:3.12.12=testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio:1.17.5=testCompileClasspath,testRuntimeClasspath
com.thoughtworks.qdox:qdox:1.12.1=codenarc
commons-fileupload:commons-fileupload:1.5=testCompileClasspath,testRuntimeClasspath
commons-io:commons-io:2.11.0=testCompileClasspath,testRuntimeClasspath
commons-io:commons-io:2.21.0=spotbugs
de.thetaphi:forbiddenapis:3.11=compileClasspath,testCompileClasspath,testRuntimeClasspath
dev.openfeature:sdk:1.18.2=main_java11CompileClasspath
io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath
io.sqreen:libsqreen:17.5.0=testRuntimeClasspath
javax.servlet:javax.servlet-api:3.1.0=testCompileClasspath,testRuntimeClasspath
jaxen:jaxen:2.0.6=spotbugs
junit:junit:4.13.2=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.18.12=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.12=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.java.dev.jna:jna-platform:5.8.0=testRuntimeClasspath
net.java.dev.jna:jna:5.8.0=testRuntimeClasspath
net.sf.saxon:Saxon-HE:12.10=spotbugs
org.apache.ant:ant-antlr:1.10.14=codenarc
org.apache.ant:ant-junit:1.10.14=codenarc
org.apache.bcel:bcel:6.12.0=spotbugs
org.apache.commons:commons-lang3:3.20.0=spotbugs
org.apache.commons:commons-text:1.15.0=spotbugs
org.apache.logging.log4j:log4j-api:2.26.1=spotbugs
org.apache.logging.log4j:log4j-core:2.26.1=spotbugs
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.33.0=annotationProcessor,testAnnotationProcessor
org.codehaus.groovy:groovy-ant:3.0.23=codenarc
org.codehaus.groovy:groovy-docgenerator:3.0.23=codenarc
org.codehaus.groovy:groovy-groovydoc:3.0.23=codenarc
org.codehaus.groovy:groovy-json:3.0.23=codenarc
org.codehaus.groovy:groovy-json:3.0.25=testCompileClasspath,testRuntimeClasspath
org.codehaus.groovy:groovy-templates:3.0.23=codenarc
org.codehaus.groovy:groovy-xml:3.0.23=codenarc
org.codehaus.groovy:groovy:3.0.23=codenarc
org.codehaus.groovy:groovy:3.0.25=testCompileClasspath,testRuntimeClasspath
org.codenarc:CodeNarc:3.7.0=codenarc
org.dom4j:dom4j:2.2.0=spotbugs
org.gmetrics:GMetrics:2.1.0=codenarc
org.hamcrest:hamcrest-core:1.3=testRuntimeClasspath
org.hamcrest:hamcrest:3.0=testCompileClasspath,testRuntimeClasspath
org.jctools:jctools-core-jdk11:4.0.6=testRuntimeClasspath
org.jctools:jctools-core:4.0.6=testRuntimeClasspath
org.jspecify:jspecify:1.0.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.14.1=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.14.1=testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.14.1=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter:5.14.1=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.14.1=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.14.1=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.14.1=testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.14.1=testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.14.1=testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.14.1=testRuntimeClasspath
org.junit:junit-bom:5.14.1=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:4.4.0=testRuntimeClasspath
org.objenesis:objenesis:3.3=testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:9.10.1=spotbugs
org.ow2.asm:asm-analysis:9.7.1=testRuntimeClasspath
org.ow2.asm:asm-commons:9.10.1=spotbugs,testRuntimeClasspath
org.ow2.asm:asm-tree:9.10.1=spotbugs,testRuntimeClasspath
org.ow2.asm:asm-util:9.10.1=spotbugs
org.ow2.asm:asm-util:9.7.1=testRuntimeClasspath
org.ow2.asm:asm:9.10.1=buildTimeInstrumentationPlugin,compileClasspath,main_java11CompileClasspath,main_java11RuntimeClasspath,muzzleTooling,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath
org.slf4j:log4j-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:1.7.30=buildTimeInstrumentationPlugin,compileClasspath,main_java11RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath
org.slf4j:slf4j-api:1.7.32=testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=main_java11CompileClasspath,spotbugsSlf4j
org.slf4j:slf4j-api:2.0.18=spotbugs
org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j
org.snakeyaml:snakeyaml-engine:2.9=buildTimeInstrumentationPlugin,main_java11RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath
org.spockframework:spock-bom:2.4-groovy-3.0=testCompileClasspath,testRuntimeClasspath
org.spockframework:spock-core:2.4-groovy-3.0=testCompileClasspath,testRuntimeClasspath
org.tabletest:tabletest-junit:1.2.2=testCompileClasspath,testRuntimeClasspath
org.tabletest:tabletest-parser:1.2.1=testCompileClasspath,testRuntimeClasspath
org.xmlresolver:xmlresolver:5.3.3=spotbugs
empty=main_java11AnnotationProcessor,spotbugsPlugins
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package datadog.trace.instrumentation.openfeature;

import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.declaresMethod;
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.namedOneOf;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;

import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.agent.tooling.InstrumenterModule;
import java.util.Set;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

/**
* Keeps legacy providers usable as default-value providers after their bootstrap API is removed.
*/
@SuppressWarnings("unused")
@AutoService(InstrumenterModule.class)
public class LegacyProviderInstrumentation extends InstrumenterModule
implements Instrumenter.ForSingleType,
Instrumenter.WithTypeStructure,
Instrumenter.HasMethodAdvice {
public LegacyProviderInstrumentation() {
super("openfeature");
}

@Override
protected boolean defaultEnabled() {
return true;
}

@Override
public boolean isApplicable(final Set<TargetSystem> enabledSystems) {
// Application safety must not depend on whether Feature Flags is enabled.
return true;
}

@Override
public String instrumentedType() {
return "datadog.trace.api.openfeature.Provider";
}

@Override
public ElementMatcher<TypeDescription> structureMatcher() {
// The current SDK's deprecated alias has no legacy evaluator to replace.
return declaresMethod(named("loadEvaluatorClass").and(takesArguments(0)));
}

@Override
public void methodAdvice(final MethodTransformer transformer) {
transformer.applyAdvice(
named("initialize").and(takesArguments(1)),
packageName + ".LegacyProviderAdvice$Initialize");
transformer.applyAdvice(
named("getProviderHooks").and(takesArguments(0)),
packageName + ".LegacyProviderAdvice$Hooks");
transformer.applyAdvice(
namedOneOf(
"getBooleanEvaluation",
"getStringEvaluation",
"getIntegerEvaluation",
"getDoubleEvaluation",
"getObjectEvaluation")
.and(takesArguments(3)),
packageName + ".LegacyProviderAdvice$Evaluation");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package datadog.trace.instrumentation.openfeature;

import static java.util.Collections.emptyList;
import static net.bytebuddy.asm.Advice.Argument;
import static net.bytebuddy.asm.Advice.OnMethodEnter;
import static net.bytebuddy.asm.Advice.OnMethodExit;
import static net.bytebuddy.asm.Advice.OnNonDefaultValue;
import static net.bytebuddy.asm.Advice.Return;

import dev.openfeature.sdk.ErrorCode;
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.Reason;
import java.util.List;
import org.slf4j.LoggerFactory;

/** Avoids linking legacy evaluators to the removed agent bootstrap API. */
@SuppressWarnings("unused")
public class LegacyProviderAdvice {
public static class Initialize {
@OnMethodEnter(skipOn = OnNonDefaultValue.class)
public static boolean skipLegacyInitialization() {
return true;
}

@OnMethodExit(suppress = Throwable.class)
public static void warn() {
LoggerFactory.getLogger("datadog.trace.api.openfeature.Provider")
.warn(
"This dd-openfeature version is incompatible with the Datadog Java agent;"
+ " returning caller defaults. Upgrade dd-openfeature to enable Feature Flags.");
}
}

public static class Hooks {
@OnMethodExit(suppress = Throwable.class)
public static void returnNoHooks(@Return(readOnly = false) List<?> hooks) {
hooks = emptyList();
}
}

public static class Evaluation {
@OnMethodEnter(skipOn = OnNonDefaultValue.class)
public static boolean skipLegacyEvaluation() {
return true;
}

@OnMethodExit(suppress = Throwable.class)
public static void returnDefault(
@Argument(1) final Object defaultValue,
@Return(readOnly = false) ProviderEvaluation<?> evaluation) {
evaluation =
ProviderEvaluation.builder()
.value(defaultValue)
.reason(Reason.ERROR.name())
.errorCode(ErrorCode.PROVIDER_NOT_READY)
.errorMessage("Upgrade dd-openfeature to enable Feature Flags with this Java agent")
.build();
}
}
}
46 changes: 46 additions & 0 deletions dd-smoke-tests/openfeature-legacy/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import static org.gradle.api.JavaVersion.VERSION_11

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
id 'application'
id 'com.gradleup.shadow'
id 'dd-trace-java.module.smoke-test'
}

description = 'Released dd-openfeature provider Smoke Tests.'

testJvmConstraints {
minJavaVersion = VERSION_11
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}

tasks.withType(JavaCompile).configureEach {
configureCompiler(it, VERSION_11)
}

application {
mainClass = 'datadog.smoketest.openfeature.legacy.LegacyProviderApplication'
}

dependencies {
// A provider released before the SDK bridge, linked to the agent bootstrap API it removed.
implementation 'com.datadoghq:dd-openfeature:1.67.1'
testImplementation project(':dd-smoke-tests')
}

tasks.withType(Test).configureEach {
def shadowJarTask = tasks.named('shadowJar', ShadowJar)
dependsOn shadowJarTask
jvmArgumentProviders.add(new CommandLineArgumentProvider() {
@Override
Iterable<String> asArguments() {
return shadowJarTask.map { ["-Ddatadog.smoketest.shadowJar.path=${it.archiveFile.get()}"] }.get()
}
})
}
Loading
Loading