-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbuild.gradle
More file actions
275 lines (228 loc) · 8.8 KB
/
build.gradle
File metadata and controls
275 lines (228 loc) · 8.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
plugins {
id 'java'
id 'maven-publish'
id 'signing'
id 'com.vanniktech.maven.publish' version '0.28.0'
}
version = rootProject.version
group = rootProject.group
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
vendor = JvmVendorSpec.ADOPTIUM
}
}
tasks.withType(JavaCompile).configureEach {
options.release = 17
}
repositories {
mavenCentral()
}
// Shared config for all agent subprojects (bootstrap, internal)
subprojects {
apply plugin: 'java'
apply plugin: 'dev.braintrust.muzzle'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
vendor = JvmVendorSpec.ADOPTIUM
}
}
tasks.withType(JavaCompile).configureEach {
options.release = 17
}
repositories {
mavenCentral()
}
}
// Add muzzle generation task and muzzle check plugin to smoke-test test-instrumentation.
// (Instrumentation subprojects under :braintrust-sdk are configured in braintrust-sdk/build.gradle.)
subprojects { subproject ->
subproject.afterEvaluate {
if (subproject.path == ':braintrust-java-agent:smoke-test:test-instrumentation') {
def instrumentationApi = project(':braintrust-java-agent:instrumenter')
// Bootstrap classes (e.g. BraintrustBridge) are on the bootstrap classpath at runtime.
// Make them available at compile time so instrumentation modules can reference them.
dependencies.add('compileOnly', project(':braintrust-java-agent:bootstrap'))
// --- $Muzzle side-class generation (compile-time) ---
// Configuration for the muzzle generator classpath
configurations.maybeCreate('muzzleGenerator')
dependencies.add('muzzleGenerator', instrumentationApi)
dependencies.add('muzzleGenerator', 'net.bytebuddy:byte-buddy:1.17.5')
task generateMuzzle(type: JavaExec) {
dependsOn compileJava, instrumentationApi.tasks.named('compileJava')
description = 'Generates $Muzzle side-classes for InstrumentationModule subclasses'
group = 'build'
// Classpath: compiled instrumentation classes + instrumenter + bytebuddy + deps
classpath = files(
sourceSets.main.output.classesDirs,
configurations.muzzleGenerator,
configurations.compileClasspath
)
mainClass = 'dev.braintrust.instrumentation.muzzle.MuzzleGenerator'
args = [sourceSets.main.java.classesDirectory.get().asFile.absolutePath]
}
// Run muzzle generation after compileJava, before jar
tasks.named('classes').configure { dependsOn generateMuzzle }
// Run muzzle checks as part of the check lifecycle
tasks.named('check').configure { dependsOn 'muzzle' }
}
}
}
// No main source code — this project only assembles the agent JAR and runs tests.
sourceSets.main.java.srcDirs = []
configurations {
// Bootstrap classes (BraintrustAgent, BraintrustClassLoader, BraintrustAutoConfigCustomizer)
// — our code + META-INF/services, bundled as normal .class files
bootstrap
// Bootstrap libraries — unshaded, added to bootstrap classpath at runtime via
// Instrumentation.appendToBootstrapClassLoaderSearch(). Includes:
// - OTel API (Tracer, Span, Context, etc.)
// - OTel SDK (SdkTracerProvider, SpanProcessor, etc.)
// - OTel SDK autoconfigure (AutoConfiguredOpenTelemetrySdk)
// - OTel SDK autoconfigure SPI (AutoConfigurationCustomizerProvider)
bootstrapLibs
// Agent internals (ByteBuddy, OTLP exporter, OkHttp, instrumentation code)
// — hidden as .classdata under internal/, only loadable by BraintrustClassLoader
internal
}
dependencies {
bootstrap project(':braintrust-java-agent:bootstrap')
// OTel API + SDK + autoconfigure on bootstrap classpath
bootstrapLibs "io.opentelemetry:opentelemetry-api:${otelVersion}"
internal project(path: ':braintrust-java-agent:internal', configuration: 'shadow')
// Test dependencies
testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}"
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation "io.opentelemetry:opentelemetry-api:${otelVersion}"
testImplementation "org.slf4j:slf4j-simple:${slf4jVersion}"
testCompileOnly project(':braintrust-java-agent:bootstrap')
}
/**
* Configure the standard jar task to assemble the agent JAR with classloader isolation.
*/
jar {
dependsOn configurations.bootstrap, configurations.bootstrapLibs, configurations.internal
archiveBaseName.set('braintrust-java-agent')
archiveClassifier.set('')
manifest {
attributes(
'Premain-Class': 'dev.braintrust.system.AgentBootstrap',
'Agent-Class': 'dev.braintrust.system.AgentBootstrap',
'Can-Redefine-Classes': 'true',
'Can-Retransform-Classes': 'true',
'Implementation-Title': 'Braintrust Java Agent',
'Implementation-Version': project.version,
'Implementation-Vendor': 'Braintrust',
)
}
// 1) Include bootstrap classes as normal .class files (our code + META-INF/services)
from(provider { configurations.bootstrap.collect { zipTree(it) } }) {
// Keep META-INF/services (needed for ServiceLoader) but exclude other META-INF
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/maven/**'
}
// 2) Include bootstrap libraries as normal .class files (OTel API + SDK + autoconfigure)
from(provider { configurations.bootstrapLibs.collect { zipTree(it) } }) {
exclude 'META-INF/**'
}
// 3) Include internal classes as .classdata files under internal/
from(provider { configurations.internal.collect { zipTree(it) } }) {
into 'internal'
rename '(.*)\\.class$', '$1.classdata'
// Keep META-INF/services (needed by ServiceLoader in BraintrustClassLoader)
// but exclude everything else in META-INF
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/maven/**'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
exclude 'META-INF/LICENSE*'
exclude 'META-INF/NOTICE*'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/proguard/**'
exclude 'META-INF/versions/**'
}
}
test {
useJUnitPlatform()
// Launch JUnit with the Braintrust Java Agent attached
jvmArgs "-javaagent:${jar.archiveFile.get().asFile.absolutePath}"
// TODO: add config to turn off exporter so this isn't necessary
environment 'BRAINTRUST_API_KEY', 'bogus'
testLogging {
events "passed", "skipped", "failed"
showStandardStreams = true
exceptionFormat "full"
}
}
/**
* Runs GlobalLoggerTest as a standalone main() with the agent attached.
*/
task testGlobalLogger(type: JavaExec) {
dependsOn jar, testClasses
mainClass = 'dev.braintrust.system.GlobalLoggerTest'
classpath = sourceSets.test.runtimeClasspath
// jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"
jvmArgs "-javaagent:${jar.archiveFile.get().asFile.absolutePath}"
// TODO: add config to turn off exporter so this isn't necessary
environment 'BRAINTRUST_API_KEY', 'bogus'
inputs.files(jar)
inputs.files(sourceSets.test.output)
def markerFile = layout.buildDirectory.file('test-results/global-logger-test.passed')
outputs.file(markerFile)
doLast {
markerFile.get().asFile.tap {
parentFile.mkdirs()
text = "passed at ${java.time.Instant.now()}"
}
}
}
test.dependsOn testGlobalLogger
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.JavaLibrary
import com.vanniktech.maven.publish.SonatypeHost
def signingKey = System.getenv("GPG_SIGNING_KEY")
def signingKeyId = System.getenv("GPG_SIGNING_KEY_ID")
def signingPassword = System.getenv("GPG_SIGNING_PASSWORD")
if (signingKey != null && signingKeyId != null && signingPassword != null) {
ext["signingInMemoryKey"] = signingKey
ext["signingInMemoryKeyId"] = signingKeyId
ext["signingInMemoryKeyPassword"] = signingPassword
}
mavenPublishing {
if (signingKey != null && signingKeyId != null && signingPassword != null) {
signAllPublications()
}
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
coordinates(group.toString(), 'braintrust-java-agent', version.toString())
configure(
new JavaLibrary(
new JavadocJar.Empty(),
false // no sources jar — this is a fat agent jar
)
)
pom {
name = 'Braintrust Java Agent'
description = 'Braintrust auto-instrumentation Java agent for OpenTelemetry-based tracing'
url = 'https://github.com/braintrustdata/braintrust-sdk-java'
licenses {
license {
name = 'MIT License'
url = 'https://opensource.org/licenses/MIT'
}
}
developers {
developer {
id = 'braintrust'
name = 'Braintrust Team'
email = 'sdk@braintrustdata.com'
}
}
scm {
connection = 'scm:git:git://github.com/braintrustdata/braintrust-sdk-java.git'
developerConnection = 'scm:git:git://github.com/braintrustdata/braintrust-sdk-java.git'
url = 'https://github.com/braintrustdata/braintrust-sdk-java'
}
}
}