Skip to content
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
28 changes: 9 additions & 19 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,47 +21,37 @@ repositories {
}

ext {
otelVersion = '1.36.0'
otelVersion = '1.54.1'
jacksonVersion = '2.16.1'
junitVersion = '5.10.1'
assertjVersion = '3.25.1'
mockitoVersion = '5.8.0'
slf4jVersion = '2.0.9'
junitVersion = '5.11.4'
slf4jVersion = '2.0.17'
}

dependencies {
// OpenTelemetry
api "io.opentelemetry:opentelemetry-api:${otelVersion}"
api "io.opentelemetry:opentelemetry-sdk:${otelVersion}"
api "io.opentelemetry:opentelemetry-sdk-trace:${otelVersion}"
api "io.opentelemetry:opentelemetry-sdk-logs:${otelVersion}"
implementation "io.opentelemetry:opentelemetry-exporter-otlp:${otelVersion}"
implementation "io.opentelemetry:opentelemetry-exporter-logging:${otelVersion}"
implementation "io.opentelemetry:opentelemetry-sdk-testing:${otelVersion}"
implementation "io.opentelemetry:opentelemetry-semconv:1.25.0-alpha"
implementation "io.opentelemetry:opentelemetry-semconv:1.30.1-alpha"

// HTTP Client (Java 11+)
implementation 'com.fasterxml.jackson.core:jackson-databind:' + jacksonVersion
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:' + jacksonVersion
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:' + jacksonVersion
implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}"

// Logging
implementation "org.slf4j:slf4j-api:${slf4jVersion}"
runtimeOnly "org.slf4j:slf4j-simple:${slf4jVersion}"

// Utilities
implementation 'com.google.code.findbugs:jsr305:3.0.2' // @Nullable annotations
implementation 'org.apache.commons:commons-lang3:3.14.0'
implementation 'com.google.code.findbugs:jsr305:3.0.2' // for @Nullable annotations

// AI SDKs (optional dependencies)
compileOnly 'com.openai:openai-java:2.8.1' // Official OpenAI SDK
compileOnly 'com.openai:openai-java:2.8.1'
implementation "io.opentelemetry.instrumentation:opentelemetry-openai-java-1.1:2.19.0-alpha"
// compileOnly 'com.anthropic:anthropic-java:0.1.0' // Not yet available

// Testing
testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}"
testImplementation "org.assertj:assertj-core:${assertjVersion}"
}

test {
Expand Down
6 changes: 6 additions & 0 deletions examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ repositories {
mavenCentral()
}

def braintrustLogLevel = System.getenv('BRAINTRUST_LOG_LEVEL') ?: 'info'

dependencies {
implementation project(':')
// TODO: not sure why I have to do this. I would have expected this to come over in the project root transitive deps
Expand All @@ -33,20 +35,23 @@ task runSimpleOpenTelemetry(type: JavaExec) {
description = 'Run the simple OpenTelemetry example'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'dev.braintrust.examples.SimpleOpenTelemetryExample'
systemProperty 'org.slf4j.simpleLogger.log.dev.braintrust', braintrustLogLevel
}

task runCustomOpenTelemetry(type: JavaExec) {
group = 'Braintrust SDK Examples'
description = 'Run the custom OpenTelemetry example'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'dev.braintrust.examples.CustomOpenTelemetryExample'
systemProperty 'org.slf4j.simpleLogger.log.dev.braintrust', braintrustLogLevel
}

task runOpenAIInstrumentation(type: JavaExec) {
group = 'Braintrust SDK Examples'
description = 'Run the OpenAI instrumentation example. NOTE: this requires OPENAI_API_KEY to be exported and will make a small call to openai, using your tokens'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'dev.braintrust.examples.OpenAIInstrumentationExample'
systemProperty 'org.slf4j.simpleLogger.log.dev.braintrust', braintrustLogLevel
debugOptions {
enabled = true
port = 5566
Expand All @@ -60,6 +65,7 @@ task runExperiment(type: JavaExec) {
description = 'Run the experiment example'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'dev.braintrust.examples.ExperimentExample'
systemProperty 'org.slf4j.simpleLogger.log.dev.braintrust', braintrustLogLevel
debugOptions {
enabled = true
port = 5566
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.braintrust.examples;

import dev.braintrust.config.BraintrustConfig;
import dev.braintrust.log.BraintrustLogger;
import dev.braintrust.trace.BraintrustTracing;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
Expand Down Expand Up @@ -88,7 +87,7 @@ private static void registerShutdownHook(OpenTelemetrySdk otel) {
.addShutdownHook(
new Thread(
() -> {
BraintrustLogger.debug(
System.out.println(
"Shutting down. Force-Flushing all otel data.");
var result =
CompletableResultCode.ofAll(
Expand All @@ -108,7 +107,7 @@ private static void registerShutdownHook(OpenTelemetrySdk otel) {
TimeUnit
.SECONDS))
.toList());
BraintrustLogger.debug(
System.out.println(
"otel shutdown complete. Flush done: %s, Flush successful: %s"
.formatted(
result.isDone(), result.isSuccess()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ public static void main(String[] args) throws Exception {
result -> "vegetable".equals(result) ? 1.0 : 0.0))
.build();
var result = eval.run();
System.out.println(
"\n\n Example complete! View your data in Braintrust: "
+ result.createReportString());
System.out.println("\n\n" + result.createReportString());
}
}
12 changes: 7 additions & 5 deletions src/main/java/dev/braintrust/api/BraintrustApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import dev.braintrust.config.BraintrustConfig;
import dev.braintrust.log.BraintrustLogger;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
Expand All @@ -18,6 +17,7 @@
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import lombok.extern.slf4j.Slf4j;

public interface BraintrustApiClient {
/** Creates or gets a project by name. */
Expand All @@ -39,6 +39,7 @@ static BraintrustApiClient of(BraintrustConfig config) {
return new HttpImpl(config);
}

@Slf4j
class HttpImpl implements BraintrustApiClient {
private final BraintrustConfig config;
private final HttpClient httpClient;
Expand Down Expand Up @@ -170,25 +171,25 @@ private <T> CompletableFuture<T> postAsync(
}

private <T> CompletableFuture<T> sendAsync(HttpRequest request, Class<T> responseType) {
BraintrustLogger.debug("API Request: {} {}", request.method(), request.uri());
log.debug("API Request: {} {}", request.method(), request.uri());

return httpClient
.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(response -> handleResponse(response, responseType));
}

private <T> T handleResponse(HttpResponse<String> response, Class<T> responseType) {
BraintrustLogger.debug("API Response: {} - {}", response.statusCode(), response.body());
log.debug("API Response: {} - {}", response.statusCode(), response.body());

if (response.statusCode() >= 200 && response.statusCode() < 300) {
try {
return objectMapper.readValue(response.body(), responseType);
} catch (IOException e) {
BraintrustLogger.warn("Failed to parse response body", e);
log.warn("Failed to parse response body", e);
throw new ApiException("Failed to parse response body", e);
}
} else {
BraintrustLogger.warn(
log.warn(
"API request failed with status {}: {}",
response.statusCode(),
response.body());
Expand Down Expand Up @@ -225,6 +226,7 @@ private static ObjectMapper createObjectMapper() {
}

/** Implementation for test doubling */
@Slf4j
class InMemoryImpl implements BraintrustApiClient {
private final List<OrganizationAndProjectInfo> organizationAndProjectInfos;
private final Set<Experiment> experiments =
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/dev/braintrust/config/BraintrustConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public final class BraintrustConfig extends BaseConfig {
Duration.ofSeconds(getConfig("BRAINTRUST_REQUEST_TIMEOUT", 30));

/** Setting for unit testing. Do not use in production. */
private final boolean unitTetJavaExportSpansInMemory =
getConfig("BRAINTRUST_TEST_JAVA_EXPORT_SPANS_IN_MEMORY", false);
private final boolean exportSpansInMemoryForUnitTest =
getConfig("BRAINTRUST_JAVA_EXPORT_SPANS_IN_MEMORY_FOR_UNIT_TEST", false);

public static BraintrustConfig fromEnvironment() {
return of();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.openai.models.chat.completions.ChatCompletionSystemMessageParam;
import com.openai.models.chat.completions.ChatCompletionToolMessageParam;
import com.openai.models.chat.completions.ChatCompletionUserMessageParam;
import dev.braintrust.log.BraintrustLogger;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.logs.LogRecordBuilder;
Expand All @@ -37,7 +36,9 @@
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;

@Slf4j
final class ChatCompletionEventsHelper {

private static final AttributeKey<String> EVENT_NAME = stringKey("event.name");
Expand Down Expand Up @@ -76,7 +77,7 @@ public static void emitPromptLogEvents(
"braintrust.input_json",
JSON_MAPPER.writeValueAsString(content));
} catch (JsonProcessingException e) {
BraintrustLogger.error("Error mapping json", e);
log.error("Error mapping json", e);
}
body.put("content", Value.of(content));
}
Expand Down Expand Up @@ -200,7 +201,7 @@ public static void emitCompletionLogEvents(
var completionJson = JSON_MAPPER.writeValueAsString(completion);
Span.current().setAttribute("braintrust.output_json", completionJson);
} catch (JsonProcessingException e) {
BraintrustLogger.error("Error mapping completion json", e);
log.error("Error mapping completion json", e);
}
for (ChatCompletion.Choice choice : completion.choices()) {
ChatCompletionMessage choiceMsg = choice.message();
Expand Down
Loading