टेलीमेट्री

ADK-Rust, adk-telemetry crate के माध्यम से उत्पादन-ग्रेड अवलोकन क्षमता प्रदान करता है, जो tracing इकोसिस्टम और OpenTelemetry का उपयोग करके संरचित लॉगिंग और डिस्ट्रीब्यूटेड ट्रेसिंग को एकीकृत करता है।

अवलोकन

टेलीमेट्री सिस्टम सक्षम बनाता है:

  • Structured Logging: समृद्ध, प्रासंगिक जानकारी के साथ क्वेरी योग्य लॉग
  • Distributed Tracing: agent पदानुक्रम और सेवा सीमाओं में अनुरोधों को ट्रैक करें
  • OpenTelemetry Integration: ट्रेस को अवलोकन बैकएंड (जैसे Jaeger, Datadog, Honeycomb) में निर्यात करें
  • Automatic Context Propagation: सभी ऑपरेशनों में Session, user और invocation IDs का स्वचालित संदर्भ प्रसार
  • Pre-configured Spans: सामान्य ADK ऑपरेशनों के लिए पूर्व-कॉन्फ़िगर किए गए स्पैन के हेल्पर फ़ंक्शन

त्वरित शुरुआत

बेसिक कंसोल लॉगिंग

डेवलपमेंट और साधारण डिप्लॉयमेंट के लिए, कंसोल लॉगिंग इनिशियलाइज़ करें:

use adk_telemetry::init_telemetry;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize telemetry with your service name
    init_telemetry("my-agent-service")?;
    
    // Your agent code here
    
    Ok(())
}

यह समझदार डिफॉल्ट्स के साथ संरचित लॉगिंग को stdout पर कॉन्फ़िगर करता है।

OpenTelemetry निर्यात

डिस्ट्रीब्यूटेड ट्रेसिंग के साथ प्रोडक्शन डिप्लॉयमेंट के लिए:

use adk_telemetry::init_with_otlp;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize with OTLP exporter
    init_with_otlp("my-agent-service", "http://localhost:4317")?;
    
    // Your agent code here
    
    // Flush traces before exit
    adk_telemetry::shutdown_telemetry();
    Ok(())
}

यह ट्रेस और मेट्रिक्स को एक OpenTelemetry कलेक्टर एंडपॉइंट पर निर्यात करता है।

लॉग स्तर

RUST_LOG एनवायरनमेंट वेरिएबल का उपयोग करके लॉगिंग की वर्बोसिटी को नियंत्रित करें:

स्तरविवरणउपयोग का मामला
errorकेवल त्रुटियाँप्रोडक्शन (न्यूनतम)
warnचेतावनियाँ और त्रुटियाँप्रोडक्शन (डिफ़ॉल्ट)
infoसूचनात्मक संदेशडेवलपमेंट, स्टेजिंग
debugविस्तृत डीबगिंग जानकारीलोकल डेवलपमेंट
traceबहुत वर्बोस ट्रेसिंगडीप डीबगिंग

लॉग स्तर सेट करना

# Set global log level
export RUST_LOG=info

# Set per-module log levels
export RUST_LOG=adk_agent=debug,adk_model=info

# Combine global and module-specific levels
export RUST_LOG=warn,adk_agent=debug

यदि RUST_LOG सेट नहीं है, तो टेलीमेट्री सिस्टम डिफ़ॉल्ट रूप से info स्तर पर होता है।

लॉगिंग मैक्रो

लॉगिंग के लिए मानक tracing मैक्रो का उपयोग करें:

use adk_telemetry::{trace, debug, info, warn, error};

// सूचनात्मक लॉगिंग
info!("Agent started successfully");

// फ़ील्ड के साथ संरचित लॉगिंग
info!(
    agent.name = "my_agent",
    session.id = "sess-123",
    "Processing user request"
);

// डीबग लॉगिंग
debug!(user_input = ?input, "Received input");

// चेतावनी और त्रुटि लॉगिंग
warn!("Rate limit approaching");
error!(error = ?err, "Failed to call model");

संरचित फ़ील्ड

बेहतर फ़िल्टरिंग और विश्लेषण के लिए लॉग संदेशों में प्रासंगिक फ़ील्ड जोड़ें:

use adk_telemetry::info;

info!(
    agent.name = "customer_support",
    user.id = "user-456",
    session.id = "sess-789",
    invocation.id = "inv-abc",
    "Agent execution started"
);

ये फ़ील्ड आपके अवलोकन बैकएंड में क्वेरी योग्य हो जाते हैं।

इंस्ट्रूमेंटेशन

स्वचालित इंस्ट्रूमेंटेशन

फ़ंक्शन के लिए स्वचालित रूप से स्पैन बनाने के लिए #[instrument] विशेषता का उपयोग करें:

use adk_telemetry::{instrument, info};

#[instrument]
async fn process_request(user_id: &str, message: &str) {
    info!("Processing request");
    // Function logic here
}

// "user_id" और "message" फ़ील्ड के साथ "process_request" नामक एक स्पैन बनाता है।

संवेदनशील पैरामीटर छोड़ें

ट्रेस से संवेदनशील डेटा को बाहर रखें:

use adk_telemetry::instrument;

#[instrument(skip(api_key))]
async fn call_external_api(api_key: &str, query: &str) {
    // api_key ट्रेस में दिखाई नहीं देगा
}

कस्टम स्पैन नाम

use adk_telemetry::instrument;

#[instrument(name = "external_api_call")]
async fn fetch_data(url: &str) {
    // स्पैन का नाम "fetch_data" के बजाय "external_api_call" होगा
}

पूर्व-कॉन्फ़िगर किए गए स्पैन

ADK-Telemetry सामान्य ऑपरेशनों के लिए सहायक फ़ंक्शन प्रदान करता है:

एजेंट निष्पादन स्पैन

use adk_telemetry::agent_run_span;

let span = agent_run_span("my_agent", "inv-123");
let _enter = span.enter();

// एजेंट निष्पादन कोड यहाँ
// इस स्कोप के भीतर के सभी लॉग स्पैन संदर्भ को इनहेरिट करते हैं

मॉडल कॉल स्पैन

use adk_telemetry::model_call_span;

let span = model_call_span("gemini-2.0-flash");
let _enter = span.enter();

// मॉडल API कॉल यहाँ

टूल निष्पादन स्पैन

use adk_telemetry::tool_execute_span;

let span = tool_execute_span("weather_tool");
let _enter = span.enter();

// टूल निष्पादन कोड यहाँ

कॉलबैक स्पैन

use adk_telemetry::callback_span;

let span = callback_span("before_model");
let _enter = span.enter();

// कॉलबैक लॉजिक यहाँ

संदर्भ विशेषताएँ जोड़ना

वर्तमान स्पैन में उपयोगकर्ता और सत्र संदर्भ जोड़ें:

use adk_telemetry::add_context_attributes;

add_context_attributes("user-456", "sess-789");

मैनुअल स्पैन निर्माण

कस्टम इंस्ट्रूमेंटेशन के लिए, स्पैन मैन्युअल रूप से बनाएँ:

use adk_telemetry::{info, Span};

let span = tracing::info_span!(
    "custom_operation",
    operation.type = "data_processing",
    operation.id = "op-123"
);

let _enter = span.enter();
info!("Performing custom operation");
// ऑपरेशन कोड यहाँ

स्पैन विशेषताएँ

गतिशील रूप से विशेषताएँ जोड़ें:

use adk_telemetry::Span;

let span = Span::current();
span.record("result.count", 42);
span.record("result.status", "success");

OpenTelemetry कॉन्फ़िगरेशन

OTLP एंडपॉइंट

OTLP एक्सपोर्टर ट्रेस को एक कलेक्टर एंडपॉइंट पर भेजता है:

use adk_telemetry::init_with_otlp;

// लोकल जेगर (डिफ़ॉल्ट OTLP पोर्ट)
init_with_otlp("my-service", "http://localhost:4317")?;

// क्लाउड प्रदाता एंडपॉइंट
init_with_otlp("my-service", "https://otlp.example.com:4317")?;

एक लोकल कलेक्टर चलाना

डेवलपमेंट के लिए, OTLP सपोर्ट के साथ जेगर चलाएँ:

docker run -d --name jaeger \
  -p 4317:4317 \
  -p 16686:16686 \
  jaegertracing/all-in-one:latest

# ट्रेस http://localhost:16686 पर देखें

ट्रेस विज़ुअलाइज़ेशन

एक बार कॉन्फ़िगर हो जाने पर, ट्रेस आपके ऑब्जर्वेबिलिटी बैकएंड में दिखाई देते हैं, जिसमें निम्न शामिल हैं:

  • एजेंट निष्पादन पदानुक्रम
  • मॉडल कॉल विलंबताएँ
  • टूल निष्पादन का समय
  • त्रुटि प्रसार
  • संदर्भ प्रवाह (उपयोगकर्ता ID, सत्र ID, आदि)

ADK के साथ एकीकरण

जब टेलीमेट्री सिस्टम इनिशियलाइज़ किया जाता है, तो ADK-Rust कंपोनेंट स्वचालित रूप से टेलीमेट्री उत्सर्जित करते हैं:

use adk_rust::prelude::*;
use adk_telemetry::init_telemetry;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    // Initialize telemetry first
    init_telemetry("my-agent-app")?;
    
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.5-flash")?);
    
    let agent = LlmAgentBuilder::new("support_agent")
        .model(model)
        .instruction("You are a helpful support agent.")
        .build()?;
    
    // Use Launcher for simple execution
    Launcher::new(Arc::new(agent)).run().await?;
    
    Ok(())
}

Agent, model और Tool के ऑपरेशंस स्वचालित रूप से संरचित लॉग और ट्रेस उत्सर्जित करेंगे।

टूल्स में कस्टम टेलीमेट्री

कस्टम टूल्स में टेलीमेट्री जोड़ें:

use adk_rust::prelude::*;
use adk_telemetry::{info, instrument, tool_execute_span};
use serde_json::{json, Value};

#[instrument(skip(ctx))]
async fn weather_tool_impl(
    ctx: Arc<dyn ToolContext>,
    args: Value,
) -> Result<Value> {
    let span = tool_execute_span("weather_tool");
    let _enter = span.enter();
    
    let location = args["location"].as_str().unwrap_or("unknown");
    info!(location = location, "Fetching weather data");
    
    // Tool logic here
    let result = json!({
        "temperature": 72,
        "condition": "sunny"
    });
    
    info!(location = location, "Weather data retrieved");
    Ok(result)
}

let weather_tool = FunctionTool::new(
    "get_weather",
    "Get current weather for a location",
    json!({
        "type": "object",
        "properties": {
            "location": {"type": "string"}
        },
        "required": ["location"]
    }),
    weather_tool_impl,
);

कॉलबैक में कस्टम टेलीमेट्री

कॉलबैक में ऑब्जर्वेबिलिटी जोड़ें:

use adk_rust::prelude::*;
use adk_telemetry::{info, callback_span};
use std::sync::Arc;

let agent = LlmAgentBuilder::new("observed_agent")
    .model(model)
    .before_callback(Box::new(|ctx| {
        Box::pin(async move {
            let span = callback_span("before_agent");
            let _enter = span.enter();
            
            info!(
                agent.name = ctx.agent_name(),
                user.id = ctx.user_id(),
                session.id = ctx.session_id(),
                "Agent execution starting"
            );
            
            Ok(None)
        })
    }))
    .after_callback(Box::new(|ctx| {
        Box::pin(async move {
            let span = callback_span("after_agent");
            let _enter = span.enter();
            
            info!(
                agent.name = ctx.agent_name(),
                "Agent execution completed"
            );
            
            Ok(None)
        })
    }))
    .build()?;

प्रदर्शन संबंधी विचार

सैंपलिंग

उच्च-थ्रूपुट सिस्टम के लिए, ट्रेस सैंपलिंग पर विचार करें:

// Note: Sampling configuration depends on your OpenTelemetry setup
// Configure sampling in your OTLP collector or backend

एसिंक स्पैन

उचित स्पैन संदर्भ सुनिश्चित करने के लिए हमेशा एसिंक फ़ंक्शन पर #[instrument] का उपयोग करें:

use adk_telemetry::instrument;

// ✅ सही - await पॉइंट्स पर स्पैन संदर्भ संरक्षित रहता है
#[instrument]
async fn async_operation() {
    tokio::time::sleep(Duration::from_secs(1)).await;
}

// ❌ गलत - मैनुअल स्पैन संदर्भ खो सकता है
async fn manual_span_operation() {
    let span = tracing::info_span!("operation");
    let _enter = span.enter();
    tokio::time::sleep(Duration::from_secs(1)).await;
    // await के बाद संदर्भ खो सकता है
}

प्रोडक्शन में लॉग स्तर

ओवरहेड कम करने के लिए प्रोडक्शन में info या warn स्तर का उपयोग करें:

export RUST_LOG=warn,my_app=info

समस्या निवारण

कोई लॉग दिखाई नहीं दे रहा

  1. जाँचें कि RUST_LOG वातावरण चर सेट है
  2. सुनिश्चित करें कि किसी भी लॉगिंग से पहले init_telemetry() को कॉल किया गया है
  3. सत्यापित करें कि टेलीमेट्री केवल एक बार इनिशियलाइज़ की गई है (आंतरिक रूप से Once का उपयोग करता है)

ट्रेस एक्सपोर्ट नहीं किए गए

  1. सत्यापित करें कि OTLP एंडपॉइंट पहुंच योग्य है
  2. जाँचें कि कलेक्टर चल रहा है और कनेक्शन स्वीकार कर रहा है
  3. लंबित स्पैन को फ़्लश करने के लिए एप्लिकेशन से बाहर निकलने से पहले shutdown_telemetry() को कॉल करें
  4. नेटवर्क/फ़ायरवॉल समस्याओं की जाँच करें

स्पैन में संदर्भ गायब है

  1. async फ़ंक्शन पर #[instrument] का उपयोग करें
  2. सुनिश्चित करें कि स्पैन let _enter = span.enter() के साथ दर्ज किए गए हैं
  3. ऑपरेशन की अवधि के लिए _enter गार्ड को स्कोप में रखें

सर्वोत्तम अभ्यास

  1. जल्दी इनिशियलाइज़ करें: main() के शुरू में init_telemetry() को कॉल करें
  2. संरचित फ़ील्ड का उपयोग करें: स्ट्रिंग इंटरपोलेशन के बजाय कुंजी-मूल्य युग्मों के साथ संदर्भ जोड़ें
  3. Async फ़ंक्शन को इंस्ट्रूमेंट करें: async फ़ंक्शन पर हमेशा #[instrument] का उपयोग करें
  4. बाहर निकलने पर फ़्लश करें: एप्लिकेशन समाप्ति से पहले shutdown_telemetry() को कॉल करें
  5. उपयुक्त लॉग स्तर: महत्वपूर्ण घटनाओं के लिए info का उपयोग करें, विवरण के लिए debug का उपयोग करें
  6. संवेदनशील डेटा से बचें: #[instrument(skip(...))] के साथ संवेदनशील पैरामीटर छोड़ें
  7. सुसंगत नामकरण: सुसंगत फ़ील्ड नामों का उपयोग करें (जैसे, user.id, session.id)

संबंधित

  • Callbacks - कॉलबैक में टेलीमेट्री जोड़ें
  • Tools - कस्टम टूल को इंस्ट्रूमेंट करें
  • Deployment - प्रोडक्शन टेलीमेट्री सेटअप

पिछला: ← Events | अगला: Launcher →