Monocle helps developers and platform engineers building or managing GenAI apps monitor these in prod by making it easy to instrument their code to capture traces that are compliant with the open-source cloud-native observability ecosystem.
View on Github
Monocle allows you to easily instrument your GenAI applications to capture telemetry for both custom code and third-party libraries. This guide explains how to instrument your code, create output processors, and analyze the resulting telemetry.
Monocle allows you to instrument your own custom wrappers around GenAI services. The setupMonocle
function is used to configure instrumentation for your application.
const { setupMonocle } = require('monocle2ai');
setupMonocle(
"myapp.name", // Service name
[], // Custom hooks array (empty here)
[ // Instrumentation configurations array
{
"package": require.resolve('./path/to/your/module'),
"object": "YourClass",
"method": "yourMethod",
"spanName": "customSpanName",
"output_processor": [
YOUR_OUTPUT_PROCESSOR
]
}
]
);
Output processors define how to extract and format telemetry data from method calls. They have access to:
const EXAMPLE_OUTPUT_PROCESSOR = {
type: "inference", // Type of span (inference, retrieval, etc.)
attributes: [ // Arrays of attribute definitions
[
{
attribute: "name",
accessor: arguments => arguments.instance.someProperty
},
// More attributes...
]
],
events: [ // Events to capture
{
name: "data.input",
attributes: [
{
attribute: "input",
accessor: arguments => arguments.args[0] || null
}
]
},
// More events...
]
};
Here’s how we instrument a custom OpenAI client:
setupMonocle(
"openai.app",
[],
[
{
"package": require.resolve('./custom_ai_code/openaiClient'),
"object": "OpenAIClient",
"method": "chat",
"spanName": "openaiClient.chat",
"output_processor": [
INFERENCE_OUTPUT_PROCESSOR
]
}
]
);
The INFERENCE_OUTPUT_PROCESSOR
extracts information like:
{
"package": require.resolve('./custom_ai_code/vectorDb'),
"object": "InMemoryVectorDB",
"method": "searchByText",
"spanName": "vectorDb.searchByText",
"output_processor": [
VECTOR_OUTPUT_PROCESSOR
]
}
The VECTOR_OUTPUT_PROCESSOR
captures:
You can also instrument third-party NPM modules like Google’s Generative AI SDK:
{
"package": "@google/generative-ai",
"object": "GenerativeModel",
"method": "generateContent",
"spanName": "gemini.generateContent",
"output_processor": [
GEMINI_OUTPUT_PROCESSOR
]
}
For NPM modules, specify the package name directly instead of using require.resolve()
.
Let’s see how output processors translate to actual traces:
The Vector DB processor extracts:
accessor: arguments => arguments.instance.constructor.name
accessor: arguments => arguments.args[0] || null
accessor: arguments => arguments.response.map(...).join(", ")
This produces the following trace data:
{
"name": "vectorDb.searchByText",
"attributes": {
"span.type": "retrieval",
"entity.2.name": "InMemoryVectorDB",
"entity.2.type": "vectorstore.InMemoryVectorDB",
"entity.3.name": "text-embedding-ada-002",
"entity.3.type": "model.embedding.text-embedding-ada-002"
},
"events": [
{
"name": "data.input",
"attributes": { "input": "programming languages" }
},
{
"name": "data.output",
"attributes": {
"response": "JavaScript is a high-level programming language, Machine learning is a subset of artificial intelligence"
}
}
]
}
The Gemini output processor extracts:
accessor: arguments => arguments.instance.model
accessor: arguments => ...input text extraction logic...
accessor: arguments => arguments.response.response.text()
This produces the following trace data:
{
"name": "gemini.generateContent",
"attributes": {
"span.type": "inference",
"entity.2.type": "gemini",
"entity.2.provider_name": "Google",
"entity.2.deployment": "models/gemini-1.5-flash",
"entity.3.name": "models/gemini-1.5-flash",
"entity.3.type": "model.llm.models/gemini-1.5-flash"
},
"events": [
{
"name": "data.input",
"attributes": { "input": ["Tell me a short joke about programming."] }
},
{
"name": "data.output",
"attributes": { "response": "Why do programmers prefer dark mode? Because light attracts bugs!\n" }
},
{
"name": "metadata",
"attributes": {
"prompt_tokens": 8,
"completion_tokens": 14,
"total_tokens": 22
}
}
]
}
attributes
sectiondata.input
, data.output
, and metadata
Monocle’s custom instrumentation provides a flexible way to track your GenAI application’s behavior. By defining output processors, you can extract meaningful telemetry data from any GenAI component, whether it’s your custom code or a third-party library.