tessl install tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core@1.5.0Quarkus LangChain4j Core provides runtime integration for LangChain4j with the Quarkus framework, enabling declarative AI service creation through CDI annotations.
Observability capabilities enable monitoring AI service interactions through CDI events, covering lifecycle events, tool executions, and guardrail validations.
CDI qualifier for selecting specific AI services when observing events.
// Package: io.quarkiverse.langchain4j.observability
/**
* CDI Qualifier for selecting specific AI service for event listening.
* Use to observe events from a particular AI service interface.
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AiServiceSelector {
/**
* The AI service interface class to select.
*/
Class<?> value();
}Enum defining all available AI service event types.
// Package: io.quarkiverse.langchain4j.observability
/**
* Enum of all AI service event types.
* Each enum value corresponds to a specific event class.
*/
public enum AiServiceEvents {
/**
* Fired when AI service method starts.
*/
STARTED(AiServiceStartedEvent.class),
/**
* Fired when response is received from model.
*/
RESPONSE_RECEIVED(AiServiceResponseReceivedEvent.class),
/**
* Fired when a tool is executed.
*/
TOOL_EXECUTED(ToolExecutedEvent.class),
/**
* Fired when input guardrail is executed.
*/
INPUT_GUARDRAIL_EXECUTED(InputGuardrailExecutedEvent.class),
/**
* Fired when output guardrail is executed.
*/
OUTPUT_GUARDRAIL_EXECUTED(OutputGuardrailExecutedEvent.class),
/**
* Fired when AI service method completes successfully.
*/
COMPLETED(AiServiceCompletedEvent.class),
/**
* Fired when AI service method errors.
*/
ERROR(AiServiceErrorEvent.class);
/**
* Create a listener adapter for this event type.
*
* @param aiServiceClass The AI service class to listen for
* @return Listener adapter
*/
public AiServiceListener<?> createListener(Class<?> aiServiceClass);
/**
* Get the event class for this event type.
*
* @return Event class
*/
public Class<?> getEventClass();
}import io.quarkiverse.langchain4j.observability.AiServiceSelector;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@ApplicationScoped
public class AssistantObserver {
// Observe started events
public void onStarted(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceStartedEvent event
) {
System.out.println("AI service started: " + event.methodName());
}
// Observe completed events
public void onCompleted(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceCompletedEvent event
) {
System.out.println("AI service completed: " + event.methodName());
}
// Observe error events
public void onError(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceErrorEvent event
) {
System.err.println("AI service error: " + event.error().getMessage());
}
// Observe tool executions
public void onToolExecuted(
@Observes @AiServiceSelector(MyAssistant.class) ToolExecutedEvent event
) {
System.out.println("Tool executed: " + event.toolName());
}
// Observe guardrail executions
public void onInputGuardrail(
@Observes @AiServiceSelector(MyAssistant.class) InputGuardrailExecutedEvent event
) {
System.out.println("Input guardrail: " + event.outcome());
}
public void onOutputGuardrail(
@Observes @AiServiceSelector(MyAssistant.class) OutputGuardrailExecutedEvent event
) {
System.out.println("Output guardrail: " + event.outcome());
}
}import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@ApplicationScoped
public class GlobalObserver {
// Observe all AI service completions regardless of service
public void onAnyCompletion(@Observes AiServiceCompletedEvent event) {
System.out.println("Any AI service completed");
}
// Observe all errors
public void onAnyError(@Observes AiServiceErrorEvent event) {
logError(event);
}
private void logError(AiServiceErrorEvent event) {
// Error logging logic
}
}import io.quarkiverse.langchain4j.observability.AiServiceSelector;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import java.util.concurrent.ConcurrentHashMap;
@ApplicationScoped
public class MetricsCollector {
@Inject
MeterRegistry registry;
private final ConcurrentHashMap<String, Long> startTimes = new ConcurrentHashMap<>();
public void onStarted(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceStartedEvent event
) {
String key = event.methodName() + "-" + System.identityHashCode(event);
startTimes.put(key, System.nanoTime());
}
public void onCompleted(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceCompletedEvent event
) {
String key = event.methodName() + "-" + System.identityHashCode(event);
Long startTime = startTimes.remove(key);
if (startTime != null) {
long duration = System.nanoTime() - startTime;
Timer.builder("ai.service.duration")
.tag("method", event.methodName())
.tag("service", "MyAssistant")
.register(registry)
.record(duration, java.util.concurrent.TimeUnit.NANOSECONDS);
}
}
public void onError(
@Observes @AiServiceSelector(MyAssistant.class) AiServiceErrorEvent event
) {
registry.counter("ai.service.errors",
"method", event.methodName(),
"service", "MyAssistant"
).increment();
}
}Event fired when tool input guardrail executes.
// Package: io.quarkiverse.langchain4j.runtime.observability
/**
* Event fired when tool input guardrail is executed.
* Package: io.quarkiverse.langchain4j.runtime.observability
*/
public record ToolInputGuardrailExecutedEvent(
ToolInvocationContext toolInvocationContext,
Class<?> toolClass,
String toolName,
ToolGuardrailOutcome outcome,
long duration
) {}Event fired when tool output guardrail executes.
// Package: io.quarkiverse.langchain4j.runtime.observability
/**
* Event fired when tool output guardrail is executed.
* Package: io.quarkiverse.langchain4j.runtime.observability
*/
public record ToolOutputGuardrailExecutedEvent(
ToolInvocationContext toolInvocationContext,
Class<?> toolClass,
String toolName,
ToolGuardrailOutcome outcome,
long duration
) {}Adapter for creating AI service listeners.
// Package: io.quarkiverse.langchain4j.observability
/**
* Adapter for creating AI service event listeners.
* Implements LangChain4j AiServiceListener and fires CDI events.
*
* @param <T> Event type
*/
public record AiServiceListenerAdapter<T extends AiServiceEvent>(
Class<T> eventClass,
Class<?> aiServiceClass
) implements AiServiceListener<T> {
/**
* Handle AI service event by firing CDI event.
*
* @param event The AI service event
*/
@Override
public void onEvent(T event);
}Literal for programmatic @AiServiceSelector creation.
// Package: io.quarkiverse.langchain4j.observability
/**
* AnnotationLiteral for programmatic @AiServiceSelector creation.
*/
public class AiServiceSelectorLiteral
extends AnnotationLiteral<AiServiceSelector>
implements AiServiceSelector {
/**
* Create literal for AI service class.
*
* @param aiServiceClass The AI service class
* @return AiServiceSelector literal
*/
public static AiServiceSelectorLiteral of(Class<?> aiServiceClass);
@Override
public Class<?> value();
}// Package: io.quarkiverse.langchain4j.runtime.observability
/**
* Enum representing guardrail validation outcomes.
*/
public enum GuardrailOutcome {
SUCCESS,
FAILURE,
FATAL
}// Package: io.quarkiverse.langchain4j.runtime.observability
/**
* Enum representing tool-specific guardrail outcomes.
*/
public enum ToolGuardrailOutcome {
SUCCESS,
FAILURE,
FATAL
}Quarkus LangChain4j Core provides built-in observability features:
Automatic metrics when quarkus-micrometer is present:
# Enable metrics
quarkus.langchain4j.metrics.enabled=trueMetrics collected:
langchain4j.aiservice.duration - AI service method durationlangchain4j.aiservice.requests - Number of requestslangchain4j.aiservice.errors - Number of errorslangchain4j.tool.executions - Tool execution countlangchain4j.guardrail.executions - Guardrail execution countAutomatic tracing when quarkus-opentelemetry is present:
# Configure tracing
quarkus.langchain4j.tracing.include-prompt=true
quarkus.langchain4j.tracing.include-completion=true
quarkus.langchain4j.tracing.include-tool-arguments=true
quarkus.langchain4j.tracing.include-tool-result=trueSpans created:
Observability is useful for: