Loading...
Loading...
Analyzes observability signals from customer GenAI applications with DQL. Reads OpenTelemetry GenAI spans and LLM evaluation bizevents. Use for: golden signals (traffic, errors, latency, saturation); LLM signals (model, provider, tokens); cost/token analytics, usage attribution, and prompt caching; agent signals (tool calls, steps, failures, loop detection, Smartscape topology); conversation/session analytics; guardrails (blocked/truncated responses); and evaluation signals (quality, pass/fail). Trigger: "LLM latency", "token usage by model", "cost by model and provider", "cost per conversation", "who is driving token spend", "do I have prompt caching", "failing agent tool calls", "find runaway agents", "responses truncated or blocked", "failed evaluations", "am I hitting rate limits", "token throughput / TPM", "provider throttling or 429s". Do NOT use for: Davis CoPilot/MCP telemetry (dt-platform), generic service metrics (dt-obs-services), logs (dt-obs-logs), or non-GenAI tracing (dt-obs-tracing).
npx skill4agent add dynatrace/dynatrace-for-ai dt-obs-genaispan.status_code == "error"duration1msduration / 1msfetch spans, from: now()-24h
| filter isNotNull(gen_ai.request.model)
| summarize total = count(), errors = countIf(span.status_code == "error"), by: {gen_ai.request.model}
| fieldsAdd error_rate_pct = if(total > 0, errors * 100.0 / total, else: 0.0)
| sort error_rate_pct descchatexecute_toolinvoke_agentcreate_agentfetch spans, from: now()-24h
| filter isNotNull(gen_ai.request.model)
| summarize p95_ms = percentile(duration, 95) / 1ms, requests = count(), by: {gen_ai.provider.name}
| sort p95_ms descgen_ai.usage.input_tokensgen_ai.usage.output_tokensfetch spans, from: now()-24h
| filter isNotNull(gen_ai.usage.input_tokens) or isNotNull(gen_ai.usage.output_tokens)
| summarize input_tokens = sum(gen_ai.usage.input_tokens), output_tokens = sum(gen_ai.usage.output_tokens), total_tokens = sum(gen_ai.usage.input_tokens) + sum(gen_ai.usage.output_tokens), by: {gen_ai.provider.name, gen_ai.request.model}
| sort total_tokens descexecute_toolinvoke_agentcreate_agentGENAI_AGENTGENAI_MODELGENAI_PROVIDERGENAI_SERVICEfetch spans, from: now()-24h
| filter isNotNull(gen_ai.agent.name)
| summarize total = count(), errors = countIf(span.status_code == "error"), by: {gen_ai.agent.name}
| fieldsAdd error_rate_pct = if(total > 0, errors * 100.0 / total, else: 0.0)
| sort errors descgen_ai.conversation.idfetch spans, from: now()-24h
| filter isNotNull(gen_ai.conversation.id)
| summarize turns = countDistinct(trace.id), total_tokens = sum(gen_ai.usage.input_tokens) + sum(gen_ai.usage.output_tokens), errors = countIf(span.status_code == "error"), by: {gen_ai.conversation.id}
| sort total_tokens descgen_ai.response.finish_reasonscontent_filterlengthprompt-injectionpii-leakagetoxicitybiasfetch spans, from: now()-24h
| filter isNotNull(gen_ai.response.finish_reasons)
| fieldsAdd finish_reason = gen_ai.response.finish_reasons
| expand finish_reason
| summarize calls = count(), by: {finish_reason, gen_ai.request.model}
| sort calls descevent.type == "gen_ai.evaluation.result"trace.idfetch bizevents, from: now()-24h
| filter event.type == "gen_ai.evaluation.result"
| filter gen_ai.evaluation.score.label == "fail"
| fields timestamp, gen_ai.evaluation.name, gen_ai.evaluation.score.value, gen_ai.evaluation.explanation, gen_ai.evaluation.input.question, gen_ai.evaluation.input.answer
| sort timestamp descfetch spans, from: now()-24h
| summarize
has_genai = countIf(isNotNull(gen_ai.request.model)),
has_tokens = countIf(isNotNull(gen_ai.usage.input_tokens) or isNotNull(gen_ai.usage.output_tokens)),
has_agents = countIf(isNotNull(gen_ai.agent.name)),
has_tools = countIf(gen_ai.operation.name == "execute_tool"),
has_conversation = countIf(isNotNull(gen_ai.conversation.id)),
has_finish_reason = countIf(isNotNull(gen_ai.response.finish_reasons)),
has_cached_tokens = countIf(isNotNull(gen_ai.usage.cache_read.input_tokens) or isNotNull(gen_ai.usage.cache_creation.input_tokens)),
total = count()
fetch bizevents, from: now()-24h
| filter event.type == "gen_ai.evaluation.result"
| summarize evals = count()has_genaihas_genaihas_tokenshas_agentshas_toolshas_conversationhas_finish_reasonhas_cached_tokensevalshas_conversation == 0has_cached_tokens == 0| Parameter | Default | Rationale |
|---|---|---|
| Timeframe | Last 24 h ( | Covers a full operational day without being too narrow |
| Model scope | All models (no model filter) | Shows the full picture; user can narrow after seeing results |
| Provider scope | All providers | Same rationale as model scope |
| Token threshold | None | Show all — let the data reveal the outliers |
has_genaiask-dynatrace-docs| User Request / Prompt Starter | Capability | Reference File |
|---|---|---|
| "Understand AI Observability signals" | All signal categories overview | This SKILL.md |
| "Analyze LLM latency and errors", "LLM errors", "error rate by model" | Golden Signals | golden-signals.md |
| "Which models are slowest right now?", "compare latency across providers" | LLM Signals | llm-signals.md |
| "Show token usage by model", "token usage spikes" | Cost and Tokens | cost-and-tokens.md |
| "Break down cost by model and provider", "which prompts are most expensive?" | Cost and Tokens | cost-and-tokens.md |
| "Trace a failing agent run", "show failed tool calls" | Agent Signals | agent-signals.md |
| "Break down agent steps by latency" | Agent Signals | agent-signals.md |
| "Map agent topology", "which models does this agent use?", "list GenAI agents/models/providers" | Agent Signals (Smartscape) | agent-signals.md |
| "Is an agent stuck in a loop?", "find runaway agents", "what caused the token spike?" | Agent Signals (loops) | agent-signals.md |
| "Cost per conversation", "most expensive sessions", "how deep do conversations run?" | Conversation Analytics | conversation-analytics.md |
| "Stitch together an agent trajectory", "filter by session id", "connect traces across a session" | Conversation Analytics | conversation-analytics.md |
| "How often are responses blocked/filtered?", "are responses being truncated?", "finish reasons" | Guardrails | guardrails.md |
| "Cost by application/user/tenant", "who is driving token spend?" | Cost and Tokens (attribution) | cost-and-tokens.md |
| "Do I have prompt caching?", "cache hit rate", "caching savings" | Cost and Tokens (caching) | cost-and-tokens.md |
| "Summarize evaluation quality scores", "show low-scoring responses", "show failed evaluations" | Evaluation Quality | evaluations.md |
| "What signals am I missing?", "why is there no data?" | Empty-State Check | This SKILL.md |
1. Run token usage by model and provider (cost-and-tokens.md → "Token usage by model and provider")
2. Identify the top model-provider combinations by total_tokens
3. For the top offenders, run token usage spikes to check for abnormal time windows
4. Use the cost-estimation template in "Most expensive prompts and models" to estimate USD spend — ask the user for per-model prices first (see "Exception — cost prices" under Agent Instructions)
5. Check for prompt-size outliers: high input_tokens / output_tokens ratio indicates large context windows
6. Attribute spend to a consumer (cost-and-tokens.md → "Usage attribution") and check whether prompt caching is enabled and effective (cost-and-tokens.md → "Prompt caching economics")1. Run token usage spikes (cost-and-tokens.md → "Token usage spikes") to find the abnormal time window
2. Within that window, run repeated-tool-calls and runaway-turn queries (agent-signals.md → "Agent loops and runaway detection")
3. For a flagged trace.id, open the trace to see what the agent looped on
4. If conversation ids are present, re-run the loop query grouped by gen_ai.conversation.id to catch cross-turn loops (conversation-analytics.md)1. Run failing agent activity query (agent-signals.md → "Failing agent activity")
2. Sort by errors desc to find the most error-prone agent
3. Take the trace.id from a failing span and open in Dynatrace distributed-tracing view
4. Check agent steps by latency (agent-signals.md) to see which operation type is slowest1. Run the guardrails presence check (guardrails.md) to confirm finish reasons are recorded
2. Run the finish-reason breakdown, then the blocked (content_filter) and truncated (length) queries
3. Correlate content-filter spikes with the prompt-injection evaluator and truncation with answer-completeness failures (evaluations.md)
4. For a specific block or failure, take the trace.id and pivot to the originating spans (evaluations.md → "Correlating evaluations to traces")1. Run evaluation quality scores (evaluations.md → "Evaluation quality scores") to rank evaluators by avg_score asc
2. Focus on the lowest-scoring evaluator
3. Run failed evaluations (evaluations.md → "Failed evaluations") to surface the exact Q&A pairs and LLM judge explanations
4. Use the "Fail rate by evaluator" query to see how many responses fail each evaluator and the share of total evaluations
5. To root-cause a specific failure, take its trace.id and pivot to the originating spans (evaluations.md → "Correlating evaluations to traces")gen_ai.conversation.id