<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[LLM Observability - Elastic Observability Labs]]></title>
    <description><![CDATA[Trusted security news & research from the team at Elastic.]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[LLM Observability - Elastic Observability Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltad972c1c27dbefc6/6a88d9782904ea5e8511d473/observability-labs-thumbnail.png</url>
      <link>https://www.elastic.co/observability-labs/blog/category/llm-observability</link>
    </image>
    <link>https://www.elastic.co/observability-labs/blog/category/llm-observability</link>
    <atom:link href="https://www.elastic.co/observability-labs/rss/category/llm-observability.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[en]]></language>
    <lastBuildDate>Sat, 12 Sep 2026 05:14:09 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Your AI agent needs an alibi: Observability and audit trails for Agent Builder in Elastic]]></title>
    <description><![CDATA[Elastic 9.5 traces every Agent Builder run as OpenTelemetry spans in your own cluster, so tool calls and token counts are queryable with ES|QL. One workflow step adds the approval record, in a data stream the pipeline cannot rewrite.]]></description>
    <content:encoded><![CDATA[<p>One question to an Elastic Agent Builder agent produced 24 spans, 10 model calls across two models, and roughly 160,000 input tokens. Elastic 9.5 records AI agent observability data without a collector or a scraper. Every run lands as OpenTelemetry traces in your own cluster, on by default, writing to <code>traces-agent_builder.otel-&lt;space-id&gt;</code> down to each ES|QL query the agent generated and each index it looked up.</p>
<p>Those traces show how the agent reached its recommendation and what it cost. They do not record who approved it. Below: how to read the traces, scope the three identities a run touches, and append the approval decision to a data stream the pipeline cannot rewrite.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8b462c91ad11f060/6a95560048c299343ec688fd/02-architecture.png" alt="Agent Builder investigates, a workflow gate takes the human approval, and each stage writes to a different Elasticsearch data stream" /></p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>Elastic Stack 9.5 or Serverless  </li>
<li>Privileges to manage Kibana advanced settings, needed to install the traces dashboard.</li>
</ul>
<h2 id="whereelasticobservabilityrecordseachpartofanaiagentaction">Where Elastic Observability records each part of an AI agent action</h2>
<p>Four questions come up in every review of an agentic operations pipeline, and each one is answered by a different record.</p>
<p>| Question | Where the answer lives | Who creates it |
| :---- | :---- | :---- |
| How did the agent reach its recommendation? | <code>traces-agent_builder.otel-*</code> spans | Agent Builder, automatically |
| Which tools did it call, and did they fail? | <code>execute_tool</code> spans in the same data stream | Agent Builder, automatically |
| Whose privileges did the run execute with? | Workflow execution record and Elasticsearch security audit logs | Kibana, partly |
| What did a human decide, and did the action run? | An index you write to yourself | You |</p>
<p>The first two are new in 9.5 and cost nothing but a toggle. The last one has no automatic source, so it is the one most pipelines are missing.</p>
<h2 id="thescenarioastalepricingcacheincheckout">The scenario: a stale pricing cache in checkout</h2>
<p>Three <code>checkout-service</code> workers serve production traffic. One of them, <code>checkout-worker-1</code>, was rolled to version <code>2026.07.26.1</code> and now returns HTTP 500 on every quote because its pricing cache stopped refreshing. The other two stay on <code>2026.07.25.3</code> and serve normally.</p>
<p>The <a href="https://www.elastic.co/observability-labs/blog/sre-control-plane-agent-builder-workflows">SRE control plane</a> pattern behind this setup connects telemetry, an Agent Builder agent that reasons over it, and Elastic Workflows that run known actions, with a <a href="https://www.elastic.co/observability-labs/blog/human-approval-sre-automation-elastic-workflows">human approval gate</a> before the first step that changes production.</p>
<p>Telemetry arrives through the documented OpenTelemetry path, so the agent reads standard OTel fields. Elasticsearch 9.5 exposes a native OTLP endpoint, which lets an OTel SDK write directly to the cluster with no collector in between:</p>
<pre><code>from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource

provider = LoggerProvider(
    resource=Resource.create({
        "service.name": "checkout-service",
        "deployment.environment": "production",
    })
)
provider.add_log_record_processor(
    BatchLogRecordProcessor(
        OTLPLogExporter(
            endpoint=f"{ES_URL}/_otlp/v1/logs",
            headers={"Authorization": f"ApiKey {API_KEY}"},
        )
    )
)
</code></pre>
<p>The endpoint speaks OTLP over protobuf and rejects <code>application/json</code> with HTTP 406, so send it through an SDK or collector rather than hand-built JSON. That writes 450 records to <code>logs-generic.otel-default</code>: 360 healthy events across the three workers and 90 <code>PricingCacheStaleError</code> events from the broken one. The agent is given none of that context and has to find it by querying.</p>
<h2 id="readingaiagentobservabilitytracesinelastic">Reading AI agent observability traces in Elastic</h2>
<p>Everything Agent Builder records about a run lives in two data streams, and all of it is queryable with ES|QL.</p>
<h3 id="howtoturnonaiagenttracingingenaisettings">How to turn on AI agent tracing in GenAI Settings</h3>
<p>Open <strong>Stack Management</strong>, then <strong>GenAI Settings</strong>, and find the <strong>Agent Builder Traces</strong> section. <strong>Collect conversation traces</strong> is on by default in 9.5.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt907aa26526dec518/6a9555e8893681fd923dd487/03-genai-settings.png" alt="Agent Builder Traces section in GenAI Settings with Collect conversa" /></p>
<p>Two details on that panel matter more than the toggle. Traces are written to <code>traces-agent_builder.otel-&lt;space-id&gt;</code>, one data stream per Kibana space, with a companion <code>logs-agent_builder.otel-&lt;space-id&gt;</code> for agent-side events. These are ordinary data streams on the standard OTel index templates, not hidden system indices, so Discover, Lens, and ES|QL query them directly.</p>
<p>The callout states the access model plainly: anyone who can read the index can read every trace in it. Trace access is not scoped per user, so restrict the index pattern through a role before granting access to a space with sensitive conversations.</p>
<h3 id="readingthellmtracewaterfallforoneagentrun">Reading the LLM trace waterfall for one agent run</h3>
<p>A single question through the <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/kibana-api">converse API</a> asks the built-in Elastic AI Agent to investigate <code>logs-generic.otel-default</code>, find which pod and version are returning HTTP 500, and propose one bounded action. It answers correctly, naming <code>checkout-worker-1</code> on <code>2026.07.26.1</code> with a 43% error rate against zero errors on the two workers still on <code>2026.07.25.3</code>.</p>
<p>Select the trace icon under any agent response to open the waterfall.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a0275868ed6d61a/6a95566e9b940a2b62cb3c62/04-trace-waterfall.png" alt="Trace waterfall for one agent run showing 24 spans across invoke_agent, chat, and execute_tool" /></p>
<p>One question through the converse API produced 24 spans over 43.7 seconds. The structure is an <code>invoke_agent</code> root, a <code>generate_title</code> side branch, then alternating <code>chat</code> and <code>execute_tool</code> spans as the agent queries, reads the result, and picks the next query.</p>
<p>Three span families carry everything you will aggregate on.</p>
<p>| Span name prefix | What it represents | Key attributes |
| :---- | :---- | :---- |
| <code>invoke_agent</code> | A conversation round (<code>CHAIN</code>) or an agent execution (<code>AGENT</code>) | <code>elastic.inference.span.kind</code>, <code>gen_ai.agent.id</code> |
| <code>chat</code> | One model call | <code>gen_ai.request.model</code>, <code>gen_ai.provider.name</code>, <code>gen_ai.usage.input_tokens</code>, <code>gen_ai.usage.output_tokens</code> |
| <code>execute_tool</code> | One tool invocation | <code>gen_ai.tool.name</code>, <code>gen_ai.tool.call.id</code>, <code>status.code</code> |</p>
<p>The token breakdown for that run:</p>
<p>| Model | Calls | Input tokens | Output tokens |
| :---- | ----: | ----: | ----: |
| <code>anthropic-claude-4.6-sonnet</code> | 5 | 113,315 | 2,039 |
| <code>anthropic-claude-4.5-haiku</code> | 5 | 47,211 | 651 |</p>
<p>Half the model calls went to the smaller model. That is <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/models">fast model routing</a>, which sends low-effort steps to a cheaper model, and the split is only visible in the trace.</p>
<p>The single agent investigation consumed roughly 160,000 input tokens in total. Each round replays the accumulated context, so cost scales with conversation length rather than with the length of the question.</p>
<h3 id="howdoyouqueryagenttoolcallswithesql">How do you query agent tool calls with ES|QL?</h3>
<p>Tool invocations are the part of agent behavior most worth watching, because that is where the agent touches your data. Every call is one <code>execute_tool</code> span, and the documented query aggregates them directly:</p>
<pre><code>FROM traces-agent_builder.otel-*
| WHERE span.name LIKE "execute_tool *"
| STATS calls = COUNT(*),
        errors = COUNT(*) WHERE status.code == "Error",
        avg_ms = ROUND(AVG(duration) / 1000000.0, 1)
  BY tool = attributes.gen_ai.tool.name
| SORT calls DESC
</code></pre>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3954942227269d2/6a955510d04dac38a16c9c15/05-tool-calls-esql.png" alt="ES|QL aggregation of execute_tool spans grouped by tool name" /></p>
<p>Across that run the agent leaned on <code>platform.core.execute_esql</code>, with <code>platform.core.generate_esql</code> and <code>load_skill</code> behind it at two calls each. <code>duration</code> is in nanoseconds on the root of the document, which is why the query divides by a million for milliseconds.</p>
<p>Check the companion logs data stream as well. During a different run in the same session, the agent tried to call a tool that was not in its available set, and the attempt was recorded as an exception event in <code>logs-agent_builder.otel-default</code>, correlated to the trace by <code>trace_id</code>:</p>
<pre><code>{
  "trace_id": "3f8b9722dbd371ac4b7ad75e4bed13b6",
  "event_name": "exception",
  "attributes": {
    "exception.type": "toolNotFoundError",
    "exception.message": "Tool \"platform.streams.query_documents\" called but was not available"
  }
}
</code></pre>
<p>A blocked tool attempt is audit-relevant, and it does not appear in the trace waterfall. Querying only the traces data stream will miss it.</p>
<p>For aggregate views there is a managed dashboard, installed per space from the same settings panel.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt84e139b24e474a43/6a9556211ade64a39142b72a/06-traces-dashboard.png" alt="Agent Builder traces overview dashboard showing token usage, conversation latency, and tool call frequency" /></p>
<p>Over a fifteen-minute window covering these runs, it reported 903,914 input tokens, 11,734 output tokens, and 44 LLM requests, with 35 tool spans at a 100% success rate and 0.42 seconds average duration. The dashboard is managed and read-only, so duplicate it to change a panel, and Elastic can still ship improvements to the original.</p>
<h3 id="whatopentelemetryllmtracesdonotcapturebydefault">What OpenTelemetry LLM traces do not capture by default</h3>
<p>By default, a trace records structure and cost, not content. Six toggles under <strong>Advanced privacy settings</strong> control prompts, responses, tool call details, system prompts, real tool and agent names, and real conversation and workflow IDs, and all six are off.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6c873c449fc27e07/6a9554a860f7958318d76b3c/07-privacy-settings.png" alt="Advanced privacy settings with six toggles, all off by default" /></p>
<p>By default, a trace records structure and cost, not content. Select any span in the waterfall and the detail panel says so directly: "No input/output data available for this span."</p>
<p>Identifiers are hashed rather than dropped. The run with the blocked tool call returned conversation <code>be30fb53-d351-4fa1-b5e1-a569816f85d9</code> from the API, but its spans carry <code>gen_ai.conversation.id: b1141340d0851a46</code>. That lets you group every span belonging to one conversation and compare conversations against each other, without exposing an identifier that ties back to a user's session.</p>
<p>The consequence is that you cannot join traces to conversations on the conversation ID unless you enable real IDs, and you rarely need to. The converse API hands you the correlation key directly:</p>
<pre><code>{
  "conversation_id": "be30fb53-d351-4fa1-b5e1-a569816f85d9",
  "trace_id": "3f8b9722dbd371ac4b7ad75e4bed13b6",
  "model_usage": {
    "llm_calls": 22,
    "input_tokens": 518251,
    "output_tokens": 6423,
    "model": "anthropic-claude-4.6-sonnet"
  }
}
</code></pre>
<p>Store that <code>trace_id</code> in your own decision record, and the join works without weakening the privacy defaults. Enable real IDs only when exact response-to-decision attribution is required, and restrict the trace index in the same change.</p>
<h2 id="auditingaiagentactionsbeyondthetrace">Auditing AI agent actions beyond the trace</h2>
<p>The traces stop at what the agent did, so the records that show who authorised it have to come from somewhere else.</p>
<h3 id="whoseprivilegesdoesanaiagentactionrunwith">Whose privileges does an AI agent action run with?</h3>
<p>Three identities are involved in an agentic pipeline, and each has its own boundary.</p>
<p>| Identity | Runs with | Determined by | How to scope |
| :---- | :---- | :---- | :---- |
| Agent Builder tools | The privileges of whoever is chatting | The current user, so two people can get different data from the same question | Roles, as described in <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/permissions">Agent Builder permissions</a> |
| Workflow steps | One stored API key shared by every <code>elasticsearch.*</code> and <code>kibana.*</code> step | The trigger: manual runs use the person who started them, scheduled runs use whoever last saved the workflow | <a href="https://www.elastic.co/docs/explore-analyze/workflows/authorization">Workflow authorization</a> |
| Trace readers | Index-level access, all or nothing | A role grant on <code>traces-agent_builder.otel-*</code> | A role boundary on the trace index pattern |</p>
<p>One consequence of the stored key belongs in any review. Deactivating a user or changing their role does not refresh it, and the workflow keeps running with the privileges it captured until someone saves it again or toggles <strong>Enabled</strong> off and back on. Revoking an engineer's access does not, by itself, stop workflows that still run as them.</p>
<p>Scope the investigation role to reads only:</p>
<pre><code>POST /_security/role/agent-builder-observability-investigator
{
  "cluster": ["monitor_inference"],
  "indices": [
    {
      "names": ["logs-*", "metrics-*", "traces-*"],
      "privileges": ["read", "view_index_metadata"]
    }
  ]
}
</code></pre>
<p>Reading the agent's own traces is a separate grant, needing <code>read</code> and <code>view_index_metadata</code> on <code>traces-agent_builder.otel-*</code>. Keep the two roles apart, because the people who investigate incidents and the people who audit the agent are not always the same people.</p>
<h3 id="recordingwhoapprovedanagentactioninelasticsearch">Recording who approved an agent action in Elasticsearch</h3>
<p>Run the workflow, and it stops at the approval gate, where the reviewer sees the agent's structured output rendered into the request rather than a bare confirmation prompt.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt38b441b0cded6d2c/6a9554bc0897901dfdefb3ee/08-approval-gate.png" alt="Workflow approval gate showing the agent structured output and the decision input form" /></p>
<p>The execution record is detailed. It captures <code>resumedAt</code>, <code>resumedBy</code>, the full <code>resumeInput</code> payload, per-step token usage, and a deep link back to itself.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc05efc447ca49698/6a9554d2e657a3f7b475b008/09-execution-record.png" alt="Workflow execution record showing resumedBy, resumeInput, and per-step token usage" /></p>
<p>That execution history is an operational view, not an audit store. The underlying <code>.workflows-events</code> data stream is reserved for system operations and rejects user queries outright, so you cannot run ES|QL across a quarter of decisions, and execution history is subject to retention rather than to your compliance policy.</p>
<p>Write the decision to an index you control:</p>
<pre><code>- name: review
  type: waitForInput
  with:
    message: |
      ## Approve the proposed checkout remediation?

      The evidence query matched {{ steps.collect_evidence.output.hits.total.value }} error events in the last hour.

      Agent classification: {{ steps.investigate.output.structured_output.incident_class }}
      Affected pod: {{ steps.investigate.output.structured_output.affected_pod }}
      Proposed action: {{ steps.investigate.output.structured_output.recommended_action }}
    schema:
      type: object
      properties:
        decision:
          type: string
          enum: ["approve", "decline"]
        reason:
          type: string
          enum: ["supported-by-evidence", "insufficient-evidence", "wrong-target", "unsafe-action"]
        notes:
          type: string
      required: ["decision", "reason"]

- name: record_decision
  type: elasticsearch.index
  with:
    index: "agent-action-audit"
    document:
      "@timestamp": "{{ now | date: '%Y-%m-%dT%H:%M:%S.%LZ' }}"
      "event.action": "agent_recommendation_reviewed"
      "incident.id": "{{ consts.incident_id }}"
      "agent.conversation_id": "{{ steps.investigate.output.conversation_id }}"
      "agent.incident_class": "{{ steps.investigate.output.structured_output.incident_class }}"
      "agent.affected_pod": "{{ steps.investigate.output.structured_output.affected_pod }}"
      "agent.recommended_action": "{{ steps.investigate.output.structured_output.recommended_action }}"
      "agent.evidence_count": "{{ steps.collect_evidence.output.hits.total.value }}"
      "review.decision": "{{ steps.review.output.response.decision }}"
      "review.reason": "{{ steps.review.output.response.reason }}"
      "review.notes": "{{ steps.review.output.response.notes }}"
      "review.responded_by": "{{ steps.review.output.respondedBy }}"
      "workflow.execution_id": "{{ execution.id }}"
      "workflow.executed_by": "{{ execution.executedBy }}"
      "workflow.execution_url": "{{ execution.url }}"
</code></pre>
<p>Two details in the workflow snippet above differ from the reference page.</p>
<p>The reviewer payload is nested one level deeper. The docs describe <code>steps.&lt;name&gt;.output.&lt;field&gt;</code>, but the running build returns the submitted values under <code>response</code>, alongside a <code>respondedBy</code> field:</p>
<pre><code>{
  "response": { "decision": "approve", "reason": "supported-by-evidence" },
  "respondedBy": "1506416774"
}
</code></pre>
<p><code>execution.executedBy</code> records who started the run, and <code>respondedBy</code> records who approved the action, which in a human-in-the-loop pipeline are usually different people.</p>
<p>The second detail is the timestamp. <code>{{ now }}</code> renders a JavaScript date string like <code>Sun Jul 26 2026 07:37:11 GMT+0000 (Coordinated Universal Time)</code>, which Elasticsearch rejects with <code>failed to parse date field</code>, and <code>execution.startedAt</code> has the same problem. The Liquid <code>date</code> filter fixes it.</p>
<p>The workflow editor also flags <code>steps.review.output.*</code> as an invalid variable before the first run, because the reviewer payload shape is only known once someone responds. The warning clears after the step has real output, and the templates resolve correctly at runtime.</p>
<h3 id="makingtheauditdatastreamappendonly">Making the audit data stream append-only</h3>
<p>An audit trail the agent's own pipeline can rewrite is not an audit trail. Elasticsearch provides two independent controls, and they compose.</p>
<p>First, write to a data stream rather than an index, because data streams accept appends and nothing else:</p>
<pre><code>PUT _index_template/agent-action-audit
{
  "index_patterns": ["agent-action-audit"],
  "data_stream": {},
  "priority": 500,
  "template": {
    "mappings": {
      "properties": {
        "@timestamp":            { "type": "date" },
        "event.action":          { "type": "keyword" },
        "incident.id":           { "type": "keyword" },
        "agent.conversation_id": { "type": "keyword" },
        "agent.evidence_count":  { "type": "long" },
        "agent.recommended_action": { "type": "keyword" },
        "review.decision":       { "type": "keyword" },
        "review.reason":         { "type": "keyword" },
        "review.responded_by":   { "type": "keyword" },
        "workflow.execution_id": { "type": "keyword" }
      }
    }
  }
}
</code></pre>
<p>Second, give the writer <code>create_doc</code> and nothing else, so it can add records but cannot reach for the by-query escape hatches:</p>
<pre><code>PUT _security/role/agent-action-audit-writer
{
  "indices": [
    { "names": ["agent-action-audit"], "privileges": ["create_doc", "auto_configure"] }
  ]
}
</code></pre>
<p>Tested against the running cluster, that pair behaves the way an audit store should:</p>
<p>| Attempt as the audit writer | Result |
| :---- | :---- |
| Append a decision record | <code>201 Created</code> |
| Overwrite a record by ID | <code>400</code>, only <code>op_type: create</code> is allowed in data streams |
| <code>_update_by_query</code> to change a decision | <code>403</code>, action unauthorized |
| <code>_delete_by_query</code> to erase history | <code>403</code>, action unauthorized |
| <code>_search</code> to read the trail back | <code>403</code>, action unauthorized |</p>
<p>The write-only behaviour in the last row is deliberate. The workflow that writes decisions has no reason to read them, so auditors get a separate read role and the writer stays write-only.</p>
<p>The two controls fail differently, which matters. The <code>400</code> comes from the data stream itself and applies to everyone, including a superuser. The <code>403</code> rows come from the role, and a superuser could still run them, which is why tamper-resistant retention means shipping records off the cluster the agent's operators administer.</p>
<p>For cluster-level activity, <a href="https://www.elastic.co/docs/deploy-manage/security/logging-configuration/enabling-audit-logs">enable Elasticsearch and Kibana security audit logging</a> and forward the logs to a monitoring deployment. On 9.5 <code>xpack.security.audit.enabled</code> became a dynamic cluster setting, so Elasticsearch no longer needs a restart to turn it on, though on orchestrated deployments the logs still have to be shipped somewhere readable.</p>
<h3 id="querythedecisiontrailwithesql">Query the decision trail with ES|QL</h3>
<p>Two runs of the workflow, one approved and one declined, produce two rows you can query alongside everything else in Elastic.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd2e55b4cd891ee8e/6a9554e18814aa7f0289c29f/10-decision-trail-esql.png" alt="ES|QL query over the agent-action-audit data stream returning two decision records" /></p>
<pre><code>FROM agent-action-audit
| KEEP @timestamp, agent.incident_class, agent.affected_pod, agent.recommended_action,
       agent.evidence_count, review.decision, review.reason, review.responded_by,
       workflow.execution_id
| SORT @timestamp DESC
</code></pre>
<p>Both runs saw the same 90 error events and proposed <code>restart-checkout-worker</code> on <code>checkout-worker-1</code>. The first review approved it as <code>supported-by-evidence</code>, and the second declined it as <code>wrong-target</code>, on the argument that restarting the pod hides a pricing-feed problem rather than fixing it.</p>
<p>Because both decisions are structured fields, disagreement between reviews is queryable. You can count rejections per incident class and group them by reason: <code>insufficient-evidence</code> sends you back to the investigation path, and <code>unsafe-action</code> sends you to the workflow and its permission boundary.</p>
<h2 id="aiagentobservabilitylimitstodesignaround">AI agent observability limits to design around</h2>
<p>Four behaviors are worth designing around, and each is cheaper to handle before the workflows are written.</p>
<ol>
<li><strong>Trace access is index-level, not per user.</strong> A space with sensitive conversations needs a role boundary on <code>traces-agent_builder.otel-*</code> rather than a UI setting.</li>
<li><strong>The managed dashboard is not installed automatically in a new space.</strong> Add it to your space provisioning checklist.</li>
<li><strong>The workflow execution carries its own APM <code>traceId</code>.</strong> It is not the same trace as the Agent Builder spans its <code>ai.agent</code> step produced, so correlate through the conversation ID or the <code>trace_id</code> returned by the agent rather than expecting one trace to span both.</li>
<li><strong>The <code>waitForInput</code> output shape differs from the reference page.</strong> The submitted values arrive under <code>response</code>, alongside <code>respondedBy</code>, as covered above.</li>
</ol>
<p>None of these blocks the pattern.</p>
<h2 id="wheretostartwithaiagentobservability">Where to start with AI agent observability</h2>
<p>Turn trace collection on, install the dashboard in the space your agents run in, and open the waterfall for one real conversation. It shows the tool sequence, the model split, and the latency distribution that the answer text does not.</p>
<p>Then pick the single incident class where you already trust the runbook, and add one <code>elasticsearch.index</code> step after its approval gate. An append-only decision record costs one workflow step and answers the three questions a review needs: who approved this, on what evidence, and what happened next.</p>
<p>For the details, see <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/collect-traces">Collect Agent Builder traces</a>, the <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/agent-traces-dashboard">traces overview dashboard</a>, <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/permissions">Agent Builder permissions</a>, <a href="https://www.elastic.co/docs/explore-analyze/workflows/authorization">workflow authorization</a>, and the <a href="https://www.elastic.co/docs/explore-analyze/workflows/steps/wait-for-input"><code>waitForInput</code> reference</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/ai-agent-observability-audit-trail</link>
    <guid isPermaLink="false">ai-agent-observability-audit-trail</guid>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2c757a76a8a7504d/6a9553fe0897906e2aefb3e4/01-header.png" length="0" type="image/png"/>
    <pubDate>Mon, 31 Aug 2026 15:13:52 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elastic now alerts at 80% OpenAI rate limit usage, before your app gets throttled]]></title>
    <description><![CDATA[OpenAI rate limit monitoring in Elastic maps headroom across every project and model. Compare configured RPM, TPM and IPM limits against real usage and plan capacity before a throttling alert fires.]]></description>
    <content:encoded><![CDATA[<p>Elastic's <a href="https://www.elastic.co/docs/reference/integrations/openai">OpenAI integration</a> now polls rate limits every five minutes and checks them against real usage across every project and model. You can see RPM, TPM and IPM headroom before OpenAI hits you with an HTTP 429. A prebuilt alert fires when peak one-minute utilization crosses 80% of your configured limit for three checks in a row, grouped by project and model, so one team's spike doesn't get lost in an org-wide average. OpenAI configures these limits per project, capped at or below your organization's overall ceiling. That means a single noisy project can burn through its own allocation while the rest of the org still has room, and until now, that headroom stayed invisible until it ran out.</p>
<p>The first time most teams learn that their OpenAI project is close to a rate limit is when production traffic starts getting throttled with HTTP 429 responses. OpenAI enforces rate limits at the project level, not at the organization level, so a single noisy workload in one project can saturate that project's RPM or TPM ceiling while the rest of the organization still has plenty of room. Without OpenAI rate limit monitoring that compares configured limits against actual consumption, headroom is invisible until it runs out.</p>
<h2 id="openaiapimonitoringinelasticwhatsnew">OpenAI API monitoring in Elastic: what's new</h2>
<p>We're pleased to announce updates to the <a href="https://www.elastic.co/docs/reference/integrations/openai">Elastic OpenAI integration</a>. On top of the existing token usage and audit log coverage, the integration now polls OpenAI's <a href="https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/projects/subresources/rate_limits/methods/list_rate_limits">List project rate limits Admin API</a> per project and rolls the results up into both per-project and org-wide views. A new <code>openai.rate_limits</code> dataset feeds two new dashboard panels and a prebuilt threshold alert rule, so teams can see how close each project and model is to being throttled before users experience production impact.</p>
<h2 id="whattheintegrationpollsusageauditlogsandratelimitsapis">What the integration polls: Usage, Audit Logs and Rate Limits APIs</h2>
<p>The Elastic OpenAI integration is built for teams running applications on the OpenAI API platform. The people accountable for it are the developers shipping those services, the platform and SRE teams keeping them running, and the finance and FinOps owners answering "how much is our software consuming, and are we within our capacity envelopes?"</p>
<p>The integration collects from three OpenAI Admin API surfaces:</p>
<ul>
<li><strong>Usage API</strong> for usage counts across tokens, characters, seconds, sessions, bytes, and images, with project, model, user, and API key attribution where that Usage API surface provides it.</li>
<li><strong>Audit Logs API</strong> for organization audit events such as API key creation, project changes, and user activity.</li>
<li><strong>Rate Limits API</strong> for configured RPM, TPM, and IPM ceilings per project and per model, plus other limit dimensions where available; the new headroom views compare the per-minute request, token, and image limits against actual consumption.</li>
</ul>
<p>Because everything is pulled from the Admin API at the organization level, platform teams get a unified view across every project, model and API key, alongside the rest of the telemetry they already monitor in Elastic, without touching application code or installing SDKs in every service.</p>
<h2 id="whatteamsneedtomonitorwhenrunningontheopenaiapi">What teams need to monitor when running on the OpenAI API</h2>
<p>Four operational needs come up over and over for teams running production workloads on the OpenAI API.</p>
<h3 id="tokenusageattribution">Token usage attribution</h3>
<p>A single OpenAI organization usually serves many internal teams and products, each with its own project, its own mix of models (GPT-5.5 Pro for the hardest reasoning tasks, GPT-5.4 for everyday traffic, GPT-5.4 nano for high-volume low-cost requests, and specialized models for images, audio and embeddings) and its own user and API key footprint. When usage patterns shift, the platform team needs to know which project, model and key is driving the change so they can attribute consumption back to the right team and decide which workloads should move to a cheaper model.</p>
<h3 id="ratelimitheadroom">Rate limit headroom</h3>
<p>OpenAI enforces per-model rate limits on requests per minute (RPM) and tokens per minute (TPM) at the project level, not at the organization level. The first time a team learns they're close to the ceiling is usually when production traffic starts being throttled. Surfacing configured limits alongside actual consumption, per project and per model, lets platform teams see headroom in advance, plan capacity, and request limit increases before users feel the impact.</p>
<h3 id="auditvisibility">Audit visibility</h3>
<p>Security and compliance teams need to know who created API keys, who changed project settings, who invited or removed users, and when. The integration ingests OpenAI's organization audit log so those events land in the same Elastic deployment as the usage data, ready for correlation, alerting and long-term retention. Audit log ingestion has two prerequisites: audit logging must be enabled in your OpenAI organization, and the Admin API key used by the integration must belong to an <strong>Organization Owner</strong>, because OpenAI restricts audit-log access to that role. Without both, the <code>openai.audit</code> dataset stays empty.</p>
<h3 id="granularityforeveryaudience">Granularity for every audience</h3>
<p>The same data needs to serve different cadences. SREs want one-minute resolution to catch spikes and trigger throttling alerts. Platform engineers want hourly views for capacity planning. Finance and FinOps owners want daily totals that roll up cleanly for reporting. A single integration that exposes all three granularities removes the need to maintain separate pipelines for each audience.</p>
<h2 id="howdoeselasticpolltheopenaiadminapi">How does Elastic poll the OpenAI Admin API?</h2>
<p>The integration runs on Elastic Agent and uses the CEL input to poll OpenAI's Admin API on a schedule. Authentication uses a single Admin API key, stored as an encrypted Fleet secret and redacted from agent logs. From a single configuration, the integration ingests datasets from three Admin API sources:</p>
<p><strong>Usage API datasets</strong> (per project, model, user and API key, with each dataset tracking the unit OpenAI exposes for that workload):</p>
<ul>
<li><code>openai.completions</code> for chat and completion token counts (input, output, cached, audio input/output).</li>
<li><code>openai.embeddings</code> for embedding token counts.</li>
<li><code>openai.moderations</code> for moderation token counts.</li>
<li><code>openai.images</code> for image counts and size dimensions.</li>
<li><code>openai.audio_speeches</code> for text-to-speech character counts.</li>
<li><code>openai.audio_transcriptions</code> for speech-to-text duration in seconds.</li>
<li><code>openai.code_interpreter_sessions</code> for code interpreter session counts.</li>
<li><code>openai.vector_stores</code> for vector store byte counts.</li>
</ul>
<p><strong>Audit Logs API dataset:</strong></p>
<ul>
<li><code>openai.audit</code> for organization audit events such as API key creation, project changes and user activity.</li>
</ul>
<p><strong>Rate Limits API dataset:</strong></p>
<ul>
<li><code>openai.rate_limits</code> <em>(new)</em> for snapshots of configured rate limits per project and per model, including RPM, TPM, IPM, and other limit fields where OpenAI returns them, paged across all active projects on each poll.</li>
</ul>
<p>Ingest pipelines handle parsing and field mapping so the data lands queryable, dashboard-ready, and aligned with the rest of Elastic Observability. Because the data is pulled from the Admin API at the organization level, you get this visibility without any application-side instrumentation or SDK changes.</p>
<h2 id="whatyouneedtosetupopenaimonitoringinelastic">What you need to set up OpenAI monitoring in Elastic</h2>
<p>To get started with the Elastic OpenAI integration, you will need:</p>
<ul>
<li>An Elastic deployment:</li>
<li><strong>Elastic Cloud Hosted (ECH)</strong> running a recent supported version, or</li>
<li><strong>Elastic Cloud Serverless</strong>, no version requirement, works out of the box.</li>
<li>An OpenAI organization with <strong>Admin API</strong> access.</li>
<li>An <strong>Admin API key</strong> provisioned by an <strong>Organization Owner</strong> from the <a href="https://platform.openai.com/settings/organization/admin-keys">OpenAI platform settings</a> under <strong>Settings → Admin keys</strong>. Owner-level keys are required if you want the <code>openai.audit</code> dataset to populate.</li>
<li>Audit logging enabled in your OpenAI organization, if you want audit data.</li>
<li>Elastic Agent installed on a host with outbound HTTPS access to <code>api.openai.com</code>, or the agentless deployment option.</li>
</ul>
<h2 id="howtosetuptheopenaiintegration">How to set up the OpenAI integration</h2>
<ol>
<li>Generate an Admin API key in the <a href="https://platform.openai.com/settings/organization/admin-keys">OpenAI platform settings</a>.</li>
<li>In Kibana, go to <strong>Management → Integrations</strong>, search for <strong>OpenAI</strong> and click <strong>Add</strong>.</li>
<li>Choose your deployment mode: <strong>agentless</strong> for a zero-install experience, or <strong>Elastic Agent</strong> on your own host.</li>
<li>Tune the defaults if you need to. Each dataset has sensible defaults:</li>
</ol>
<ul>
<li><strong>Usage datasets</strong> poll every 5 minutes with 1-minute buckets. Each dataset exposes a <code>finalization_grace</code> setting that controls when a per-minute usage bucket is considered final. The default <code>0s</code> favors freshness: a bucket is ingested as soon as its minute closes. The observed behavior (which OpenAI does not document, but the integration team measured against the live API) is that bucket counts can keep rising for some time after that point, so per-minute totals at <code>0s</code> can undercount during heavy bursts. Setting <code>finalization_grace</code> to <code>15m</code>, the recommended value for accurate counts, holds a bucket back until the grace window has elapsed and brings counts much closer to the Usage API, though a small residual undercount can remain during very high-volume bursts because OpenAI's per-minute counts can be revised upward beyond any fixed grace window. The cost is delaying dashboards and the rate limit headroom alert by the grace period.</li>
<li><strong>Rate limits</strong> polls every 5 minutes. Each poll captures the full set of configured RPM, TPM and IPM limits per project and per model.</li>
<li><strong>Audit logs</strong> polls on a separate cadence and ingests all org-level audit events. Remember the prerequisites: audit logging enabled in your OpenAI organization and an Organization-Owner Admin API key.</li>
</ul>
<ol>
<li>Open the integration assets in Kibana. Within minutes, usage, audit, and rate-limit data starts flowing, and the prebuilt dashboards and alert rule are ready to use.</li>
</ol>
<p>For the full configuration reference, see the <a href="https://www.elastic.co/docs/reference/integrations/openai">OpenAI integration documentation</a>.</p>
<h2 id="whatdotheopenairatelimitdashboardsshow">What do the OpenAI rate limit dashboards show?</h2>
<p>The integration ships with a pre-built Kibana dashboard that gives you an immediate, queryable view of your organization's OpenAI API consumption. The overview pulls headline numbers (total tokens, total invocations, top models, top projects, top users and top API keys) into one place for a quick read on the state of your OpenAI usage. The screenshot below shows the OpenAI usage overview dashboard:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt55959947293efa82/6a7f0f1805b7b5417b18ba40/openai-overview.png" alt="Pre-built OpenAI usage overview dashboard in Elastic showing total tokens, top models, top projects, top users and top API keys" /></p>
<p>From the overview, you can drill into the views that answer the operational needs introduced earlier.</p>
<h3 id="tokenusagebymodelprojectanduser">Token usage by model, project and user</h3>
<p>The token metrics panels break down token consumption (input, output, cached input, audio input/output) for the token-based datasets (<code>openai.completions</code>, <code>openai.embeddings</code>, <code>openai.moderations</code>) by model and over time. This is the view that tells you where your token budget is actually going, which workloads are getting the most out of prompt caching, and which projects, users or API keys are driving the bulk of your token consumption. Filter by project or model to scope the view to a single team or product. Image, audio and vector-store consumption (measured in images, characters, seconds, sessions and bytes rather than tokens) is reported in dedicated sections of the same dashboard. The token metrics panels look like this:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb92bc42bd94d5c6d/6a7f0f1b63e959626e73dec2/openai-token.png" alt="OpenAI token usage metrics by model and project in Elastic, showing input, output, cached and audio token consumption over time" /></p>
<h3 id="ratelimitheadroomperprojectandmodelnew">Rate limit headroom: per project and model <em>(new)</em></h3>
<p>The new rate limit headroom panel joins the configured limits from <code>openai.rate_limits</code> against actual consumption from the usage datasets, per <code>project_id</code> and <code>model</code>. For each row it reports peak one-minute used, the configured limit, and utilization percentage for requests (RPM), tokens (TPM), and images (IPM). Rows are sorted by highest TPM utilization first, with RPM and IPM utilization as tie-breakers, so the highest token-pressure rows appear at the top of the list. Utilization is computed against the peak one-minute bucket in the lookback window, never a 5- or 15-minute sum against a one-minute ceiling, so the panel reflects peak-minute pressure against the one-minute ceiling instead of averaging it away. The per-project rate limit headroom panel is shown below:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd81c080dff528457/6a7f0f1e2f00b2a2f9efec60/openai-rate_limit.png" alt="OpenAI rate limit headroom dashboard panel in Elastic, showing RPM, TPM and IPM utilization per project and model with the closest-to-throttling row at the top" /></p>
<h3 id="ratelimitheadroomorgwiderollupbymodelnew">Rate limit headroom: org-wide rollup by model <em>(new)</em></h3>
<p>Because OpenAI enforces limits per project, a single per-project view doesn't answer "how much total capacity do we have for <code>gpt-image-2</code> across the organization?" The new org-wide rollup panel reports the same RPM, TPM and IPM metrics summed across all active projects for each model. Both the limit and the usage figures are indicative upper bounds rather than exact org-wide numbers (the limit is a sum of per-project ceilings; the usage is a sum of each project's peak minute, which may fall in different minutes across projects), but together they give platform teams a single number to plan against when they're sizing a new workload or deciding which project should absorb a new use case. The org-wide rollup panel is shown below:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt783a4f0120092992/6a7f0f21c2cc09a3a8249686/openai-rate_limit_org_wide.png" alt="OpenAI rate limit headroom org-wide rollup in Elastic, summing RPM, TPM and IPM metrics by model across all active projects" /></p>
<p>Behind the scenes, version <code>2.3.0</code> also normalizes request and token counts into shared <code>openai.base.usage_tokens</code> and <code>openai.base.usage_images</code> fields across the usage datasets, so the headroom panels render correctly even when only a subset of usage datasets is enabled.</p>
<h3 id="openaiauditlogactivityinelastic">OpenAI audit log activity in Elastic</h3>
<p>The audit panels surface organization audit events (API key creations, project changes, user invitations and login activity) so security and compliance teams can review who did what, when, alongside the usage data. The audit dashboard is shown below:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt788a856cc65581ab/6a7f0f2496b5a6dae787b541/openai-audit.png" alt="OpenAI audit log dashboard in Elastic, showing API key creation, project changes, user invitations and login activity events" /></p>
<h2 id="outoftheboxalertforratelimitheadroomnew">Out-of-the-box alert for rate limit headroom <em>(new)</em></h2>
<p>The integration ships with a pre-built threshold alert rule template, <code>[OpenAI] Rate limit headroom low</code>, ready to install in one click from the integration's Assets tab.</p>
<p>The default behavior is tuned to be useful out of the box:</p>
<ul>
<li>Runs every 5 minutes.</li>
<li>Looks back over the last 15 minutes.</li>
<li>Fires after 3 consecutive matches.</li>
<li>Triggers when peak one-minute TPM utilization reaches or exceeds 80% of the configured project/model limit.</li>
<li>Groups alerts by <code>project_id::model</code>, so an incident in one project on one model doesn't get lost in an org-wide aggregate.</li>
</ul>
<p>The 80% threshold and other parameters are editable in Kibana after you install the rule, so each team can tune the alert to its own risk tolerance.</p>
<h2 id="customopenaialertsandslosinelasticobservability">Custom OpenAI alerts and SLOs in Elastic Observability</h2>
<p>As with every other Elastic integration, all the OpenAI metrics and audit data is fully available to leverage in every capability in <a href="https://www.elastic.co/observability">Elastic Observability</a>, including <a href="https://www.elastic.co/guide/en/observability/current/slo.html">SLOs</a>, <a href="https://www.elastic.co/guide/en/observability/current/create-alerts.html">alerting</a>, custom <a href="https://www.elastic.co/guide/en/kibana/current/dashboard.html">dashboards</a> and in-depth <a href="https://www.elastic.co/guide/en/observability/current/monitor-logs.html">logs exploration</a>.</p>
<p>For example, to keep token consumption under control across a single project, create a custom threshold rule that sums tokens from the relevant usage dataset and fires when the daily or hourly total crosses your budget. To track model mix, define an SLO in Elastic Observability that treats OpenAI requests on your approved lower-cost model families as the "good events" (the ones that count as meeting the target) and all OpenAI requests as the "total events", grouped by <code>openai.base.project_id</code> and <code>openai.base.user_id</code>. The ratio becomes your SLI; a 7-day rolling 80% target quickly surfaces projects and users overusing more expensive models.</p>
<h2 id="choosingopenaiusagedatagranularity">Choosing OpenAI usage data granularity</h2>
<p>OpenAI usage data collected by the integration powers different cadences, with a fidelity-versus-freshness tradeoff to be aware of. One-minute usage buckets feed the rate limit headroom alert and near-real-time throttling notifications when a project approaches its ceiling: with <code>finalization_grace</code> set to <code>0s</code> (the default), per-minute counts arrive within minutes but can undercount during heavy bursts; raising <code>finalization_grace</code> to <code>15m</code> brings counts much closer to reconciled at the cost of delaying the dashboards and alert by the grace period; a small residual undercount can still remain for the busiest buckets. Hourly views support operational monitoring and capacity planning across projects and models. Daily aggregates roll up cleanly for FinOps reporting and reconciliation. An out-of-the-box alert ships for rate limit headroom (<code>[OpenAI] Rate limit headroom low</code>), and the same data can be reused for custom usage and budget thresholds without building anything from scratch.</p>
<h2 id="getstartedwithopenaimonitoringinelastic">Get started with OpenAI monitoring in Elastic</h2>
<p>The <a href="https://www.elastic.co/docs/reference/integrations/openai">Elastic OpenAI integration</a> is available today in Elastic Cloud, including Elastic Cloud Hosted and Elastic Cloud Serverless. To get started, sign up for a <a href="https://cloud.elastic.co/registration">free Elastic Cloud trial</a>, provision an Admin API key in the <a href="https://platform.openai.com/settings/organization/admin-keys">OpenAI platform settings</a>, and add the OpenAI integration from Kibana under <strong>Management → Integrations</strong>.</p>
<p>Within minutes you'll have token usage, audit activity, and rate limit headroom data flowing into Elasticsearch, with the prebuilt dashboards and the new throttling alert ready to use.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/openai-rate-limit-monitoring</link>
    <guid isPermaLink="false">openai-rate-limit-monitoring</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[Metrics]]></category>
    <dc:creator><![CDATA[Daniela Tzvetkova]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb99f918480cb486e/6a7f0f273cab1c5c100e493a/title_openai_rate_limit.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elastic Ramen: A CLI harness for SRE investigation and remediation]]></title>
    <description><![CDATA[Exploring Elastic Ramen, a CLI harness that brings Agent Builder conversations, skills, and tools into the terminal so engineers can move from investigation to remediation in a single thread.]]></description>
    <content:encoded><![CDATA[<p>Observability tools tell you what went wrong.
They rarely help you fix it.
When responding to an incident, engineers split their time across Kibana, Slack, and the terminal.
At each step, the AI assistant stays behind in the previous surface, and the investigation starts over from scratch.</p>
<p><strong>Elastic Ramen</strong> (<strong>R</strong>oot-cause <strong>A</strong>nalysis &amp; <strong>M</strong>onitoring <strong>En</strong>gine) bridges that gap.
It is a local CLI agent that connects directly to <a href="https://www.elastic.co/search-labs/blog/elastic-ai-agent-builder-context-engineering-introduction">Elastic Agent Builder</a>, carrying the same conversation, skills, and Elastic context into the terminal.
Ramen operates directly in the environment where fixes actually happen. No handoff. No re-auth. No translation layer.
Ramen is open source and available at <a href="https://github.com/elastic/elastic-ramen">elastic/elastic-ramen</a>.</p>
<div>
    
</div>
<h2 id="whytheterminalmatters">Why the terminal matters</h2>
<p>Agent Builder gives engineers a strong environment for querying observability data.
Ramen takes that same capability to the two workflows that need it most.</p>
<p><strong>Onboarding.</strong>
Configuring collectors, managing credentials, and validating data flow all happen in the shell.
A local agent can guide that work right where the credentials and tools already live.</p>
<p><strong>Mitigation.</strong>
The actual fix, whether restarting pods, scaling deployments, or rolling back releases, requires <code>kubectl</code>, <code>gcloud</code>, <code>git</code>, or internal scripts.
A CLI agent runs on hardware the team already trusts, using the credentials already present on the engineer's machine.</p>
<h2 id="howramenworks">How Ramen works</h2>
<p>Ramen is a CLI client for Agent Builder.
It is not a separate assistant with its own memory.
It connects your local environment to the same conversations, skills, and tools you already use in Kibana through a simple authentication flow.</p>
<p>On first launch, Ramen connects to your Elastic deployment and gives you everything out of the box:</p>
<ul>
<li>LLM inference through the Kibana gateway, using your existing AI connector</li>
<li>Native Kibana tools for managing workflows and agents</li>
<li>The Agent Builder MCP server for ES|QL queries and documentation search</li>
<li>An embedded <code>elastic</code> CLI for cluster health, data streams, and SLOs</li>
<li>Built-in skills for root cause analysis and SLO management</li>
</ul>
<p>The agent carries your investigation history across surfaces, so you never re-explain the incident when moving from the UI to the CLI.
Terminal interactions sync back to Elastic automatically, building a searchable record of operational knowledge for the team.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltac16bc2fa6b8d5c4/6a85cacd80984c13d1668fd6/architecture-flow.jpg" alt="Diagram showing the Ramen CLI connecting to Agent Builder, which accesses Elastic Stack data, with conversations syncing back." /></p>
<h2 id="getstarted">Get started</h2>
<p>You need an Elastic Observability Serverless project.
In Kibana, open <strong>Stack Management</strong>, then <strong>Advanced Settings</strong>, or go directly to <code>https://&lt;your-kibana-url&gt;/app/management/kibana/settings?query=ramen</code>.
Enable <strong><code>elasticRamen:enabled</code></strong>, then install the CLI:</p>
<pre><code>npm i -g @elastic/ramen
bun add -g @elastic/ramen
</code></pre>
<p>You can also use the install script or download a pre-built binary from <a href="https://github.com/elastic/elastic-ramen/releases">GitHub Releases</a>:</p>
<pre><code>curl -fsSL https://raw.githubusercontent.com/elastic/elastic-ramen/dev/install | bash
</code></pre>
<p>Once installed, connect to your deployment:</p>
<pre><code>elastic-ramen --kibana-base=https://&lt;your-kibana-url&gt;
</code></pre>
<p>Ramen opens a browser auth flow, generates credentials, and stores them locally.
After that, it reconnects automatically.
Start a conversation in Agent Builder and resume it in the terminal with <code>/kibana-conversations</code>.</p>
<h2 id="whatisnext">What is next</h2>
<p>Ramen is the first surface of a multi-surface agent system.
The same architecture extends to every surface engineers already use:</p>
<ul>
<li><strong>Space-scoped collaboration</strong> for shared agent context during outages</li>
<li><strong>Slack, Teams, Jira, PagerDuty</strong> integration: start from an alert, collaborate in chat, mitigate in the terminal, one thread</li>
<li><strong>Shared memory</strong>: progressively distill conversations into durable operational context that improves future investigations</li>
</ul>
<p>Beyond incident response, the same model applies to deployment risk analysis, production debugging, CI/CD policy checks, and cost anomaly investigation.</p>
<h2 id="summary">Summary</h2>
<p>Ramen connects signal to action: Elastic data and Agent Builder context, plus the ability to act with local tools, in one continuous thread.
Elastic as the persistent context layer, every surface you use as the interface.</p>
<p>Try it out on <a href="https://github.com/elastic/elastic-ramen">GitHub</a> and let us know what you think.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/elastic-ramen-agent-builder-cli</link>
    <guid isPermaLink="false">elastic-ramen-agent-builder-cli</guid>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Joe Reuter,Vignesh Shanmugam]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt130656ed78a12658/6a85cad018249c018f18f7b9/cover.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Windows Event Log Monitoring with OpenTelemetry & Elastic Streams]]></title>
    <description><![CDATA[Learn how to enhance Windows Event Log monitoring with OpenTelemetry for standardized ingestion and Elastic Streams for smart partitioning and analysis.]]></description>
    <content:encoded><![CDATA[<p>For system administrators and SREs, Windows Event Logs are both a goldmine and a graveyard. They contain the critical data needed to diagnose the root cause of a server crash or a security breach, but they are often buried under gigabytes of noise. Traditionally, extracting value from these logs required brittle regex parsers, manual rule creation, and a significant amount of human intuition.</p>
<p>However, the landscape of log management is shifting. By combining the industry-standard ingestion of OpenTelemetry (OTel) with the AI-driven capabilities of Elastic Streams, we can change how we monitor Windows infrastructure. This approach isn't just moving data. We are also using Large Language Models (LLMs) to understand it.</p>
<h2 id="thechallengewithtraditionalwindowslogging">The Challenge with Traditional Windows Logging</h2>
<p>Windows generates a massive variety of logs: System, Security, Application, Setup, and Forwarded Events. Within those categories, you have thousands of Event IDs. Historically, getting this data into an observability platform involved installing proprietary agents and configuring complex pipelines to strip out the XML headers and format the messages.</p>
<p>Once the data was ingested, we can try to figure out what "bad" looked like. You had to know in advance that Event ID 7031 indicated a service crash, and then write a specific alert for it. If you missed a specific Event ID or if the format changed, your monitoring went dark.</p>
<h2 id="step1ingestionviaopentelemetry">Step 1: Ingestion via OpenTelemetry</h2>
<p>The first step in modernizing this workflow is adopting OpenTelemetry. The OTel collector has matured significantly and now offers robust support for Windows environments. By installing the collector directly on Windows servers, you can configure receivers to tap into the event log subsystems.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt13a67d803cdc46b4/6a7f1cabb6b734b8c7e49216/otel-config.png" alt="OTel collector configuration for Windows Event Logs" /></p>
<p>The beauty of this approach is standardization. You aren't locked into a vendor-specific shipping agent. The OTel collector acts as a universal router, grabbing the logs and sending them to your observability backend in this case, the Elastic logs index designed to handle high-throughput streams.</p>
<p>The key thing to pay attention to in this configuration is how we add this transform statement:</p>
<pre><code>transform/logs-streams:
  log_statements:
    - context: resource
      statements:
        - set(attributes["elasticsearch.index"], "logs")
</code></pre>
<p>This works with the vanilla opentelemetry collector and when the data arrives in Elastic, it tells Elastic to use the new wired streams feature which enables all the downstream AI features we discuss in later steps.</p>
<p>Checkout my example configuration <a href="https://github.com/davidgeorgehope/otel-collector-windows/blob/main/config.yaml">here</a></p>
<h2 id="step2aidrivenpartitioning">Step 2: AI-Driven Partitioning</h2>
<p>Once the data arrives, the next challenge is organization. Dumping all Windows logs into a single <code>logs-*</code> index is a recipe for slow queries and confusion. In the past, we split indices based on hardcoded fields. Now, we can use AI to "fingerprint" the data.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4de0a4697a52249b/6a7f1cafea068d714cf0a330/ai-partitioning.png" alt="AI-driven partitioning of Windows logs" /></p>
<p>This process involves analyzing the incoming stream to identify patterns. The system looks at the structure and content of the logs to determine their origin. For example, it can distinguish between a <code>Windows Security Audit</code> log and a <code>Service Control Manager</code> log purely based on the data shape.</p>
<p>The result is automatic partitioning. The system creates separate, optimized "buckets" or streams for each data type. You get a clean separation of concerns, Security logs go to one stream, File Manager logs to another, without having to write a single conditional routing rule. This partitioning is crucial for performance and for the next phase of the process: analysis.</p>
<h2 id="step3significanteventsandllmanalysis">Step 3: Significant Events and LLM Analysis</h2>
<p>Once your data is partitioned (e.g., into a dedicated <code>Service Control Manager</code> stream), you can apply GenAI models to analyze the semantic meaning of that stream.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt32645d1a432e8bfb/6a7f1cb3bdcff01f02c4331b/llm-analysis.png" alt="LLM analysis of log streams" /></p>
<p>In a traditional setup, the system sees text strings. In an AI-driven setup, the system understands context. When an LLM analyzes the <code>Service Control Manager</code> stream, it identifies what that system is responsible for. It knows that this specific component manages the starting and stopping of system services.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf18fd4bedf526eb5/6a7f1cb6e3a219399f99f902/significant-events-suggestions.png" alt="Significant events suggestions from AI" /></p>
<p>Because the model understands the <em>purpose</em> of the log stream, it can generate suggestions for what constitutes a "Significant Event." It doesn't need you to tell it to look for crashes; it knows that for a Service Manager, a crash is a critical failure.</p>
<h3 id="frompassivestoragetoproactivesuggestions">From Passive Storage to Proactive Suggestions</h3>
<p>The workflow effectively automates the creation of detection rules. The LLM scans the logs and generates a list of potential problems relevant to that specific dataset, such as:</p>
<ul>
<li><strong>Service Crashes:</strong> High severity anomalies where background processes terminate unexpectedly.</li>
<li><strong>Startup/Boot Failures:</strong> Critical errors preventing the OS from reaching a stable state.</li>
<li><strong>Permission Denials:</strong> Security-relevant events regarding service interactions.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1ec41d68fba309eb/6a7f1cba63e9593c6073e2bb/significant-events-list.png" alt="List of significant events detected" /></p>
<p>It bubbles these up as suggested observations. You can review a list of potential issues, see the severity the AI has assigned to them (e.g., Critical, Warning), and with a single click, generate the query required to find those logs.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt41d653eef46a3c18/6a7f1cbd9090b0c7ab84ee8b/query-generation.png" alt="Auto-generated query for significant events" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>The combination of OpenTelemetry for standardized ingestion and AI-driven Streams for analysis turns the chaotic flood of Windows logs into a structured, actionable intelligence source. We are moving away from the era of "log everything, look at nothing" to an era where our tools understand our infrastructure as well as we do.</p>
<p>The barrier to effective monitoring is no longer technical complexity. Whether you are tracking security audits or debugging boot loops, leveraging LLMs to partition and analyze your streams is the new standard for observability.</p>
<p><a href="https://cloud.elastic.co/serverless-registration?onboarding_token=observability">Try Streams today</a></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/windows-event-monitoring-with-opentelemetry-and-elastic-streams</link>
    <guid isPermaLink="false">windows-event-monitoring-with-opentelemetry-and-elastic-streams</guid>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[David Hope]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4de0a4697a52249b/6a7f1cafea068d714cf0a330/ai-partitioning.png" length="0" type="image/png"/>
    <pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elastic Observability: Streams Data Quality and Failure Store Insights]]></title>
    <description><![CDATA[Discover how the Streams a new AI driven Elastic Observability feature help manage data quality with a failure store to help you monitor, troubleshoot, and retain high-quality data.]]></description>
    <content:encoded><![CDATA[<p>When working with observability and logging data, not all documents make it into Elasticsearch in pristine condition. Some may be dropped due to processing failures in ingest pipelines or mapping errors, while others may be partially ingested with ignored fields if a fields value is incompatible with the defined mappings. These issues can impact downstream analysis and dashboards. Streams data quality makes it easier than ever to monitor the health of your ingested data, identify potential issues, and take corrective action right from the UI. With data quality, you can now see exactly how well your Stream is performing and quickly understand whether your data has a <strong>Good</strong>, <strong>Degraded</strong>, or <strong>Poor</strong> quality.</p>
<h2 id="whatsindataquality">What's in data quality</h2>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd3a30fe96ac6e296/6a7f04c23cab1c41ed0e44ca/data-quality-tab.png" alt="Data quality tab" /></p>
<h3 id="ataglancesummary">At-a-glance summary</h3>
<p>The summary card shows:</p>
<ul>
<li><strong>Degraded documents</strong> - Documents that contain the <code>_ignored</code> field - see <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-ignored-field">this</a> for more info.  </li>
<li><strong>Failed documents</strong> - Documents that were rejected at ingestion due to mapping conflicts or pipeline failures.</li>
</ul>
<p>The overall <strong>quality score</strong> (Good, Degraded, Poor) is automatically calculated based on the percentage of degraded and failed documents.</p>
<h3 id="trendsovertime">Trends over time</h3>
<p>The tab includes a time-series chart so you can track how degraded and failed documents are accumulating over time. Use the <strong>date picker</strong> to zoom into a specific range and understand when problems are spiking.</p>
<h3 id="qualityissuestable">Quality issues table</h3>
<p>A detailed table lists the types of issues affecting your stream. For each issue, you can:</p>
<ul>
<li>See which fields are causing problems.  </li>
<li>Review counts of affected documents.  </li>
<li>Filter by issues that have not been solved yet (Current issues only).  </li>
<li>Open a <strong>flyout</strong> to dive deeper into the cause of the issue and learn how to fix it.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2243f9ecead50c83/6a7f04c5ead8ec69aebaa49b/quality-issue-flyout.png" alt="Data quality issue flyout" /></p>
<h2 id="monitoringdegradeddocuments">Monitoring degraded documents</h2>
<p>A degraded document is one that contains the <code>_ignored</code> field, which means one or more of its fields were ignored during indexing. One of the reasons could be that their values didn’t match the expected mappings. While the rest of the document is still indexed, a high number of degraded documents can affect query results, dashboards, and overall observability accuracy.</p>
<p>To help keep these issues under control, the Data quality tab provides visibility into the percentage of degraded documents in your stream.</p>
<h3 id="setuparuletostayaheadofissues">Set up a rule to stay ahead of issues</h3>
<p>You can use the <strong>Create rule</strong> button above the Degraded docs chart to define an alert that notifies you when the percentage of degraded documents crosses a certain threshold. This makes it easy to proactively monitor for mapping mismatches and ensure your data continues to meet quality expectations.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5a0a67cc1e79eef/6a7f04c8b6b734cad3e48a49/create-rule-button.png" alt="Create rule button" /></p>
<p>For more information on how to configure this rule, see <a href="https://www.elastic.co/docs/solutions/observability/incident-management/create-a-degraded-docs-rule#degraded-docs-rule-conditions">Degraded docs rule conditions</a>.</p>
<h2 id="handlingfaileddocumentswiththefailurestore">Handling failed documents with the failure store</h2>
<p><a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/failure-store"><strong>Failure store</strong></a> is a special index that captures documents rejected during ingestion. Instead of losing this data, the failure store retains it in a dedicated <code>::failures</code> index, allowing you to inspect the problematic documents, understand what went wrong, and fix the underlying issues.</p>
<p>In Data Quality tab, the failed documents are only visible if your stream has a failure store enabled, for checking failure store documents you are required to have at least <code>read_failure_store</code> privileges. If the failure store is <strong>not enabled</strong>, you’ll see an <strong>“Enable failure store”</strong> link that opens a modal to configure it and set the retention period. For enabling failure store you are required to have <code>manage_failure_store</code> privileges over the specific data stream. For further information about failure store security you can refer to <a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/failure-store#use-failure-store-searching">Searching failures</a>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3b13256241ba414d/6a7f04cc4c4bfb223eccd1c3/enable-fs-link.png" alt="Enable failure store link" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3fab88aed8a59595/6a7f04cfead8ec0fb9baa49f/failure-store-modal.png" alt="Failure store configuration modal" /></p>
<p>Once enabled, you can <strong>edit the failure store configuration</strong> or disable it at any time using the <strong>Edit</strong> button above the failed docs chart.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt39033956ac35e490/6a7f04d273d9bd342429d7ac/edit-fs-button.png" alt="Edit failure store button" /></p>
<p>The failure store can also be configured in the Streams Retention tab - see <a href="https://www.elastic.co/blog/simplifying-retention-management-with-streams.mdx">this article</a> for more information.</p>
<h2 id="technicalimplementation">Technical implementation</h2>
<p>Under the hood, the <strong>Data quality</strong> tab builds on the existing <strong>Dataset quality</strong> plugin - the same one that powers the <a href="https://www.elastic.co/docs/solutions/observability/data-set-quality-monitoring"><strong>Dataset quality page</strong></a> in <strong>Stack Management</strong>. However, instead of working in the context of datasets following the Data stream naming scheme, it’s now tailored specifically for <strong>streams</strong>.</p>
<p>To determine the quality of a stream, the UI sends three <strong>ES|QL</strong> query server requests:</p>
<ol>
<li><strong>All documents (including failures):</strong></li>
</ol>
<pre><code> FROM myStream, myStream::failures | STATS doc_count = COUNT(*)
</code></pre>
<ol>
<li><strong>Failed documents only:</strong></li>
</ol>
<pre><code> FROM myStream::failures | STATS failed_doc_count = COUNT(*)
</code></pre>
<ol>
<li><strong>Degraded documents:</strong></li>
</ol>
<pre><code>FROM myStream METADATA _ignored | WHERE _ignored IS NOT NULL | STATS degraded_doc_count = COUNT(*)
</code></pre>
<p>The results of these queries are then used to calculate the <strong>percentages</strong> of failed and degraded documents. The overall data quality is determined using simple thresholds:</p>
<ul>
<li><strong>Good:</strong> Both percentages are 0%</li>
<li><strong>Degraded:</strong> Any percentage is greater than 0% but less than 3%</li>
<li><strong>Poor:</strong> Any percentage is above 3%</li>
</ul>
<p>For managing the <strong>failure store</strong>, Streams uses the <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-data-stream-options">Update data stream options API</a> with the <code>failure_store</code> parameter to configure and update the failure store settings, including enabling the store and setting the retention period.</p>
<h2 id="whyyoulllovethis">Why you’ll love this</h2>
<p>The new <strong>Data quality</strong> tab gives you:  </p>
<ul>
<li>Visibility into ingestion problems without digging into logs  </li>
<li>A clear breakdown of degraded vs. failed documents  </li>
<li>Insights into which fields are ignored and why  </li>
<li>Tools to capture and troubleshoot failed docs with the failure store</li>
</ul>
<p>By surfacing data quality issues directly in the Streams UI, we’re making it easier to keep your data flowing reliably and to ensure your analytics are built on a strong foundation.</p>
<h2 id="tryitouttoday"><strong>Try it out today</strong></h2>
<p>The <strong>data quality</strong> feature is available in <strong>Elastic Observability on Serverless</strong>, and coming soon for self-managed and Elastic Cloud users.</p>
<p>Sign up for an Elastic trial at <a href="http://cloud.elastic.co">cloud.elastic.co</a>, and trial Elastic's Serverless offering which will allow you to play with all of the Streams functionality.</p>
<p>For more information on Streams:</p>
<p><em>Read about</em> <a href="https://www.elastic.co/observability-labs/blog/reimagine-observability-elastic-streams"><em>Reimagining streams</em></a></p>
<p><em>Look at the</em> <a href="http://elastic.co/elasticsearch/streams"><em>Streams website</em></a></p>
<p><em>Read the</em> <a href="https://www.elastic.co/docs/solutions/observability/streams/streams"><em>Streams documentation</em></a></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/data-quality-and-failure-store-in-streams</link>
    <guid isPermaLink="false">data-quality-and-failure-store-in-streams</guid>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Elena Stoeva,Yngrid Coello]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1ec20ca008eb1b74/6a7f04d51967ea791e33037f/article.png" length="0" type="image/png"/>
    <pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[How Streams in Elastic Observability Simplifies Retention Management]]></title>
    <description><![CDATA[Learn how Streams simplifies retention management in Elasticsearch with a unified view to monitor, visualize, and control data lifecycles using DSL or ILM.]]></description>
    <content:encoded><![CDATA[<p>Managing retention in Elasticsearch can get complicated fast. Between <a href="https://www.elastic.co/docs/manage-data/lifecycle/data-stream">Data stream lifecycle (DSL)</a>, <a href="https://www.elastic.co/docs/manage-data/lifecycle/index-lifecycle-management">Index lifecycle management (ILM)</a>, templates, and individual index settings, keeping policies consistent across data streams often takes more effort than it should.</p>
<p><strong>Streams</strong> changes that. It introduces a clear, unified way to manage how long your data lives, whether you’re using DSL or ILM. You can visualize ingestion, understand where data sits across tiers, and adjust retention with confidence, applying updates to a single stream without worrying about unintended changes elsewhere, all from a single view.</p>
<h3 id="walkthroughexploringtheretentiontab">Walkthrough: Exploring the Retention Tab</h3>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd3add839c290ff4d/6a7f1ace42a117193695c313/retention_view.png" alt="Retention view of a stream" /></p>
<p>Retention management lives in the <strong>Retention</strong> tab of each stream. This is your control panel for understanding how much data you’re storing, how quickly it’s growing, and how your lifecycle policies are applied. It’s also where you can monitor and configure the <a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/failure-store">Failure store</a>, which tracks and retains documents that failed to be ingested.</p>
<h4 id="metricsataglance">Metrics at a glance</h4>
<p>At the top of the view, you’ll find an overview of key metrics:</p>
<ul>
<li>Storage size: the total data volume currently held by the stream.</li>
<li>Ingestion averages: calculated from the selected time range, Streams extrapolates both daily and monthly averages to give you a sense of long-term trends.</li>
</ul>
<p>This combination of near-real-time and projected values helps you quickly spot when ingestion is ramping up and whether your retention policy aligns with it.</p>
<h4 id="ingestionovertime">Ingestion over time</h4>
<p>Below the metrics, a graph shows ingestion volume over time. This information is approximated based on the number of documents over time, multiplied by the average document size in the backing index. </p>
<h4 id="visualizinglifecyclephases">Visualizing lifecycle phases</h4>
<p>When an ILM policy is effective, the retention view becomes more visual. Streams displays a phase breakdown (hot, warm, cold, frozen) showing the data volume stored in each phase. This gives you a clear sense of how your data is distributed across the storage tiers and whether your lifecycle is doing what you expect.</p>
<h4 id="failurestore">Failure store</h4>
<p>A failure store is a secondary set of indices inside a data stream, dedicated to storing documents that failed to be ingested. Within the Retention tab, you can toggle the Failure store on or off, and configure its own retention period.
We’ll cover Failure store and Data quality in more detail in <a href="https://www.elastic.co/observability-labs/blog/data-quality-and-failure-store-in-streams">this article</a>.</p>
<h3 id="updatingretention">Updating Retention</h3>
<p>Beyond visualizing your retention, Streams makes it easy to change how it’s managed.</p>
<h4 id="switchingbetweendslandilm">Switching between DSL and ILM</h4>
<p>You can freely switch a stream between DSL and ILM management, or update a DSL retention  with just a few clicks. Streams takes care of updating the lifecycle settings at the data stream level, ensuring consistent retention across all existing backing indices, not just new ones.</p>
<p>Whether you prefer the simplicity of DSL or the fine-grained tiering of ILM, you can move between the two seamlessly. </p>
<p><em>Clicking “Edit data retention” opens a modal that allows you to update the stream’s configuration. From there you can update the ILM policy or set a custom retention period via DSL.</em>
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf84e9c56b29c83ce/6a7f1ad1e88c6577ce00bb10/edit_ilm.png" alt="Modal view to set a lifecycle policy" /></p>
<p><em>You can set a custom period, or pick an Indefinite retention for your data.</em>
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf65643993fb4558/6a7f1ad4b437705f7b4d710e/edit_dsl.png" alt="Modal view to set a custom retention period" /></p>
<p><em>You can also update streams’ lifecycle via the <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-put-streams-name">Upsert stream</a> or the <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-put-streams-name-ingest">Update ingest stream settings</a> Kibana APIs.</em></p>
<h4 id="inheritordeferdifferentstrategiesfordifferentstreamtypes">Inherit or defer: different strategies for different stream types</h4>
<p><strong>Classic streams</strong></p>
<p>For classic streams, you can default to the existing index template’s retention. Retention isn’t managed by Streams in this case, it follows the lifecycle configuration defined in the template just as it normally would.</p>
<p>This option is useful if you’re onboarding existing data streams and want to keep their lifecycle behavior intact while still benefiting from Streams’ visibility and monitoring features.</p>
<p><strong>Wired streams</strong></p>
<p>Wired streams live in a tree structure, and that hierarchy allows an inheritance model.</p>
<p>A child stream can inherit the lifecycle of its nearest ancestor that has a concrete policy (ILM or DSL). This keeps your configuration lean and consistent since you can set a single lifecycle at a higher level in the tree and let Streams automatically apply it to all relevant descendants.</p>
<p>If that ancestor’s lifecycle is later updated, Streams cascades the change down to all children that inherit it, so everything stays in sync.</p>
<p><em>In the figure below, we set a different retention for</em> <strong><em>logs.prod</em></strong> <em>and</em> <strong><em>logs.staging</em></strong> <em>environments. The child partitions of these environments automatically inherit the configuration.</em>
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd19829108995542f/6a7f1ad777b034c80a3ff913/streams_tree.png" alt="A streams tree that shows inheritance" /></p>
<h4 id="howitworksunderthehood">How it works under the hood</h4>
<p>When you apply or update a lifecycle, <strong>Streams</strong> calls Elasticsearch’s <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-data-stream-settings">/_data_stream/_settings</a>. This is a new API we’ve added in 8.19 / 9.1 for this purpose. </p>
<p>This API is key to keeping retention consistent:</p>
<ol>
<li>It applies the lifecycle directly at the data stream level, overriding any configuration from cluster settings or index templates.</li>
<li>It propagates the retention update to all existing backing indices, not just new ones, so retention remains uniform across your historical and future data.</li>
</ol>
<p>By centralizing lifecycle management at the data stream level and applying a consistent configuration across the backing indices, we remove the ambiguity that used to exist between template-level and index-level configurations. You always know which retention policy is actually in effect, and you can see it directly in the UI.</p>
<h3 id="wrappingup">Wrapping Up</h3>
<p>With Streams, retention management becomes clear and consistent. You can visualize ingestion, switch between DSL and ILM, or inherit policies across streams, all without diving into templates or manual index settings.</p>
<p>By unifying retention into a single view, Streams turns lifecycle management into something simple, predictable, and transparent.</p>
<p>Sign up for an Elastic trial at <a href="http://cloud.elastic.co">cloud.elastic.co</a>, and trial Elastic's Serverless offering which will allow you to play with all of the Streams functionality.</p>
<p>Additionally, check out:</p>
<p><em>Read about</em> <a href="https://www.elastic.co/observability-labs/blog/reimagine-observability-elastic-streams"><em>Reimagining streams</em></a></p>
<p><em>Look at the</em> <a href="http://elastic.co/elasticsearch/streams"><em>Streams website</em></a></p>
<p><em>Read the</em> <a href="https://www.elastic.co/docs/solutions/observability/streams/streams"><em>Streams documentation</em></a></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/simplifying-retention-management-with-streams</link>
    <guid isPermaLink="false">simplifying-retention-management-with-streams</guid>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Kevin Lacabane]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0cd69b3a64600cfd/6a7f1adafc63abfe6764d084/article.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 30 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Live logs and prosper: fixing a fundamental flaw in observability]]></title>
    <description><![CDATA[Stop chasing symptoms. Learn how Streams, in Elastic Observability fixes the fundamental flaw in observability, using AI to proactively find the 'why' in your logs for faster resolution.]]></description>
    <content:encoded><![CDATA[<p>SREs are often overwhelmed by dashboards and alerts that show what and where things are broken, but fail to reveal why. This industry-wide focus on visualizing symptoms forces engineers to manually hunt for answers. The crucial "why" is buried in information-rich logs, but their massive volume and unstructured nature has led the industry to throw them aside or treat them like a second-class citizen. As a result, SREs are forced to turn every investigation into a high-stress, time-consuming hunt for clues. We can solve this problem with logs, but unlocking their potential requires us to reimagine how we work with them and improve the overall investigations journey. </p>
<h2 id="observabilitythebrokenpromise">Observability, the broken promise</h2>
<p>To see why the current model fails, let’s look at the all-too-familiar challenge every SRE dreads: knowing a problem exists but needing to spend valuable time just trying to find where to even start the investigation.</p>
<p>Imagine you get a Slack message from the support team: "a few high-value customers are reporting their payments are failing." You have no shortage of alerts, but most are just flagging symptoms. You don’t know where to start. You decide to check the logs to see if there is anything obvious, starting with the systems that have the high CPU alert.</p>
<p>You spend a few minutes searching and <code>grep</code>-ing through terabytes of logs for affected customer IDs, trying to piece together the problem. Nothing. You worry that you aren’t getting all the logs to reveal the problem, so you turn on more logging in the application. Now you’re knee-deep in data, desperately trying to find patterns, errors, or other "hints" that will give you a clue as to the <em>why</em>.</p>
<p>Finally, one of the broader log queries hits on an error code associated with an impacted customer ID. This is the first real clue. You pivot your search to this new error code and after an hour of digging, you finally uncover the error message. You've finally found the <em>why</em>, but it was a stressful, manual hunt that took far too much time and impacted dozens more customers.</p>
<p>This incident perfectly illustrates the broken promise of modern observability: The complete failure of the investigation process. Investigations are a manual, reactive process that SREs are forced into every day. At Elastic, we believe metrics, traces, and logs are all essential, but their roles, and the workflow between them, must be fundamentally re-imagined for effective investigations.</p>
<p>Observability is about having the clearest understanding possible of the <em>what</em>, <em>where</em>, and <em>why</em>. Metrics are essential for understanding the <em>what</em>. They are the heartbeat of your system, powering the dashboards and alerts that tell you when a threshold has been breached, like high CPU utilization or error rates. But they are aggregates; they show the symptom, rarely the root cause. Traces are good at identifying the <em>where</em>. They map the journey of a request through a distributed system, pinpointing the specific microservice or function where latency spikes or an error originates. Yet, their effectiveness hinges on complete and consistent code instrumentation, a constant dependency on development teams that can leave you with critical visibility gaps. Logs tell you the <em>why</em>. They contain all the rich, contextual, and unfiltered truth of an event. If we can more proactively and efficiently extract information from logs, we can greatly improve our overall understanding of our environments.</p>
<h2 id="challengesoflogsinmodernenvironments">Challenges of logs in modern environments</h2>
<p>While logs are in the standard toolbox, they have been neglected. SREs using today’s solutions deal with several major problems:</p>
<ul>
<li><p>First, due to their unstructured nature, it’s very difficult to parse and manage logs so that they’re useful. As a result, many SRE teams spend a lot of time building and maintaining complex pipelines to help manage this process. </p></li>
<li><p>Second, logs can get expensive at high volume, which leads teams to drop them on the floor to control costs, throwing away valuable information in the process. Consequently, when an incident occurs, you waste precious time hunting for the right logs, and manually correlating across services.</p></li>
<li><p>Finally, nobody has built a log solution that proactively works to find the important signals in logs and to surface those critical <em>whys</em> to you when you need them. As a result, log-based investigations are too painful and slow.</p></li>
</ul>
<p>Why are we here? As applications became more complex, log volume became unmanageable. Instead of solving this with automation, the industry took a shortcut: it gave up on getting the most out of logs and prioritized more manageable but less informative signals.</p>
<p>This decision is the origin of the broken, reactive model. It forced observability into a manual loop of 'observing' alerts, rather than building automation that could help us truly understand our systems to improve how we root cause and resolve issues. This has transformed SREs from investigators into full-time data wranglers, wrestling with Grok patterns and fragile ETL scripts instead of solving outages. </p>
<h2 id="introducingstreamstorethinkhowyouuselogsforinvestigations">Introducing Streams to rethink how you use logs for investigations</h2>
<p>Streams is an agentic AI solution that simplifies working with logs to help SRE teams rapidly understand the <em>why</em> behind an issue for faster resolution. The combination of Elasticsearch and AI is turning manual management of noisy logs into automated workflows that identify patterns, context, and meaning, marking a fundamental shift in observability.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a12707c4b143aca/6a7f1a5f1967ea4bc8330b76/streams-manifesto-01.png" alt="Streams" /></p>
<h4 id="logeverythinginanyformat">Log everything in any format</h4>
<p>By applying the Elasticsearch platform for context engineering to bring together retrieval and AI-driven parsing to keep up with schema changes, we are reimagining the entire log pipeline.  </p>
<p>Streams ingests raw logs from all your sources to a single destination. It then uses AI to partition incoming logs into their logical components and parses them to extract relevant fields for an SRE to validate, approve, or modify. Imagine a world where you simply point your logs to a single endpoint, and everything just works. Less wrestling with Grok patterns, configuring processors, and hunting for the right plugin. All of which significantly reduces the complexity. Streams is a big step towards realizing that vision.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt53b07fce2875a685/6a7f1a624c4bfbc20cccd8fe/streams-manifesto-02.png" alt="Streams" /></p>
<p>As a result, SREs are freed from managing complex ingestion pipelines, allowing them to spend less time on data wrangling and more time preventing service disruptions.</p>
<h4 id="solveincidentsfasterwithsignificanteventsnbsp">Solve incidents faster with Significant Events </h4>
<p>Significant Events, a capability within Streams, uses AI to automatically surface major errors and anomalies, enabling you to be proactive in your investigations. So, instead of just combing through endless noise, you can focus on the events that truly matter, such as startup and shutdown messages, out-of-memory errors, internal server failures, and other significant signals of change. These events act as actionable markers, giving SREs early warning and clear focus to begin an investigation before service impact.</p>
<p>With this new foundation, logs will become your primary signal for investigation. The panicked, manual search for a needle in a digital haystack is about to be over. Significant Events acts like a smart metal detector that sifts through the chaos and only beeps when it finds issues, helping you to easily ignore all that hay and find the "needle" faster. </p>
<p>Now imagine the same scenario we started with. Instead of starting a frantic, time-consuming grep through terabytes of logs. Streams has already done the heavy lifting. Its AI-driven analysis has detected a new, anomalous pattern that began before your support team even knew about it and automatically surfaced it as a significant event. Rather than you hunting for a clue, the clue finds you. </p>
<p>With a single click, you have the <em>why</em>: a Java out-of-memory error in a specific service component. This is your starting point. You find the root cause in under two minutes and begin remediation. The customer impact is stopped, the dev team gets the specific error, and the problem is contained before it can escalate. In this case, metrics and traces were unhelpful in finding the <em>why</em>. The answer was waiting in the logs all along.</p>
<p>This ideal outcome is possible because you can both afford to keep every log and instantly find the signal within them. Elastic's cost-efficient architecture with powerful compression, searchable snapshots, and data tiering makes full retention a reality. From there, Streams automatically surfaces the significant event, ensuring that the answer is never lost in the noise.</p>
<p>Elastic is the only company that provides an AI-driven log-first approach to elevate your observability signals and make it dramatically faster and easier to get to <em>why</em>. This is built on our decades of leadership in search, relevance, and powerful analytics that provides the foundation for understanding logs at a deep, semantic level.</p>
<h2 id="thevisionforstreamsnbsp">The vision for Streams </h2>
<p>The partitioning, parsing, and Significant Events you see today is just the starting point. The next step in our vision is to use the Significant Events to automatically generate critical SRE artifacts. Imagine Streams creating intelligent alerts, on-the-fly investigation dashboards, and even data-driven SLOs based <em>only</em> on the events that actually impact service health. From there, the goal is to use AI to drive automated Root Cause Analysis (RCA) directly from log patterns and generate remediation runbooks, turning a multi-hour hunt into an instant resolution recommendation.</p>
<p>Once this AI-drive log foundation is in place, our vision for Streams expands to become a unified intelligence layer that operates across all your telemetry data. It’s not just about making each signal better in isolation, but about understanding the context and relationships between them to solve complex problems. </p>
<p>For metrics, Streams won’t just alert you to a single metric spike but detect a correlated anomaly across multiple, seemingly unrelated metrics e.g. p99 latency for a specific service, rise in garbage collection time, transaction success rate.</p>
<p>Similarly, for traces it identifies a new, unexpected service call (e.g., a new database or an external API) appears in a critical transaction path after a deployment or identifies specific span is suddenly responsible for a majority of errors across all traces, even if the overall error rate hasn't breached a threshold.</p>
<p>The goal is not to have separate streams for logs, metrics, and traces, but to weave them into a single narrative that automatically correlates all three signals. Ultimately, Streams is about fundamentally changing the goal from human led data gathering exercise to proactive, AI-driven resolution.</p>
<p><em>For more on Streams:</em></p>
<p><em>Read the</em> <a href="https://www.elastic.co/observability-labs/blog/elastic-observability-streams-ai-logs-investigations"><em>Streams launch blog</em></a></p>
<p><em>Look at the</em> <a href="http://elastic.co/elasticsearch/streams"><em>Streams website</em></a></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/reimagine-observability-elastic-streams</link>
    <guid isPermaLink="false">reimagine-observability-elastic-streams</guid>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Ken Exner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6615169fc7402c80/6a7f1a65c2cc0973942499b6/streams-manifesto.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 27 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Automating User Journeys for Synthetic Monitoring with MCP in Elastic]]></title>
    <description><![CDATA[This post explores how you can automatically create user journeys with Synthetic Monitoring in Elastic Observability, TypeScript, and FastMCP, and walks through the app and its workflow.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/docs/solutions/observability/synthetics">Synthetic Monitoring in Elastic Observability</a> enables you to track user pathways using a global testing infrastructure, emulating the full user path to measure the impact of web applications. It also provides comprehensive insight into your website's performance, functionality, and availability from development to production, allowing you to identify and resolve issues before they affect your customers. </p>
<p>One of the main components of Elastic's Synthetic Monitoring is the ability to create user journeys, which can be done with or without code. There is a <a href="https://github.com/elastic/synthetics">Synthetics agent,</a>, a CLI tool that guides you through the process of creating both heartbeat monitors and user journeys and deploying your code to Elastic Observability. If you are using code to create user journeys, you are using <a href="https://playwright.dev/">Playwright</a> under the hood with some additional configuration to make it easier to work with Elastic Observability. </p>
<p>To automatically create user journeys using TypeScript, you can create Playwright tests based on a prompt using <a href="https://www.warp.dev">Warp</a>, an AI-assisted terminal, <a href="https://deepmind.google/models/gemini/pro/">Gemini 2.5 Pro</a>, and <a href="https://modelcontextprotocol.io/docs/getting-started/intro">MCP</a>. This application was built using Python and <a href="https://gofastmcp.com/getting-started/welcome">FastMCP</a>, which wraps the synthetic agent to deploy browser tests to Elastic automatically. This blog post will guide you through how the application works, how to use it, and its development process. You can find the complete code on <a href="https://github.com/JessicaGarson/MCP-Elastic-Synthetics">GitHub</a>. </p>
<h2 id="solutionoverview">Solution overview</h2>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt52957c4621a51a56/6a7f0d329090b04d0584ea0f/01-diagram.jpg" alt="diagram" /></p>
<p>Currently, this solution is set up to run inside Warp as an <a href="https://docs.warp.dev/knowledge-and-collaboration/mcp">MCP server</a>; however, you can also use another client, such as <a href="https://claude.ai/download">Claude Desktop</a> or <a href="https://cursormcp.com/en">Cursor</a>. From there, you create a Python script using <a href="https://gofastmcp.com/getting-started/welcome">FastMCP</a>, which allows you to create functions that are callable by an LLM. Within Warp, you can make a configuration file in JSON that enables you to point to your Python script and pass in all the environment variables you are working with. From there, you'll want to toggle agent mode and ask a question about creating synthetic testing or call the MCP function directly. There are many options for which LLM you can select, be sure to check out <a href="https://docs.warp.dev/agents/using-agents">Warp's documentation</a> to learn more about the options available.</p>
<p>After that, you should ask a question about creating synthetic testing or call the MCP function you are looking for. The following three functions can be used: </p>
<ul>
<li><p><code>diagnose_warp_mcp_config</code> 
Used for debugging environment variable issues that may arise. This function likely won't be needed unless there is an issue with your configuration.  </p></li>
<li><p><code>create_and_deploy_browser_test</code>
Will automatically create Playwright tests if given the test name, the URL you want to test, and a schedule. This approach uses a template-based method, rather than a machine learning-based method, and all the tests it outputs will appear similar.   </p></li>
<li><p><code>llm_create_and_deploy_test_from_prompt</code>
Similar to <code>create_and_deploy_browser_test</code>, but the main difference is that it uses an LLM to create tests based on a prompt you give it. The tests should reflect the prompt you provided. To run this function you'll provide a test name, URL, prompt, and schedule.</p></li>
</ul>
<h2 id="whycreatethissolutionasanmcpserver">Why create this solution as an MCP server?</h2>
<p>The reason this was developed as an MCP server, as opposed to just a standalone script or a standard CLI, is that it can be structured and interacted with in a more conversational manner. It enables an LLM to generate dynamic Playwright testing while maintaining consistent arguments, environment variables, and responses to ensure accuracy and reliability. Thus, it becomes a reliable workflow that other agents or developers can compose with additional tools. In other words, the MCP layer turns your LLM-based test authoring into a standardized, reusable capability instead of a one-off script. To learn more about the direction of MCP, be sure to check out our article on the <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">topic.</a></p>
<h2 id="implementationconsiderations">Implementation considerations</h2>
<p>When creating a solution like this one, one thing to be mindful of is your use of tokens. An early version of this solution took approximately twenty minutes to create synthetic tests and ultimately led to severe rate-limiting. </p>
<p>Another issue faced during the building process was striking a balance between creating a template that facilitates the creation of a Playwright script and having an LLM create Playwright scripts based on prompts that didn't feel cookie-cutter. While using a more LLM approach an issue faced was that the scripts often didn't work or were based on parameters that didn't exist and a more templated approach was more reliable but felt repetitive. The final version of this solution attempted to balance this by using elements of the template while adjusting the LLM parameter of temperature, which controls the randomness or creativity of a large language model's output. </p>
<p>While testing this solution, a failing test also emerged that required navigating past a pop-up. In more complex cases, this may serve as a building block that requires additional domain knowledge to create a complete passing Playwright test.</p>
<h2 id="howtogetstarted">How to get started</h2>
<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>The version of Python that is used is Python 3.12.1 but you can use any version of Python higher than 3.10.   </li>
<li>This application uses Elastic Observability version 9.1.2, but you can use any version of Elastics Observability that is higher than 8.10. You can also use <a href="https://www.elastic.co/cloud/serverless">Elastic Cloud Serverless</a> as well.  </li>
<li>You will also need an OpenAI API key to use the LLM capabilities of this application. You will want to configure an environment variable for your OpenAI API Key, which you can find on the API keys page in <a href="https://platform.openai.com/api-keys">OpenAI's developer portal</a>.</li>
</ul>
<h3 id="step1installthepackagesandclonetherepository">Step 1: Install the packages and clone the repository</h3>
<p>In order for this MCP server to run locally you will need to install the the following packages: </p>
<pre><code>pip install fastmcp openai
npm install -g playwright @elastic/synthetics
</code></pre>
<p>You will use <a href="https://gofastmcp.com/getting-started/welcome">FastMCP 2.0</a> to create the MCP server, and <a href="https://github.com/openai/openai-python">OpenAI</a> to generate tests based on prompts that you provide. Additionally, you will want to clone the repository to obtain a local copy of the server.</p>
<h3 id="step2setupaconfigurationfileinwarp">Step 2: Set up a configuration file in Warp</h3>
<p>Inside of Warp, you will want to go to the side panel, where it says MCP servers and where it says “add”. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc67bb0095d239f6f/6a7f0d359090b0390b84ea15/02-add-mcp.jpg" alt="Add MCP Server" /></p>
<p>After that, you will be prompted to add a JSON configuration file that should resemble the following. Be sure to add your own Kibana URL, update the correct path, and include your own keys and tokens.</p>
<pre><code>{
 "elastic-synthetics": {
   "command": "python",
   "args": ["elastic_synthetics_server.py"],
   "env": {
     "PYTHONPATH": ".",
     "ELASTIC_KIBANA_URL": "https://your-kibana-url.elastic-cloud.com",
     "ELASTIC_API_KEY": "your-api-key-here",
     "ELASTIC_PROJECT_ID": "mcp-synthetics-demo",
     "ELASTIC_SPACE": "default",
     "ELASTIC_AUTO_PUSH": "true",
     "ELASTIC_USE_JAVASCRIPT": "false",
     "ELASTIC_INSTALL_DEPENDENCIES": "true",
     "OPENAI_API_KEY": "sk-your-openai-key",
     "LLM_MODEL": "gpt-4o"
   },
   "working_directory": "/path/to/your/file",
   "start_on_launch": true 
   }
}
</code></pre>
<h3 id="step3askaquestionorcallthetoolsdirectly">Step 3: Ask a question or call the tools directly</h3>
<p>Now that you've set up locally, you will want to toggle agent mode and select the LLM you wish to use. The reason why Gemini-Pro-2.5 was chosen for this blog post is that it provides a straightforward answer, while other LLMs selected returned a very lengthy response. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt645bcec459cec042/6a7f0d3833fa8a3c4220272a/03-agent-mode.jpg" alt="Agent mode" /></p>
<p>To start using the MCP tools, from your MCP server, you can ask a question that contains the test name, URL, prompt, and schedule. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt69de803d89d49ee9/6a7f0d3b1967ea6ee8330787/04-full-question-answer.jpg" alt="Full question and answer" /></p>
<p>You can also call the directly by typing <code>llm_create_and_deploy_test_from_prompt()</code> and the program will prompt you for the relevant details:<br />
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt400063dcb9e2ed05/6a7f0d3d33fa8a2ba1202730/05-call-mcp-tool.jpg" alt="Call MCP Tool" /></p>
<p>Inside Kibana, you should see your monitor listed if you click under Applications and select Monitors listed under Synthetics. You can also find a link to your monitor in the response of your MCP tool. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0c8e1e9e79a7ca38/6a7f0d4073d9bd5cca29db4d/06-kibana-monitors.jpg" alt="Monitors in Kibana" /></p>
<h2 id="whatsgoingoninside">What's Going On Inside</h2>
<p>This code sample consists of three primary functions, which are MCP tools that you can call from your MCP client, including <code>diagnose_warp_mcp_config</code>, <code>create_and_deploy_browser_test</code> and <code>llm_create_and_deploy_test_from_prompt</code>.</p>
<h3 id="debuggingenvironmentissues">Debugging environment issues</h3>
<p>There were various issues that came up while creating this application around environment variable loading, so there was a need to create an MCP that could be called depending on errors that may be present. </p>
<p>The tool <code>diagnose_warp_mcp_config</code> kicks off with a decorator <code>@mcp.tool()</code> which allows it to be called and listed in the list of available tools. This tool is designed to help debug issues with Elastic-specific environment variables for troubleshooting purposes. First, it loads in the environment variables and looks for the Elastic specific variables, after it does some security masking so it doesn't show any variables and hides sensitive information like API keys in the output, showing only the first eight characters followed by "…". This tool determines if the minimum required credentials (Kibana URL and API Key) are present to proceed with deployment and provides a report letting you know to address any issues that may exist. </p>
<pre><code>@mcp.tool()
def diagnose_warp_mcp_config() -&gt; Dict[str, Any]:
   """Diagnose Warp MCP environment configuration for Elastic Synthetics"""
   try:
       env_vars = load_env_from_warp_mcp()

       # Check for required variables
       kibana_url = env_vars.get('ELASTIC_KIBANA_URL') or env_vars.get('KIBANA_URL')
       api_key = env_vars.get('ELASTIC_API_KEY') or env_vars.get('API_KEY')
       project_id = env_vars.get('ELASTIC_PROJECT_ID') or env_vars.get('PROJECT_ID')
       space = env_vars.get('ELASTIC_SPACE') or env_vars.get('SPACE', 'default')

       # Mask sensitive values for display
       masked_vars = {}
       for key, value in env_vars.items():
           if 'API_KEY' in key or 'TOKEN' in key:
               masked_vars[key] = f"{value[:8]}..." if value and len(value) &gt; 8 else "***"
           else:
               masked_vars[key] = value

       deployment_ready = bool(kibana_url and api_key)

       return safe_json_response({
           "status": "success",
           "environment_variables": masked_vars,
           "required_check": {
               "kibana_url": bool(kibana_url),
               "api_key": bool(api_key),
               "project_id": bool(project_id),
               "space": bool(space)
           },
           "deployment_ready": deployment_ready,
           "recommendations": [
               "Environment variables detected" if env_vars else "No environment variables found",
               "Kibana URL configured" if kibana_url else "Missing ELASTIC_KIBANA_URL or KIBANA_URL",
               "API Key configured" if api_key else "Missing ELASTIC_API_KEY or API_KEY",
               "Ready for deployment" if deployment_ready else "Missing required credentials"
           ]
       })

   except Exception as e:
       return safe_json_response({
           "status": "error",
           "error": str(e),
           "error_type": type(e).__name__
       })
</code></pre>
<h3 id="creatingsynthetictestsbasedonatemplate">Creating synthetic tests based on a template</h3>
<p>While developing this solution to generate tests based on a prompt, the process wasn't always smooth. Early versions encountered issues with accuracy, hallucinations, and the creation of loops. To make progress, a version that relied on creating a test template to verify the mechanics of the solution, such as whether the test could pass and be deployed to Elastic correctly, was a logical next step. </p>
<p>This solution automates the entire process of creating a synthetic browser test that will regularly check if a website is working correctly, then deploys it to Elastic Observability Synthetics. Similar to <code>diagnose_warp_mcp_config</code>, the MCP tool <code>create_and_deploy_browser_test</code> starts with the decorator <code>@mcp.tool()</code> and checks to make sure that the proper environment variables are loaded. </p>
<p>From there, it creates a TypeScript test file that is based on templates and generates dynamic test steps based on the target website's characteristics, including navigating to the website, verifying the page title exists, checking page load performance, taking a screenshot, verifying page content is visible, and finally saves the test file in a <code>synthetic_tests</code> directory.</p>
<p>Finally, it wraps Elastic's CLI tool <code>@elastic/synthetics</code> to push the test to Kibana, allowing you to set which geographic locations to run tests from, how often to run the test, and the project and workspace settings.</p>
<p>You check out the full code for this MCP tool <a href="https://github.com/JessicaGarson/MCP-Elastic-Synthetics/blob/main/elastic_synthetics_server.py#L943">here.</a></p>
<h3 id="creatingsynthetictestsbasedonaprompt">Creating synthetic tests based on a prompt</h3>
<p>While creating browser tests based on a templated approach is a good starting point, it felt generic and cookie-cutter. But it made a helpful structure to build an LLM-based function on top of.</p>
<p>The MCP tool <code>llm_create_and_deploy_test_from_prompt</code> begins by ensuring that basic parameters, including locations, schedule, and directories, are listed. Additionally, it aims to learn more about the target website to inform the AI and initialize the OpenAI client and model, which is GPT-4o. </p>
<p>After setting up the LLM, it converts natural language requests into actual Playwright test code, then cleans and validates the AI-generated code to prevent issues like injection attacks or malformed syntax. It draws inspiration from the templated approach, wrapping AI-generated steps within a proven, reliable test framework template. Finally, it deploys the test to Elastic in a similar manner to the previous tool. </p>
<p>You can find the code for this tool <a href="https://github.com/JessicaGarson/MCP-Elastic-Synthetics/blob/main/elastic_synthetics_server.py#L1559">here</a>.</p>
<h2 id="conclusionandnextsteps">Conclusion and next steps</h2>
<p>Synthetic monitoring in Elastic Observability makes it easy to test complete user journeys and keep your site reliable, with simple setup and a Playwright integration. A tool like this can provide a starting point for tests that you can iterate on after.</p>
<p>A solution like this is just the start of an MCP implementation that automatically generates Playwright tests for you and can be expanded in the future to include heartbeat monitors, utilize the <a href="https://github.com/microsoft/playwright-mcp">Playwright MCP server</a>, or consider experimenting with <a href="https://www.anthropic.com/news/claude-for-chrome">Claude for Chrome</a> to create synthetic testing.  </p>
<p>Check out more articles on <a href="https://www.elastic.co/observability-labs/blog/category/infrastructure-monitoring">Observability Labs on Infrastructure Monitoring</a></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/mcp-elastic-synthetics</link>
    <guid isPermaLink="false">mcp-elastic-synthetics</guid>
    <category><![CDATA[Incident Management]]></category>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Jessica Garson]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f7fbdc61045d078/6a7f0d43fc63ab4f3364cc71/retro.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 17 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Transforming Industries and the Critical Role of LLM Observability: How to use Elastic's LLM integrations in real-world scenarios]]></title>
    <description><![CDATA[This blog explores four industry specific use cases that use Large Language Models (LLMs) and highlights how Elastic's LLM observability integrations provide insights into the cost, performance, reliability and the prompts and response exchange with the LLM.]]></description>
    <content:encoded><![CDATA[<p>In today's tech-centric world, Large Language Models (LLMs) are transforming sectors from finance and healthcare to research. LLMs are starting to underpin products and services across the spectrum. Take for example recent <a href="https://blog.google/technology/google-deepmind/gemini-model-thinking-updates-march-2025/#advanced-coding">advanced coding</a> developments in Google's Gemini 2.5 which enable it to use its reasoning capabilities to create a video game by producing the executable code from a short prompt.  Or <a href="https://www.aboutamazon.com/news/devices/new-alexa-generative-artificial-intelligence">new ways</a> to interact with Amazon's Alexa - for example, you could send a picture of a live music schedule, and have Alexa add the details to your calendar. And let's not forget Microsoft's <a href="https://blogs.microsoft.com/blog/2025/04/04/your-ai-companion/">personalization of Copilot</a> which remembers what you talk about, so it learns your likes and dislikes and details about your life; the name of your dog, that tricky project at work, what keeps you motivated to stick to your new workout routine. </p>
<p>Despite their widespread utility of LLMs, deploying these sophisticated tools in real-world scenarios poses distinct challenges, especially in managing their complex behaviors. For users such as Site Reliability Engineers (SREs), DevOps teams, and AI/ML engineers, ensuring reliability, performance, and compliance of these models introduces an additional  layer of complexity. This is where the concept of LLM Observability becomes essential. It offers crucial insights into the performance of these models, ensuring that these advanced AI systems operate both effectively and ethically.</p>
<h3 id="whyllmobservabilitymattersandhowelasticmakesiteasy">Why LLM Observability Matters and How Elastic Makes It Easy</h3>
<p>LLMs are not just another piece of software; they are sophisticated systems capable of human-like capabilities such as text generation, comprehension, and even coding. But with great power comes greater need for oversight. The opaque nature of these models can obscure how decisions are made and content generated. This makes it even more critical to implement robust observability to monitor and troubleshoot issues such as hallucinations, inappropriate content, cost overruns, errors and performance degradation. By monitoring these models closely, we can safeguard against unexpected outcomes and maintain user trust.</p>
<h3 id="realworldscenarios">Real-World Scenarios</h3>
<p>Let's explore real-world scenarios where companies leverage LLM-powered applications to enhance productivity and user experience, and how Elastic's LLM observability solutions monitor critical aspects of these models.</p>
<h4 id="1generativeaiforcustomersupport">1. Generative AI for Customer Support</h4>
<p>Companies are increasingly leveraging LLMs and generative AI to enhance customer support, using platforms like Google Vertex AI for hosting these models efficiently. With the introduction of advanced AI models such as Google's Gemini, which is integrated into Vertex AI, businesses can deploy sophisticated chatbots that manage customer inquiries, from basic questions to complex issues, in real time. These AI systems understand and respond with natural language, offering instant support for issues such as product troubleshooting or managing orders thus 
reducing wait times. They also learn from each interaction to improve accuracy continuously. This boosts customer satisfaction and allows human agents to focus on complex tasks, enhancing overall efficiency. Other ways that AI tools can further empower customer care agents is with real-time analytics, sentiment detection, and conversation summarization. </p>
<p>To support use cases like the AI-powered customer support described above, Elastic recently launched LLM observability integrations including support for <a href="https://www.elastic.co/guide/en/integrations/current/gcp_vertexai.html">LLMs hosted on GCP Vertex AI</a>. Customers who wish to monitor foundation models such as Gemini and Imagen hosted on Google Vertex AI can benefit from Elastic’s Vertex AI integration to get a deeper understanding of model behavior and performance, and ensure that the AI-driven tools are not only effective but also reliable. Customers get out-of-the-box experience ingesting a curated set of metrics from Vertex AI as well as a pre-configured dashboard.</p>
<p>By continuously tracking these metrics, customers can proactively manage their AI resources, optimize operations, and ultimately enhance the overall customer experience.</p>
<p>Let's look at some of the metrics you get from the Google Vertex AI integration which are helpful in the context of using generative AI for customer support.</p>
<ol>
<li><strong>Prediction Latency</strong>: Measures the time taken to complete predictions, critical for real-time customer interactions.</li>
<li><strong>Error Rate</strong>: Tracks errors in predictions, which is vital for maintaining the accuracy and reliability of AI-driven customer support.</li>
<li><strong>Prediction Count</strong>: Counts the number of predictions made, helping assess the scale of AI usage in customer interactions.</li>
<li><strong>Model Usage</strong>: Tracks how frequently the AI models are accessed by both virtual assistants and customer support tools.</li>
<li><strong>Total Invocations</strong>: Measures the total number of times the AI services are used, providing insights into user engagement and dependency on these tools.</li>
<li><strong>CPU and Memory Utilization</strong>: By observing CPU and memory usage, users can optimize resource allocation, ensuring that the AI tools are running efficiently without overloading the system.</li>
</ol>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta496ae3417800a11/6a7f1ba7eab5be0c7520ab1a/vertex-overview.png" alt="Vertex Overview" /></p>
<p>To learn more about how Elastic's Google Vertex AI integration can augment your LLM observability, have a quick read of this <a href="https://www.elastic.co/observability-labs/blog/elevate-llm-observability-with-gcp-vertex-ai-integration">blog</a>.</p>
<h4 id="2transforminghealthcarewithgenerativeai">2. Transforming Healthcare with Generative AI</h4>
<p>The healthcare industry is embracing generative AI to enhance patient interactions and streamline operational workflows. By leveraging platforms like Amazon Bedrock, healthcare organizations deploy advanced large language models (LLMs) to power tools that convert doctor-patient conversations into structured medical notes, reducing administrative overhead and allowing clinicians to prioritize diagnosis and treatment. These AI-driven solutions provide real-time insights, enabling informed decision-making and improving patient outcomes. Additionally, patient-facing applications powered by LLMs offer secure access to health records, empowering individuals to manage their care proactively. </p>
<p>Robust observability is essential to maintain the reliability and performance of these generative AI applications in healthcare. Elastic’s <a href="https://www.elastic.co/guide/en/integrations/current/aws_bedrock.html">Amazon Bedrock integration</a> equips providers with tools to monitor LLM behavior, capturing critical metrics like invocation latency, error rates, token usage and guardrail invocation. Pre-configured dashboards provide visibility into prompt and completion text, enabling teams to verify the accuracy of AI-generated outputs, such as medical notes, and detect issues like hallucinations. </p>
<p>Additionally, customers who configure Guardrails for Amazon Bedrock to filter harmful content like hate speech, personal insults, and other inappropriate topics, can use the Bedrock Integration to observe the prompts and responses that caused the guardrail to filter them out. This helps application developers take proactive actions to maintain a safe and positive user experience.</p>
<p>Some of the logs and metrics that can be helpful for customers using LLMs hosted on Amazon Bedrock are the following</p>
<ol>
<li><strong>Invocation Details</strong>: This Integration records the Invocation latency, count, throttles. These metrics are critical for ensuring that generative AI models respond quickly and accurately to patient queries or appointment scheduling tasks, maintaining a seamless user experience.</li>
<li><strong>Error Rates</strong>:  Tracking error rates ensures that AI tools, such as patient query assistants or appointment systems, consistently deliver accurate and reliable results. By identifying and addressing issues early, healthcare providers can maintain trust in AI systems and prevent disruptions in critical patient interactions.</li>
<li><strong>Token Usage</strong>: In healthcare, tracking token usage helps identify resource-intensive queries, such as detailed patient record summaries or complex symptom analyses, ensuring efficient model operation. By monitoring token usage, healthcare providers can optimize costs for AI-powered tools while maintaining scalability to handle growing patient interactions.</li>
<li><strong>Prompt and Completion Text</strong>: Capturing prompt and completion text allows healthcare providers to analyze how AI models respond to specific patient queries or administrative tasks, ensuring meaningful and contextually accurate interactions. This insight helps refine prompts to improve the AI's understanding and ensures that generated responses, such as appointment details or treatment explanations, meet the quality standards expected in healthcare.</li>
<li><strong>Prompt and response where guardrails intervened</strong>: Being able to track requests and responses that were deemed inappropriate by guardrails helps healthcare providers monitor what information patients are asking for. With this information users can make continuous adjustments to the LLMs to ensure appropriate responses, balancing flexibility and rich communication on the one hand, and on the other, privacy protection, hallucination prevention, and harmful content filtering. </li>
</ol>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta8ce07121048b7cc/6a7f1baa2f00b22117efef3d/aws-bedrock-overview.png" alt="Bedrock Overview" /></p>
<p>Amazon Bedrock Gaurdrails OOTB dashboard
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt843efe77fb38f137/6a7f1bad42a117cf9695c33b/amazon-bedrock-gaurdrails.png" alt="Bedrock Gaurdrails Overview" /></p>
<p>To learn about the Amazon Bedrock Integration, read this <a href="https://www.elastic.co/observability-labs/blog/llm-observability-aws-bedrock">blog</a>. To dive deeper into how the integration can help with observability of Guardrails for Amazon Bedrock, take a look at this <a href="https://www.elastic.co/observability-labs/blog/llm-observability-amazon-bedrock-guardrails">blog</a>.</p>
<h4 id="3enhancingtelcoefficiencywithgenai">3.  Enhancing Telco Efficiency with GenAI</h4>
<p>The telecommunication industry can leverage services like Azure OpenAI to transform customer interactions, optimize operations, and enhance service delivery. By integrating advanced generative AI models, telcos can offer highly personalized and responsive customer experiences across multiple channels. AI-powered virtual assistants streamline customer support by automating routine queries and providing accurate, context-aware responses, reducing the workload on human agents and enabling them to focus on complex issues while improving efficiency and satisfaction. Additionally, AI-driven insights help telcos understand customer preferences, anticipate needs, and deliver tailored offerings that boost customer loyalty. Operationally, LLMs such as Azure OpenAI enhance internal processes by enabling smarter knowledge management and faster access to critical information.</p>
<p>Elastic's LLM observability integrations like the <a href="https://www.elastic.co/guide/en/integrations/current/azure_openai.html">Azure OpenAI integration</a> can provide visibility into AI performance and costs, empowering telecom providers to make data-driven decisions and enhance customer engagement. It can help optimize resource allocation by analyzing call patterns, predicting service demands, and identifying trends, enabling telcos to scale their AI operations efficiently while maintaining high service quality.</p>
<p>Some of the key metrics and logs that Azure OpenAI that can provide insights are:</p>
<ol>
<li><strong>Error Counts</strong>: It provides critical insights into failed requests and incomplete transactions, enabling telecom providers to proactively identify and resolve issues in AI-powered applications. </li>
<li><strong>Prompt Input and Completion Text</strong>: This captures the input queries provided to AI systems and the corresponding AI-generated outputs. These fields allow telecom providers to analyze customer queries, monitor response quality, and refine AI training datasets to improve relevance and accuracy.</li>
<li><strong>Response Latency</strong>: It measures the time taken by AI models to generate responses, ensuring that virtual assistants and automated systems deliver quick and efficient replies to customer queries. </li>
<li><strong>Token Usage</strong>: It tracks the number of input and output tokens processed by the AI model, offering insights into resource consumption and cost efficiency. This data helps telecom providers monitor AI usage patterns, optimize configurations, and scale resources effectively</li>
<li><strong>Content Filter Results</strong>: In Azure OpenAI, this plays a crucial role in handling sensitive inputs provided by customers, ensuring compliance, safety, and responsible AI usage. This feature identifies and flags potentially inappropriate or harmful queries and responses in real time, enabling telecom providers to address sensitive topics with care and accuracy. </li>
</ol>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7977b3e3b8a8f599/6a7f1bb02f00b220bcefef41/azure-openai-overview.png" alt="Azureopenai Overview" /></p>
<p>The Azure OpenAI content filtering OOTB dashboard
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3596d81c2cb554ab/6a7f1bb3eab5be7e6f20ab22/azure-openai-contentfiltering.png" alt="Azureopenai Overview1" /></p>
<p>You can learn more about Elastic's Azure OpenAI integration from these two blogs - <a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai">Part 1</a> and <a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai-v2">Part 2</a>. </p>
<h4 id="4openaiintegrationforgenerativeaiapplications">4. OpenAI Integration for Generative AI Applications</h4>
<p>As AI-powered solutions become integral to modern workflows, OpenAI's sophisticated models, including language models like GPT-4o and GPT-3.5 Turbo, image generation models like DALL·E, and audio processing models like Whisper, drive innovation across applications such as virtual assistants, content creation, and speech-to-text systems. With growing complexity and scale, ensuring these models perform reliably, remain cost-efficient, and adhere to ethical guidelines is paramount. Elastic's <a href="https://www.elastic.co/docs/reference/integrations/openai">OpenAI integration</a> provides a robust solution, offering deep visibility into model behaviour to support seamless and responsible AI deployments.</p>
<p>By tapping into the OpenAI Usage API, Elastic's integration delivers actionable insights through intuitive, pre-configured dashboards, enabling Site Reliability Engineers (SREs) and DevOps teams to monitor performance and optimize resource usage across OpenAI's diverse model portfolio. This unified observability approach empowers organizations to track critical metrics, identify inefficiencies, and maintain high-quality AI-driven experiences. The following key metrics from Elastic's OpenAI integration help organizations achieve effective oversight:</p>
<ol>
<li><strong>Request Latency</strong>: Measures the time taken for OpenAI models to process requests, ensuring responsive performance for real-time applications like chatbots or transcription services.</li>
<li><strong>Invocation Rates</strong>: Tracks the frequency of API calls across models, providing insights into usage patterns and helping identify high-demand workloads.</li>
<li><strong>Token Usage</strong>: Monitors input and output tokens (e.g., prompt, completion, cached tokens) to optimize costs and fine-tune prompts for efficient resource consumption.</li>
<li><strong>Error Counts</strong>: Captures failed requests or incomplete transactions, enabling proactive issue resolution to maintain application reliability.</li>
<li><strong>Image Generation Metrics</strong>: Tracks invocation rates and output dimensions for models like DALL·E, helping assess costs and usage trends in image-based applications.</li>
<li><strong>Audio Transcription Metrics</strong>: Monitors invocation rates and transcribed seconds for audio models like Whisper, supporting cost optimization in speech-to-text workflows.</li>
</ol>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdc7aefa2a0288162/6a7f1bb7e88c65799d00bb24/openai-overview.png" alt="Openai Overview" /></p>
<p>To learn more about Elastic's OpenAI integration, read this <a href="https://www.elastic.co/observability-labs/blog/llm-observability-openai">blog</a>. </p>
<h4 id="actionablellmobservability">Actionable LLM Observability</h4>
<p>Elastic's LLM observability integrations empower users to take proactive control of their AI operations through actionable insights and real-time alerts. For instance, by setting a predefined threshold for token count, Elastic can trigger automated alerts when usage exceeds this limit, notifying Site Reliability Engineers (SREs) or DevOps teams via email, Slack, or other preferred channels. This ensures prompt awareness of potential cost overruns or resource-intensive queries, enabling teams to adjust model configurations or scale resources swiftly to maintain operational efficiency.</p>
<p>In the example below, the rule is set to alert the user if token_count crosses a threshold of 500.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd2a687e02fd719b2/6a7f1bb977b034ede23ff921/slo-1.png" alt="SLO Overview" /></p>
<p>The alert is triggered when the token count exceeds the threshold as seen below
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd811b02131cb8245/6a7f1bbdea068d84cdf0a2e7/slo-2.png" alt="SLO Overview1" /></p>
<p>Another example is tracking invocation spikes, such as when the number of predictions or API calls surpasses a defined Service Level Objective (SLO). For example, if a Bedrock AI-hosted model experiences a sudden surge in invocations due to increased customer interactions, Elastic can alert teams to investigate potential anomalies or scale infrastructure accordingly. These proactive measures help maintain the reliability and cost-effectiveness of LLM-powered applications.</p>
<p>By providing pre-configured dashboards and customizable alerts, Elastic ensures that organizations can respond to critical events in real time, keeping their AI systems aligned with cost and performance goals as well as standards for content safety and reliability.</p>
<h4 id="conclusion">Conclusion</h4>
<p>LLMs are transforming industries, but their complexity requires effective oversight observability to ensure their reliability and safe use. Elastic's LLM observability integrations provide a comprehensive solution, empowering businesses to monitor performance, manage resources, and address challenges like hallucinations and content safety. As LLMs become increasingly integral to various sectors, robust observability tools like those offered by Elastic ensure that these AI-driven innovations remain dependable, cost-effective, and aligned with ethical and safety standards.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/transforming-industries-and-the-critical-role-of-llm-observability</link>
    <guid isPermaLink="false">transforming-industries-and-the-critical-role-of-llm-observability</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <dc:creator><![CDATA[Ishleen Kaur,Daniela Tzvetkova]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb8d1632fb8fe0cd7/6a7f1bc0bd21987c6a7584cd/llmobs2.png" length="0" type="image/png"/>
    <pubDate>Thu, 08 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[End to end LLM observability with Elastic: seeing into the opaque world of generative AI applications]]></title>
    <description><![CDATA[Elastic’s LLM Observability delivers end-to-end visibility into the performance, reliability, cost, and compliance of LLMs across Amazon Bedrock, Azure OpenAI, Google Vertex AI, and OpenAI, empowering SREs to optimize and troubleshoot AI-powered applications.]]></description>
    <content:encoded><![CDATA[<p>In the ever-evolving landscape of artificial intelligence, Large Language Models (LLMs) stand as beacons of innovation, offering unprecedented capabilities across industries. From generating human-like text and translating languages to providing personalized customer interactions, the possibilities with LLMs are vast and increasingly indispensable. Enterprises are deploying these models for everything, from automating customer support systems to enhancing creative writing processes. Imagine a virtual assistant not only answering questions but also drafting business proposals or a customer service bot that understands and responds with empathy—all powered by LLMs. However, with great power comes the need for great oversight.</p>
<p>Despite the transformative potential, LLMs introduce complex challenges that necessitate a new level of observability as LLMs are notoriously opaque. Enter LLM observability: a crucial component in the lifecycle management of LLMs. This aspect becomes vital for Service Reliability Engineers (SREs) and other key stakeholders tasked with ensuring seamless, error-free operations, cost control, and minimizing the risks associated with the unpredictable nature of LLM generated responses. SREs need insights into performance metrics, error frequencies, latency issues, the cost implications of running these sophisticated models, and the prompt and response exchange with the model. Traditional monitoring tools fall short in this high-stakes environment; what’s needed is a nuanced approach to address the unique observability demands that LLMs introduce.</p>
<h3 id="elasticsllmobservabilitycapabilitiesaddressthesechallenges">Elastic's LLM Observability Capabilities Address These Challenges</h3>
<p>With Elastic’s end-to-end LLM observability you can cover a wide range of use cases. To achieve this, you can onboard two types of integrations - API-based logs and metrics and via APM instrumentation. Depending on your use case, you can also choose to use of the LLM integrations.</p>
<ol>
<li><p><strong>High level overview</strong>: via API-based logs and metrics. Monitoring LLM services from providers by ingesting a curated set of service metrics and logs like latency, invocation frequency, tokens, errors, and prompts and responses. Each LLM integration comes with out-of-the-box dashboards.</p></li>
<li><p><strong>Troubleshooting applications</strong>: via APM instrumentation. Fully OTel-native tracing and auto-instrumentation for LLM-based applications through Elastic Distributions of OpenTelemetry (EDOT). Additionally, you can use third party libraries (Langtrace, OpenLit, OpenLLMetry) together with Elastic to extend the coverage to additional LLM-related technologies. </p></li>
</ol>
<h4 id="highleveloverviewllmobservabilityforleadingproviders">High level overview: LLM Observability for Leading Providers</h4>
<p>Elastic offers tailored API-based integrations for four major LLM hosting providers:</p>
<ul>
<li><p>Azure OpenAI</p></li>
<li><p>OpenAI</p></li>
<li><p>Amazon Bedrock</p></li>
<li><p>Google Vertex AI</p></li>
</ul>
<p>These integrations bring a curated set of logs and metrics collection tailored to each provider. What this means for SREs is straightforward access to pre-configured dashboards that highlight the prompts and responses, usage patterns, performance metrics, and cost details across different models and providers.</p>
<p>For instance, SREs keen on identifying which LLM generates the most errors or insights about the models in terms of latency, cost, or usage frequency can leverage these integrations. Imagine having the capability to instantly visualize which LLM is slowing down processes or incurring high costs, thus enabling data-driven decisions to optimize operations.</p>
<h4 id="troubleshootingapplicationstracingandautoinstrumentationofopenaiamazonbedrockandgooglevertexaimodels">Troubleshooting applications: Tracing and Auto-Instrumentation of OpenAI, Amazon Bedrock and Google Vertex AI models</h4>
<p>Elastic supports OTLP tracing capabilities in EDOT for applications using OpenAI models and models hosted on Amazon Bedrock and Google Vertex AI. In addition, Elastic also supports LLM tracing from third party libraries (Langtrace, OpenLIT, OpenLLMetry). </p>
<p>Tracing offers a comprehensive map of an application's request flow, pinpointing granular details about each call within the system. For each transaction and span of a request, tracing shows critical information such as specific models utilized, request duration, errors encountered, tokens used per request, and the prompts and responses between the LLM.</p>
<p>Tracing helps SREs troubleshoot performance issues with applications developed in languages like Python, Node.js and Java." If an SRE needs to investigate latency or error issues, LLM tracing provides a zoomed-in view into the request lifecycle and allows for profound insights into whether a delay is application-specific, model-specific or systemic across deployments.</p>
<h3 id="usecasesbringingelasticsobservabilityfeaturestolife">Use Cases: Bringing Elastic's Observability Features to Life</h3>
<p>Let’s explore some practical scenarios where Elastic’s observability tools shine:</p>
<h4 id="1understandingllmperformanceandreliability">1. Understanding LLM Performance and Reliability</h4>
<p>An SRE team looking to optimize a customer support system powered by Azure OpenAI can utilize Elastic’s <a href="https://www.elastic.co/guide/en/integrations/current/azure_openai.html">Azure OpenAI integration</a> to quickly ascertain which model variants incur higher latency or error rates. This enhances decision-making regarding model deployment or even switching providers based on performance metrics.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba6dd852a703d452/6a7f0cc0fc63ab0f2b64cc37/Azure-OpenAI.png" alt="Azure OpenAI" /></p>
<p>Similarly SREs can also use in parallel integrations for <a href="https://www.elastic.co/guide/en/integrations/current/gcp_vertexai.html">Google Vertex AI</a>, <a href="https://www.elastic.co/guide/en/integrations/current/aws_bedrock.html">Amazon Bedrock</a>, and <a href="https://www.elastic.co/guide/en/integrations/current/openai.html">OpenAI</a> for other applications using models hosted on these providers.</p>
<h4 id="2troubleshootingopenaipoweredapplications">2. Troubleshooting OpenAI-Powered Applications</h4>
<p>Consider an enterprise utilizing an OpenAI model for real-time user interactions. Encountering unexplained delays, an SRE can use OpenAI tracing to dissect the transaction pathway, identifying if one specific API call or model invocation is the bottleneck. The SRE can also check the out-of-the-box OpenAI integration dashboard to verify if the latency is only affecting this application or all model invocations across the organization.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1a8db67903037838/6a7f0cc363e9595fb873ddda/OpenAI-tracing.png" alt="OpenAI Tracing" /></p>
<p>An engineer troubleshooting the LLM-based application can also check to see what were the prompt and response exchanges with the LLM during this request so they can rule out possible impact on performance due to the input. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf636f72199ddf561/6a7f0cc5e02fac383b5d6576/OpenAI-trace.png" alt="OpenAI Trace sample with logs " /></p>
<h4 id="3addressingcostandusageconcerns">3. Addressing Cost and Usage Concerns</h4>
<p>SREs are generally acutely aware of which LLM configurations are less cost-effective than required. Elastic’s integration dashboards, pre-configured to display model usage patterns, help mitigate unnecessary spending effectively. You can find out-of-the box dashboards for Azure OpenAI, OpenAI, Amazon Bedrock, and Google VertexAI models. These dashboards show key cost and usage information such as total invocations and tokens, as well as time series breakdown by model and endpoint. In addition, some integrations show more advanced usage information such as provisioned throughput units (PTU) as well as billing cost.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte81a390cd24036bd/6a7f0cc83cab1c66e30e4868/GCP-Vertex-AI.png" alt="GCP Vertex AI" /></p>
<h4 id="4understandingllmcompliancenbsp">4. Understanding LLM Compliance </h4>
<p>With the Elastic Amazon Bedrock integration for Guardrails, and Azure OpenAI integration for content filtering, SREs can swiftly address security concerns, like verifying if certain user interactions prompt policy violations. Elastic's observability logs clarify whether guardrails rightly blocked potentially harmful responses, bolstering compliance assurance.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd27317f296118f10/6a7f0ccbfc63ab8c1964cc3f/Bedrock-Guardrails.png" alt="Bedrock-Guardrails.png" /></p>
<h3 id="conclusion">Conclusion</h3>
<p>As LLMs continue to revolutionize the capabilities of modern applications, the role of observability becomes increasingly paramount. Elastic’s comprehensive observability framework empowers enterprises to harness the full potential of LLMs while maintaining robust operational insight and control. The integration with prominent LLM hosting providers and advanced tracing for OpenAI, Amazon Bedrock and Google Vertex AI models, equips SREs with the necessary arsenal to navigate the complex landscape of LLM-driven applications, ensuring they remain safe, reliable, efficient, and cost-effective.</p>
<p>In this new era of AI, balancing innovation with observability isn't just beneficial—it's essential. Whether optimizing performance, troubleshooting intricacies, or managing costs and compliance, Elastic stands at the forefront, ensuring your LLM journey is as seamless as it is groundbreaking.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/llm-observability-elastic</link>
    <guid isPermaLink="false">llm-observability-elastic</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <dc:creator><![CDATA[Daniela Tzvetkova,Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4a75b88b6d752066/6a7f0cceeab5bec2c720a6d7/llm-e2e.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 02 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[2025 observability trends: Maturing beyond the hype]]></title>
    <description><![CDATA[Discover what 500+ decision-makers revealed about OpenTelemetry adoption, GenAI integration, and LLM monitoring—insights that separate innovators from followers in Elastic's 2025 observability survey.]]></description>
    <content:encoded><![CDATA[<p>Our latest survey of over 500 observability decision-makers reveals how dramatically the landscape has evolved as we move through 2025. What strikes me most is how observability has moved beyond its technical roots to become a true business imperative. Let’s dive into what we're seeing in the industry.</p>
<h2 id="theinvestmentparadoxofobservabilityin2025">The investment paradox of observability in 2025</h2>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcd28ab8962baff2e/6a7f0a4dbd2198132e757fb9/image5.png" alt="" /></p>
<p>Here's something fascinating: 96% of executives in our survey expect observability to remain a key investment area. Yet almost all of them (97%) are hitting roadblocks in realizing full value. And surprisingly, the primary hurdles for observability are not technical or complicated in nature, can you guess what they might be?</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt01eaab94507227dc/6a7f0a50bdcff03a43c42d0b/image10.png" alt="" /></p>
<p>For 2025, IT leaders are challenged with financial hurdles for their observability. I'm seeing this tension play out constantly in conversations with leaders - they know they need to invest, but they're grappling with budget constraints, licensing costs, and proving ROI for their organizations. This creates an interesting dynamic where organizations must carefully balance increasing investment with rigorous cost optimization and business metrics.</p>
<p>What's particularly interesting is how this paradox is forcing organizations to become more strategic about their investments. Leaders are no longer just throwing money at the problem - they're thinking carefully about how to maximize value from every dollar spent.</p>
<h2 id="whyobservabilitymaturityismakingallthedifference">Why observability maturity is making all the difference</h2>
<p>The data really jumps out at me here. The gap between observability experts and newcomers tells a compelling story that I wasn't expecting to see. Expert organizations are significantly outperforming their peers across every key metric:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt05166add0381eda7/6a7f0a543ce8e231bacf52b5/image9.png" alt="" /></p>
<ul>
<li>91% of expert organizations are deploying applications and infrastructure faster (compared to just 34% of those in early stages)</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt22f788515e7afd45/6a7f0a57ead8ecd41cbaa75d/image11.png" alt="" /></p>
<ul>
<li>82% are successfully reducing operational costs (versus 56% of early-stage organizations)</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt35ca13bf87e472be/6a7f0a5aea068d31caf09d63/image4.png" alt="" /></p>
<ul>
<li>71% achieve better MTTR for incidents (while only 40% of early-stage organizations do)</li>
</ul>
<p>What I find particularly fascinating is how some benefits go beyond just maturity levels. About 80% of organizations report better customer issue response times regardless of their maturity stage. It tells me that even basic observability delivers immediate customer-facing value. This is crucial information for organizations just starting their observability journey - they can expect to see tangible benefits right from the start. But the overarching story may be that observability maturity leads teams from reactive to proactive and allows them to focus on higher level, value-add activities.</p>
<h2 id="costmanagementthenewimperative">Cost management: the new imperative</h2>
<p>The numbers around cost management paint a clear picture of where the industry is heading - 97% of IT decision-makers are actively managing observability costs, and 86% feel personally responsible for business outcomes.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt47754196fbd6a537/6a7f0a5d33fa8a2ff82025c2/image2.png" alt="" /></p>
<p>I'm seeing a clear trend where leaders are taking concrete steps in their day to day work:</p>
<ul>
<li>Consolidating their observability toolset while maintaining capabilities, they don’t want to lose anything</li>
<li>Implementing usage-based pricing models</li>
<li>Establishing clear ROI metrics</li>
<li>Creating cross-functional teams to optimize spending</li>
</ul>
<p>This isn't just about cutting costs - it's about being smarter with resources. Organizations are learning that more tools don't necessarily mean better observability.</p>
<h2 id="twotechnologiesreshapingtheobservabilitylandscape">Two technologies reshaping the observability landscape</h2>
<h3 id="aisgrowingimpact">AI's growing impact</h3>
<p>The enthusiasm for AI is remarkable - 94% of respondents see its tremendous potential. What fascinates me is how concerns about Generative AI reliability have actually decreased from 64% to 55% over the past year.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5138bff0bb780b6/6a7f0a5fe88c6544d100b58e/image7.png" alt="" /></p>
<p>Leaders are particularly excited about:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92708af419f7bb2e/6a7f0a62bd21987622757fc9/image1.png" alt="" /></p>
<ul>
<li>Automated correlation of logs, metrics, and traces (72% of respondents)</li>
<li>Predictive analytics for preventing outages</li>
<li>Natural language interfaces for querying observability data</li>
<li>Automated root cause analysis</li>
</ul>
<p>The key shift I'm seeing for the upcoming year is the move from AI as a buzzword to AI as a practical tool delivering real value in observability workflows.  </p>
<p>Generative AI capabilities paired with retrieval augmented generation (RAG) capabilities allow organizations to leverage the power of LLMs and private data (e.g., runbooks, alerts, business data) to deliver relevant and meaningful results and identify and solve problems faster while reducing noise.</p>
<h3 id="opentelemetryscontinuedmomentum">OpenTelemetry's continued momentum</h3>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcb6abc9011647535/6a7f0a64e3a219169e99f37e/image3.png" alt="" /></p>
<p>Looking at expert organizations, 80% are either experimenting with or have deployed OpenTelemetry. This isn't just about technology adoption - it's about building for the future with open standards. The correlation between OpenTelemetry adoption and overall observability maturity is correlated and unmistakable.</p>
<p>What's particularly interesting is how OpenTelemetry is changing the vendor landscape. Organizations are increasingly demanding OpenTelemetry support from their vendors, seeing it as a way to future-proof their observability investments and avoid vendor lock-in. Thinking back to how Linux shifted the server landscape, can we expect to see the same in the observability domain?</p>
<h2 id="businessintegrationandinsightsdeepens">Business integration and insights deepens</h2>
<hr />
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91f467debde60ec5/6a7f0a67c2cc0922c0249464/image8.png" alt="" /></p>
<p>Here's what I find most compelling: 64% of expert organizations are frequently correlating operational data with business outcomes, while only 9% of early-stage organizations do the same. This represents a fundamental shift from technical monitoring to business observability.</p>
<p>This isn't just about uptime anymore - organizations are increasingly using observability data to:</p>
<ul>
<li>Make informed business decisions</li>
<li>Improve customer experience</li>
<li>Optimize resource allocation</li>
<li>Drive innovation</li>
</ul>
<h2 id="lookingahead">Looking ahead</h2>
<p>As we continue through 2025, I'm seeing observability mature beyond its initial promise. Organizations are focusing less on basic implementation and more on delivering real business value through:</p>
<ul>
<li>Deeper business integration, like mapping system performance directly to revenue metrics</li>
<li>Optimized cost management through new data lake technology, efficient storage and intelligent retention</li>
<li>AI-enhanced capabilities powered by LLMs and Agentic AI</li>
<li>Standardized instrumentation through OpenTelemetry, reducing vendor lock-in</li>
</ul>
<p>The path to success in 2025 isn't just about having the right tools - it's about building mature practices that deliver measurable business value while managing costs effectively. The organizations that can balance these competing demands while maintaining focus on business outcomes are the ones pulling ahead.</p>
<p>What are you seeing in your organization's observability journey? Are these trends aligning with your experience? </p>
<p>If you would like to dig in deeper on emerging observability trends, download <a href="https://www.elastic.co/resources/observability/report/landscape-observability-report">our full report</a> or watch the on-demand webinar, <a href="https://www.elastic.co/virtual-events/observability-trends-2025">2025 Observability trends: Maturing beyond the hype and delivering results</a>!</p>
<p>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/emerging-trends-in-observability-2025</link>
    <guid isPermaLink="false">emerging-trends-in-observability-2025</guid>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[David Hope]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5afa8cac1d6450e/6a7f0a6b77b03421db3ff3c7/trends.png" length="0" type="image/png"/>
    <pubDate>Thu, 27 Feb 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Tracing a RAG based Chatbot with Elastic Distributions of OpenTelemetry and Langtrace]]></title>
    <description><![CDATA[How to observe a OpenAI RAG based application using Elastic. Instrument the app, collect logs, traces, metrics, and understand how well the LLM is performing with Elastic Distributions of OpenTelemetry on Kubernetes with Langtrace.]]></description>
    <content:encoded><![CDATA[<p>Most AI-driven applications are currently focusing around increasing the value an end user, such as an SRE gets from AI. The main use case is the creation of various chatbots. These chatbots not only use large language models (LLMs), but are also using frameworks such as LangChain, and search to improve contextual information during a conversation (Retrieval Augmented Generation). Elastic’s sample <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/chatbot-rag-app">RAG based Chatbot application</a>, showcases how to use Elasticsearch with local data that has embeddings, enabling search to properly pull out the most contextual information during a query with a chatbot connected to an LLM of your choice. It's a great example of how to build out a RAG based application with Elasticsearch. However, what about monitoring the application?</p>
<p>Elastic provides the ability to ingest OpenTelemetry data with native OTel SDKs, the off the shelf OTel collector, or even Elastic’s Distributions of OpenTelemetry (EDOT). EDOT enables you to bring in logs, metrics and traces for your GenAI application and for K8s. However you will also generally need libraries to help trace specific components in your application. In tracing GenAI applications you can pick from a large set of libraries.</p>
<ul>
<li><p><a href="https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation-genai/opentelemetry-instrumentation-openai-v2">OpenTelemetry OpenAI Instrumentation-v2</a> - allows tracing LLM requests and logging of messages made by the OpenAI Python API library. (note v2 is built by OpenTelemetry, the non v2 version is from a specific vendor and not OpenTelemetry)</p></li>
<li><p><a href="https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation-genai/opentelemetry-instrumentation-vertexai">OpenTelemetry VertexAI Instrumentation</a> - allows tracing LLM requests and logging of messages made by the VertexAI Python API library</p></li>
<li><p><a href="https://docs.langtrace.ai/introduction">Langtrace</a> - commercially available library which supports all LLMs in one library, and all traces are also OTel native.</p></li>
<li><p>Elastic’s EDOT - which recently added tracing. See <a href="https://www.elastic.co/observability-labs/blog/openai-tracing-elastic-opentelemetry">blog</a>.</p></li>
</ul>
<p>As you can see OpenTelemetry is the defacto mechanism that is converging to collect and ingest. OpenTelemetry is growing its support for this but it is also early days.</p>
<p>In this blog, we will walk through how to, with minimal code, observe a RAG based chatbot application with tracing using Langtrace. We previously covered Langtrace in a <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing-langtrace">blog</a> to highlight tracing Langchain.</p>
<p>In this blog we used langtrace OpenAI, Amazon Bedrock, Cohere, and others in one library.</p>
<h2 id="prerequisites">Pre-requisites:</h2>
<p>In order to follow along, these few pre-requisites are needed</p>
<ul>
<li><p>An Elastic Cloud account — sign up now, and become familiar with Elastic’s OpenTelemetry configuration. With Serverless no version required. With regular cloud minimally 8.17</p></li>
<li><p>Git clone the <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/chatbot-rag-app">RAG based Chatbot application</a> and go through the <a href="https://www.elastic.co/search-labs/tutorials/chatbot-tutorial/welcome">tutorial</a> on how to bring it up and become more familiar.</p></li>
<li><p>An account on your favorite LLM (OpenAI, AzureOpen AI, etc), with API keys</p></li>
<li><p>Be familiar with EDOT to understand how we bring in logs, metrics, and traces from the application through the OTel Collector</p></li>
<li><p>Kubernetes cluster - I’ll be using Amazon EKS</p></li>
<li><p>Look at <a href="https://docs.langtrace.ai/introduction">Langtrace</a> documentation also.</p></li>
</ul>
<h2 id="applicationopentelemetryoutputinelastic">Application OpenTelemetry output in Elastic</h2>
<h3 id="chatbotragapp">Chatbot-rag-app</h3>
<p>The first item that you will need to get up and running is the ChatBotApp, and once up you should see the following:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt880964dd83511be5/6a7f0f443ce8e2feb5cf5471/Chatbotapp-general.png" alt="Chatbot app main page" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6d932574c6143415/6a7f0f48ead8ecb92fbaa976/Chatbotapp-details.png" alt="Chatbot app working" /></p>
<p>As you select some of the questions you will set a response based on the index that was created in Elasticsearch when the app initializes. Additionally there will be queries that are made to LLMs.</p>
<h3 id="traceslogsandmetricsfromedotinelastic">Traces, logs, and metrics from EDOT in Elastic</h3>
<p>Once you have OTel Collector with EDOT configuration on your K8s cluster, and Elastic Cloud up and running you should see the following:</p>
<h4 id="logs">Logs:</h4>
<p>In Discover you will see logs from the Chatbotapp, and be able to analyze the application logs, any specific log patterns (saves you time in analysis), and view logs from K8s.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta108497f956043e0/6a7f0f4a1967ea4e31330847/Chatbotapp-logs.png" alt="Chatbot-logs" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt47cfac93de9cc224/6a7f0f4d5967e535e15dd3cd/Chatbotapp-log-patterns.png" alt="Chatbot-log-patterns" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltef3b11c21b429f54/6a7f0f5063e95922cc73dedd/Chatbotapp-logs-detailed.png" alt="Chatbot-log-details" /></p>
<h4 id="traces">Traces:</h4>
<p>In Elastic Observability APM, you can also see tha chatbot details, which include transactions, dependencies, logs, errors, etc.</p>
<p>When you look at traces, you will be able to see the chatbot interactions in the trace.</p>
<ol>
<li><p>You will see the end to end http call</p></li>
<li><p>Individual calls to elasticsearch</p></li>
<li><p>Specific calls such as invoke actions, and calls to the LLM</p></li>
</ol>
<p>You can also get individual details of the traces, and look at related logs, and metrics related to that trace,</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2a985aa53fe6e887/6a7f0f536693f8a83a66402b/Chatbotapp-service-traces.png" alt="CHatbot-traces" /></p>
<h4 id="metrics">Metrics:</h4>
<p>In addition to logs, and traces, any instrumented metrics will also get ingested into Elastic.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3757e1e587a76239/6a7f0f564c4bfb17ddccd60d/chatbot-reg-metrics.png" alt="Chatbot app metrics" /></p>
<h2 id="settingitallup">Setting it all up</h2>
<p>In order to properly set up the Chatbot-app on K8s with telemetry sent over to Elastic, a few things must be set up:</p>
<ol>
<li><p>Git clone the chatbot-rag-app, and modify one of the python files.</p></li>
<li><p>Next create a docker container that can be used in Kubernetes. The Docker build <a href="https://github.com/elastic/elasticsearch-labs/blob/main/example-apps/chatbot-rag-app/Dockerfile">here</a> in the Chatbot-app is good to use.</p></li>
<li><p>Collect all needed env variables. In this example we are using OpenAI, but the files can be modified for any of the LLMs. Hence you will have to get a few environmental variables loaded into the cluster. In the github repo there is a env.example for docker. You can pick and chose what is needed or not needed and adjust appropriately in the K8s file below.</p></li>
<li><p>Set up your K8s Cluster, and then install the OpenTelemetry collector with the appropriate yaml file and credentials. This will help collect K8s cluster logs and metrics also.</p></li>
<li><p>Utilize the two yaml files listed below to ensure you can run it on Kubernetes.</p></li>
</ol>
<ul>
<li><p>Init-index-job.yaml - Initiates the index in elasticsearch with the local corporate information</p></li>
<li><p>k8s-deployment-chatbot-rag-app.yaml - initializes the application frontend and backend.</p></li>
</ul>
<ol>
<li><p>Open the app on the load balancer URL against the chatbot-app service in K8s</p></li>
<li><p>Go to Elasticsearch and look at Discover for logs, go to APM and look for your chatbot-app and review the traces, and finally.</p></li>
</ol>
<h3 id="modifythecodefortracingwithlangtrace">Modify the code for tracing with Langtrace</h3>
<p>Once you curl the app and untar, go to the chatbot-rag-app directory:</p>
<pre><code>curl https://codeload.github.com/elastic/elasticsearch-labs/tar.gz/main | 
tar -xz --strip=2 elasticsearch-labs-main/example-apps/chatbot-rag-app
cd elasticsearch-labs-main/example-apps/chatbot-rag-app
</code></pre>
<p>Next open the <code>app.py</code> file in the <code>api</code> directory and add the following </p>
<pre><code>from opentelemetry.instrumentation.flask import FlaskInstrumentor

from langtrace_python_sdk import langtrace

langtrace.init(batch=False)

FlaskInstrumentor().instrument_app(app)
</code></pre>
<p>into the code:</p>
<pre><code>import os
import sys
from uuid import uuid4

from chat import ask_question
from flask import Flask, Response, jsonify, request
from flask_cors import CORS

from opentelemetry.instrumentation.flask import FlaskInstrumentor

from langtrace_python_sdk import langtrace

langtrace.init(batch=False)

app = Flask(__name__, static_folder="../frontend/build", static_url_path="/")
CORS(app)

FlaskInstrumentor().instrument_app(app)

@app.route("/")
</code></pre>
<p>See the items in <strong>BOLD</strong> which will add in the langtrace library, and the opentelemetry flask instrumentation. This combination will provide and end to end trace for the https call all the way down to the calls to Elasticsearch, and to OpenAI (or other LLMs).</p>
<h3 id="createthedockercontainer">Create the docker container</h3>
<p>Use the Dockerfile that is in the chatbot-rag-app directory as is and add the following line:</p>
<p><code>RUN pip3 install --no-cache-dir langtrace-python-sdk</code></p>
<p>into the Dockerfile:</p>
<pre><code>COPY requirements.txt ./requirements.txt
RUN pip3 install -r ./requirements.txt
RUN pip3 install --no-cache-dir langtrace-python-sdk
COPY api ./api
COPY data ./data

EXPOSE 4000
</code></pre>
<p>This enables the <code>langtrace-python-sdk</code> to be installed into the docker container so the langtrace libraries can be used properly.</p>
<h3 id="collectingtheproperenvvariables">Collecting the proper env variables:</h3>
<p>First collect the env variables from Elastic:</p>
<p>Envs for index initialization in Elastic:</p>
<pre><code>ELASTICSEARCH_URL=https://aws.us-west-2.aws.found.io
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=elastic

# The name of the Elasticsearch indexes
ES_INDEX=workplace-app-docs
ES_INDEX_CHAT_HISTORY=workplace-app-docs-chat-history
</code></pre>
<p>The <code>ELASTICSEARCH_URL</code> can be found in cloud.elastic.co when you bring up your instance.
The user and password, you will need to setup in Elastic. </p>
<p>Envs for sending the OTel instrumentation you will need the following:</p>
<pre><code>OTEL_EXPORTER_OTLP_ENDPOINT="https://123456789.apm.us-west-2.aws.cloud.es.io:443"
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer xxxxx"
</code></pre>
<p>These credentials are found in Elastic under APM integration and under OpenTelemetry</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5d0b7250dcc156d/6a7f0f5933fa8a1f732027f0/otel-credentials.png" alt="OTel credentials" /></p>
<p>Envs for LLMs</p>
<p>In this example we’re using OpenAI, hence only three variables are needed.</p>
<pre><code>LLM_TYPE=openai
OPENAI_API_KEY=XXXX
CHAT_MODEL=gpt-4o-mini
</code></pre>
<p>All these variables will be needed in the Kubernetes yamls in the next step</p>
<h3 id="setupk8sclusterandloadupotelcollectorwithedot">Setup K8s cluster and load up OTel Collector with EDOT</h3>
<p>This step is outlined in the following <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-otel-operator">Blog</a>. It’s a simple three step process.</p>
<p>This step will bring in all the K8s cluster logs and metrics and setup the OTel collector.</p>
<h3 id="setupsecretsinitializeindicesandstarttheapp">Setup secrets, initialize indices, and start the app</h3>
<p>Now that the cluster is up, and you have your environmental variables, you will need to</p>
<ol>
<li><p>Install and run the <code>k8s-deployments.yaml</code> with the variables</p></li>
<li><p>Initialize the index</p></li>
</ol>
<p>Essentially run the following:</p>
<pre><code>kubectl create -f k8s-deployment.yaml
kubectl create -f init-index-job.yaml
</code></pre>
<p>Here are the two yamls you should use. Also found <a href="https://github.com/elastic/observability-examples/tree/main/chatbot-rag-app-observability">here</a></p>
<p>k8s-deployment.yaml</p>
<pre><code>apiVersion: v1
kind: Secret
metadata:
  name: genai-chatbot-langtrace-secrets
type: Opaque
stringData:
  OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Bearer%20xxxx"
  OTEL_EXPORTER_OTLP_ENDPOINT: "https://1234567.apm.us-west-2.aws.cloud.es.io:443"
 ELASTICSEARCH_URL: "YOUR_ELASTIC_SEARCH_URL"
  ELASTICSEARCH_USER: "elastic"
  ELASTICSEARCH_PASSWORD: "elastic"
  OPENAI_API_KEY: "XXXXXXX"  

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: genai-chatbot-langtrace
spec:
  replicas: 2
  selector:
    matchLabels:
      app: genai-chatbot-langtrace
  template:
    metadata:
      labels:
        app: genai-chatbot-langtrace
    spec:
      containers:
      - name: genai-chatbot-langtrace
        image:65765.amazonaws.com/genai-chatbot-langtrace2:latest
        ports:
        - containerPort: 4000
        env:
        - name: LLM_TYPE
          value: "openai"
        - name: CHAT_MODEL
          value: "gpt-4o-mini"
        - name: OTEL_SDK_DISABLED
          value: "false"
        - name: OTEL_RESOURCE_ATTRIBUTES
          value: "service.name=genai-chatbot-langtrace,service.version=0.0.1,deployment.environment=dev"
        - name: OTEL_EXPORTER_OTLP_PROTOCOL
          value: "http/protobuf"
        envFrom:
        - secretRef:
            name: genai-chatbot-langtrace-secrets
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"

---
apiVersion: v1
kind: Service
metadata:
  name: genai-chatbot-langtrace-service
spec:
  selector:
    app: genai-chatbot-langtrace
  ports:
  - port: 80
    targetPort: 4000
  type: LoadBalancer
</code></pre>
<p>Init-index-job.yaml</p>
<pre><code>apiVersion: batch/v1
kind: Job
metadata:
  name: init-elasticsearch-index-test
spec:
  template:
    spec:
      containers:
      - name: init-index
#update your image location for chatbot rag app
        image: your-image-location:latest
        workingDir: /app/api
        command: ["python3", "-m", "flask", "--app", "app", "create-index"]
        env:
        - name: FLASK_APP
          value: "app"
        - name: LLM_TYPE
          value: "openai"
        - name: CHAT_MODEL
          value: "gpt-4o-mini"
        - name: ES_INDEX
          value: "workplace-app-docs"
        - name: ES_INDEX_CHAT_HISTORY
          value: "workplace-app-docs-chat-history"
        - name: ELASTICSEARCH_URL
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_URL
        - name: ELASTICSEARCH_USER
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_USER
        - name: ELASTICSEARCH_PASSWORD
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_PASSWORD
        envFrom:
        - secretRef:
            name: chatbot-regular-secrets
      restartPolicy: Never
  backoffLimit: 4
</code></pre>
<h3 id="openappwithloadbalancerurl">Open App with LoadBalancer URL</h3>
<p>Run the kubectl get services command and get the URL for the chatbot app</p>
<pre><code>% kubectl get services
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                                                                     AGE
chatbot-langtrace-service            LoadBalancer   10.100.130.44    xxxxxxxxx-1515488226.us-west-2.elb.amazonaws.com   80:30748/TCP                                                                6d23h
</code></pre>
<p>Play with app and review telemetry in Elastic</p>
<p>Once you go to the URL, you should see all the screens we described earlier in the <a href="https://docs.google.com/document/d/1w_3VRDJV3CoLMjOj8Ktnng-6MuKgdzkhKs4CVBWkatc/edit?tab=t.0#bookmark=id.lrmf4nbl2twi">beginning of this blog</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>With Elastic's Chatbot-rag-app you have an example of how to build out a OpenAI driven RAG based chat application. However, you still need to understand how well it performs, whether its working properly, etc. Using OTel, Elastic’s EDOT and Langtrace gives you the ability to achieve this. Additionally, you will generally run this application on Kubernetes. Hopefully this blog provides the outline of how to achieve this.</p>
<p>Here are the other Tracing blogs:</p>
<p>App Observability with LLM (Tracing)- </p>
<ul>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing-langtrace">Observing LangChain with Langtrace and OpenTelemetry</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-openlit-tracing">Observing LangChain with OpenLit Tracing</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing">Instrumenting LangChain with OpenTelemetry</a> </p></li>
</ul>
<p>LLM Observability - </p>
<ul>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elevate-llm-observability-with-gcp-vertex-ai-integration">Elevate LLM Observability with GCP Vertex AI Integration</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-aws-bedrock">LLM Observability on AWS Bedrock</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai">LLM Observability for Azure OpenAI</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai-v2">LLM Observability for Azure OpenAI v2</a></p></li>
</ul>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/openai-tracing-langtrace-elastic</link>
    <guid isPermaLink="false">openai-tracing-langtrace-elastic</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Metrics]]></category>
    <category><![CDATA[APM]]></category>
    <category><![CDATA[Kubernetes]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3180a0fd833d64/6a7f0f5c73d9bd264e29dc29/edot-openai-tracing.png" length="0" type="image/png"/>
    <pubDate>Thu, 06 Feb 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Tracing, logs, and metrics for a RAG based Chatbot with Elastic Distributions of OpenTelemetry]]></title>
    <description><![CDATA[How to observe a OpenAI RAG based application using Elastic. Instrument the app, collect logs, traces, metrics, and understand how well the LLM is performing with Elastic Distributions of OpenTelemetry on Kubernetes and Docker.]]></description>
    <content:encoded><![CDATA[<p>As discussed in the following post, <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-openai">Elastic added instrumentation for OpenAI based applications in EDOT</a>. The main application most commonly using LLMs is known as a Chatbot. These chatbots not only use large language models (LLMs), but are also using frameworks such as LangChain, and search to improve contextual information during a conversation RAG (Retrieval Augmented Generation). Elastics's sample <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/chatbot-rag-app">RAG based Chatbot application</a>, showcases how to use Elasticsearch with local data that has embeddings, enabling search to properly pull out the most contextual information during a query with a chatbot connected to an LLM of your choice. It's a great example of how to build out a RAG based application with Elasticsearch.</p>
<p>This app is also now insturmented with EDOT, and you can visualize the Chatbot's traces to OpenAI, as well as relevant logs, and metrics from the application. By running the app as instructed in the github repo with Docker you can see these traces on a local stack. But how about running it against serverless, Elastic cloud or even with Kubernetes?</p>
<p>In this blog we will walk through how to set up Elastic's RAG Based Chatbot application with Elastic cloud and Kubernetes.</p>
<h2 id="prerequisites">Prerequisites:</h2>
<p>In order to follow along, these few pre-requisites are needed</p>
<ul>
<li><p>An Elastic Cloud account — sign up now, and become familiar with Elastic's OpenTelemetry configuration. With Serverless no version required. With regular cloud minimally 8.17</p></li>
<li><p>Git clone the <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/chatbot-rag-app">RAG based Chatbot application</a> and go through the <a href="https://www.elastic.co/search-labs/tutorials/chatbot-tutorial/welcome">tutorial</a> on how to bring it up and become more familiar and how to bring up the application using Docker.</p></li>
<li><p>An account on OpenAI with API keys</p></li>
<li><p>Kubernetes cluster to run the RAG based Chatbot app</p></li>
<li><p>The instructions in this blog are also found in <a href="https://github.com/elastic/observability-examples/tree/main/chatbot-rag-app-observability">observability-examples</a> in github.</p></li>
</ul>
<h2 id="applicationopentelemetryoutputinelastic">Application OpenTelemetry output in Elastic</h2>
<h3 id="chatbotragapp">Chatbot-rag-app</h3>
<p>The first item that you will need to get up and running is the ChatBotApp, and once up you should see the following:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdd100775bedb7fa2/6a7f0f2be3a2190cf999f57e/Chatbotapp-general.png" alt="Chatbot app main page" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt68a2dbea6d8f3991/6a7f0f2e4c4bfb9fbaccd603/Chatbotapp-details.png" alt="Chatbot app working" /></p>
<p>As you select some of the questions you will set a response based on the index that was created in Elasticsearch when the app initializes. Additionally there will be queries that are made to LLMs.</p>
<h3 id="traceslogsandmetricsfromedotinelastic">Traces, logs, and metrics from EDOT in Elastic</h3>
<p>Once you have the application running on your K8s cluster or with Docker, and Elastic Cloud up and running you should see the following:</p>
<h4 id="logs">Logs:</h4>
<p>In Discover you will see logs from the Chatbotapp, and be able to analyze the application logs, any specific log patterns, which saves you time in analysis.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt29660a76fd00a49c/6a7f0f316c6eac6076f14207/chatbot-reg-logs.png" alt="Chatbot-logs" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdc9a84779ba0d561/6a7f0f34ea068d10eff09f64/chatbot-reg-logs-patterns.png" alt="Chatbot-log-patterns" /></p>
<h4 id="traces">Traces:</h4>
<p>In Elastic Observability APM, you can also see tha chatbot details, which include transactions, dependencies, logs, errors, etc.</p>
<p>When you look at traces, you will be able to see the chatbot interactions in the trace.</p>
<ol>
<li><p>You will see the end to end http call</p></li>
<li><p>Individual calls to elasticsearch</p></li>
<li><p>Specific calls such as invoke actions, and calls to the LLM</p></li>
</ol>
<p>You can also get individual details of the traces, and look at related logs, and metrics related to that trace,</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt810b06d98a833d78/6a7f0f376693f8036f664023/chatbot-reg-trace.png" alt="CHatbot-traces" /></p>
<h4 id="metrics">Metrics:</h4>
<p>In addition to logs, and traces, any instrumented metrics will also get ingested into Elastic.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16786031635f9d06/6a7f0f3a448e4eedc45c0803/chatbot-reg-metrics.png" alt="Chatbot app metrics" /></p>
<h2 id="settingitallupwithdocker">Setting it all up with Docker</h2>
<p>In order to properly set up the Chatbot-app on Docker with telemetry sent over to Elastic, a few things must be set up:</p>
<ol>
<li><p>Git clone the chatbot-rag-app</p></li>
<li><p>Modify the env file as noted in the github README with the following exception:</p></li>
</ol>
<p>Use your Elastic cloud's <code>OTEL_EXPORTER_OTLP_ENDPOINT</code> and <code>OTEL_EXPORTER_OTLP_HEADER</code> instead.</p>
<p>You can find these in the Elastic Cloud under <code>integrations-&gt;APM</code></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3720f7995587366b/6a7f0f3d3cab1c13600e494c/otel-credentials.png" alt="OTel credentials" /></p>
<p>Envs for sending the OTel instrumentation you will need the following:</p>
<pre><code>OTEL_EXPORTER_OTLP_ENDPOINT="https://123456789.apm.us-west-2.aws.cloud.es.io:443"
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20xxxxx"
</code></pre>
<p>Notice the <code>%20</code> in the headers. This will be needed to account for the space in credentials.</p>
<ol>
<li><p>Set the following to false - <code>OTEL_SDK_DISABLED=false</code></p></li>
<li><p>Set the envs for LLMs </p></li>
</ol>
<p>In this example we're using OpenAI, hence only three variables are needed.</p>
<pre><code>LLM_TYPE=openai
OPENAI_API_KEY=XXXX
CHAT_MODEL=gpt-4o-mini
</code></pre>
<ol>
<li>Run the docker container as noted </li>
</ol>
<pre><code>docker compose up --build --force-recreate
</code></pre>
<ol>
<li><p>Play with the app at <code>localhost:4000</code></p></li>
<li><p>Then log into Elastic cloud and see the output as shown previously.</p></li>
</ol>
<h2 id="runchatbotragapponkubernetes">Run chatbot-rag-app on Kubernetes</h2>
<p>In order to set this up, you can follow the following repo on Observability-examples which has the Kubernetes yaml files being used. These will also point to Elastic Cloud.</p>
<ol>
<li><p>Set up the Kubernetes Cluster (we're using EKS)</p></li>
<li><p>Get the appropriate ENV variables:</p></li>
</ol>
<ul>
<li><p>Find the <code>OTEL_EXPORTER_OTLP_ENDPOINT/HEADER</code> variables as noted in the pervious for Docker.</p></li>
<li><p>Get your OpenAI Key</p></li>
<li><p>Elasticsearch URL, and username and password.</p></li>
</ul>
<ol>
<li>Follow the instructions in the following <a href="https://github.com/elastic/observability-examples/tree/main/chatbot-rag-app-observability">github repo in observability examples</a> to run two Kubernetes yaml files.</li>
</ol>
<p>Essentially you need only replace the secret variables in k8s-deployment.yaml, and run</p>
<pre><code>kubectl create -f k8s-deployment.yaml
kubectl create -f init-index-job.yaml
</code></pre>
<p>The app needs to be running first, then we use the app to initialize Elasticsearch with indices for the app.</p>
<p><strong><em>Init-index-job.yaml</em></strong></p>
<pre><code>apiVersion: batch/v1
kind: Job
metadata:
  name: init-elasticsearch-index-test
spec:
  template:
    spec:
      containers:
      - name: init-index
        image: ghcr.io/elastic/elasticsearch-labs/chatbot-rag-app:latest
        workingDir: /app/api
        command: ["python3", "-m", "flask", "--app", "app", "create-index"]
        env:
        - name: FLASK_APP
          value: "app"
        - name: LLM_TYPE
          value: "openai"
        - name: CHAT_MODEL
          value: "gpt-4o-mini"
        - name: ES_INDEX
          value: "workplace-app-docs"
        - name: ES_INDEX_CHAT_HISTORY
          value: "workplace-app-docs-chat-history"
        - name: ELASTICSEARCH_URL
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_URL
        - name: ELASTICSEARCH_USER
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_USER
        - name: ELASTICSEARCH_PASSWORD
          valueFrom:
            secretKeyRef:
              name: chatbot-regular-secrets
              key: ELASTICSEARCH_PASSWORD
        envFrom:
        - secretRef:
            name: chatbot-regular-secrets
      restartPolicy: Never
  backoffLimit: 4
</code></pre>
<p><strong><em>k8s-deployment.yaml</em></strong></p>
<pre><code>apiVersion: v1
kind: Secret
metadata:
  name: chatbot-regular-secrets
type: Opaque
stringData:
  ELASTICSEARCH_URL: "https://yourelasticcloud.es.us-west-2.aws.found.io"
  ELASTICSEARCH_USER: "elastic"
  ELASTICSEARCH_PASSWORD: "elastic"
  OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Bearer%20xxxx"
  OTEL_EXPORTER_OTLP_ENDPOINT: "https://12345.apm.us-west-2.aws.cloud.es.io:443"
  OPENAI_API_KEY: "YYYYYYYY"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: chatbot-regular
spec:
  replicas: 2
  selector:
    matchLabels:
      app: chatbot-regular
  template:
    metadata:
      labels:
        app: chatbot-regular
    spec:
      containers:
      - name: chatbot-regular
        image: ghcr.io/elastic/elasticsearch-labs/chatbot-rag-app:latest
        ports:
        - containerPort: 4000
        env:
        - name: LLM_TYPE
          value: "openai"
        - name: CHAT_MODEL
          value: "gpt-4o-mini"
        - name: OTEL_RESOURCE_ATTRIBUTES
          value: "service.name=chatbot-regular,service.version=0.0.1,deployment.environment=dev"
        - name: OTEL_SDK_DISABLED
          value: "false"
        - name: OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT
          value: "true"
        - name: OTEL_EXPERIMENTAL_RESOURCE_DETECTORS
          value: "process_runtime,os,otel,telemetry_distro"
        - name: OTEL_EXPORTER_OTLP_PROTOCOL
          value: "http/protobuf"
        - name: OTEL_METRIC_EXPORT_INTERVAL
          value: "3000"
        - name: OTEL_BSP_SCHEDULE_DELAY
          value: "3000"
        envFrom:
        - secretRef:
            name: chatbot-regular-secrets
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"

---
apiVersion: v1
kind: Service
metadata:
  name: chatbot-regular-service
spec:
  selector:
    app: chatbot-regular
  ports:
  - port: 80
    targetPort: 4000
  type: LoadBalancer
</code></pre>
<p><strong>Open App with LoadBalancer URL</strong></p>
<p>Run the kubectl get services command and get the URL for the chatbot app</p>
<pre><code>% kubectl get services
NAME                                 TYPE           CLUSTER-IP    EXTERNAL-IP                                                               PORT(S)                                                                     AGE
chatbot-regular-service            LoadBalancer   10.100.130.44    xxxxxxxxx-1515488226.us-west-2.elb.amazonaws.com   80:30748/TCP                                                                6d23h
</code></pre>
<ol>
<li><p>Play with app and review telemetry in Elastic</p></li>
<li><p>Once you go to the URL, you should see all the screens we described earlier in the beginning of this blog.</p></li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>With Elastic's Chatbot-rag-app you have an example of how to build out a OpenAI driven RAG based chat application. However, you still need to understand how well it performs, whether its working properly, etc. Using OTel and Elastic’s EDOT gives you the ability to achieve this. Additionally, you will generally run this application on Kubernetes. Hopefully this blog provides the outline of how to achieve this.
Here are the other Tracing blogs:</p>
<p>App Observability with LLM (Tracing)- </p>
<ul>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing-langtrace">Observing LangChain with Langtrace and OpenTelemetry</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-openlit-tracing">Observing LangChain with OpenLit Tracing</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing">Instrumenting LangChain with OpenTelemetry</a> </p></li>
</ul>
<p>LLM Observability - </p>
<ul>
<li><p><a href="https://www.elastic.co/observability-labs/blog/elevate-llm-observability-with-gcp-vertex-ai-integration">Elevate LLM Observability with GCP Vertex AI Integration</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-aws-bedrock">LLM Observability on AWS Bedrock</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai">LLM Observability for Azure OpenAI</a></p></li>
<li><p><a href="https://www.elastic.co/observability-labs/blog/llm-observability-azure-openai-v2">LLM Observability for Azure OpenAI v2</a></p></li>
</ul>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/openai-tracing-elastic-opentelemetry</link>
    <guid isPermaLink="false">openai-tracing-elastic-opentelemetry</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Metrics]]></category>
    <category><![CDATA[APM]]></category>
    <category><![CDATA[Kubernetes]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt12854c40fcaa0e97/6a7f0f406c6eac23bbf1420f/edot-openai-tracing.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 24 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Instrumenting your OpenAI-powered Python, Node.js, and Java Applications with EDOT]]></title>
    <description><![CDATA[Elastic is proud to introduce OpenAI support in our Python, Node.js and Java EDOT SDKs. These add logs, metrics and tracing to applications that use OpenAI compatible services without any code change.]]></description>
    <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Last year, <a href="https://www.elastic.co/blog/elastic-distributions-opentelemetry">we announced Elastic Distribution of OpenTelemetry</a> (a.k.a. EDOT) language SDKs, which collect logs, traces and metrics from applications. When this was announced, we didn’t yet support Large Language Model (LLM) providers such as OpenAI. This limited insight developers had into Generative AI (GenAI) applications.</p>
<p>In a <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing-langtrace">prior post</a>, we reviewed LLM observability focus, such as token usage, chat latency and knowing which tools (like DuckDuckGo) your application uses. With the right logs, traces and metrics, developers can answer questions like "Which version of a model generated this response?" or "What was the exact chat prompt created by my RAG application?"</p>
<p>In the last six months, Elastic invested a lot of energy alongside others in the OpenTelemetry community towards shared specifications on these areas, including code to collect LLM related logs, metrics and traces. Our goal was to extend the zero code (agent) approach EDOT brings to GenAI use cases.</p>
<p>Today, we announce our first GenAI instrumentation capability in the EDOT language SDKs: OpenAI. Below, you’ll see how to observe GenAI applications using our Python, Node.js and Java EDOT SDKs.</p>
<h2 id="exampleapplication">Example application</h2>
<p>Many of us may be familiar with <a href="https://chatgpt.com/">ChatGPT</a>, which is frontend for OpenAI’s GPT model family. Using this, you can ask a question and the assistant might reply correctly depending on what you ask and text the LLM was trained on.</p>
<p>Here’s an example of an esoteric question answered by ChatGPT:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltedb3a50448470314/6a7f08cbbd21986162757f1f/chatgpt-screenshot.png" alt="ChatGPT answer" /></p>
<p>Our example application will simply ask this predefined question and print the result. We’ll write it in three languages: Python, JavaScript and Java.</p>
<p>We’ll execute each with a "zero code" (agent) approach, so that logs, metrics and traces are captured and visible in an Elastic Stack configured with Kibana and APM server. If you don’t have a stack running, use <a href="https://github.com/elastic/elasticsearch-labs/tree/main/docker">instructions from Elasticsearch Labs</a> to set one up.</p>
<p>Regardless of programming language, three variables are needed: the OpenAI API key, the location of your Elastic APM server, and the service name of the application. You’ll write these to a file named <code>.env</code>.</p>
<pre><code>OPENAI_API_KEY=sk-YOUR_API_KEY
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8200
OTEL_SERVICE_NAME=openai-example
</code></pre>
<p>By default instrumentations does not capture the content sent to the OpenAI API in the GenAI events sent to logs, if you want to capture it add the following:</p>
<pre><code>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
</code></pre>
<p>Each time the application is run, it sends logs, traces and metrics to the APM server, which you can find by querying Kibana like this for the application "openai-example"</p>
<p>http://localhost:5601/app/apm/services/openai-example/transactions</p>
<p>When you choose a trace, you’ll see the LLM request made by the OpenAI SDK, and HTTP traffic caused by it:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5987344c4d68ea32/6a7f08cf96b5a6107687b2cd/kibana-transaction-timeline.png" alt="Kibana transaction timeline" /></p>
<p>Select the logs tab to see the exact request and response to OpenAI. This data is critical for Q/A and evaluation use cases.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta35f22e88805b0ee/6a7f08d24c4bfbe008ccd395/kibana-transaction-logs.png" alt="Kibana transaction logs" /></p>
<p>You can also go to the Metrics Explorer and make a graph of "gen_ai.client.token.usage" or "gen_ai.client.operation.duration" over all the times you ran the application:</p>
<p>http://localhost:5601/app/metrics/explorer</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0561523ff7bc4b29/6a7f08d51967eac5b5330593/kibana-metrics-explorer.png" alt="Kibana Metrics Explorer" /></p>
<p>Continue to see exactly how this application looks and is run, in Python, Java and Node.js. Those already using our EDOT language SDKs will be familiar with how this works.</p>
<h2 id="python">Python</h2>
<p>Assuming you have python installed, the first thing would be to setup a virtual environment and install the required packages: the OpenAI client, a helper tool to read the <code>.env</code> file and our <a href="https://github.com/elastic/elastic-otel-python">EDOT Python</a> package:</p>
<pre><code>python3 -m venv .venv
source .venv/bin/activate
pip install openai "python-dotenv[cli]" elastic-opentelemetry
</code></pre>
<p>Next, run <code>edot-bootstrap</code> which analyzes the code to install any relevant instrumentation available:</p>
<pre><code>edot-bootstrap —-action=install
</code></pre>
<p>Now, create your <code>.env</code>file, as described earlier in this article, and the below source code in <code>chat.py</code></p>
<pre><code>import os

import openai

CHAT_MODEL = os.environ.get("CHAT_MODEL", "gpt-4o-mini")


def main():
  client = openai.Client()

  messages = [
    {
      "role": "user",
        "content": "Answer in up to 3 words: Which ocean contains Bouvet Island?",
    }
  ]

  chat_completion = client.chat.completions.create(model=CHAT_MODEL, messages=messages)
  print(chat_completion.choices[0].message.content)

if __name__ == "__main__":
  main()
</code></pre>
<p>Now you can run everything with:</p>
<pre><code>dotenv run -- opentelemetry-instrument python chat.py
</code></pre>
<p>Finally, look for a trace for the service named "openai-example" in Kibana. You should see a transaction named "chat gpt-4o-mini".</p>
<p>Rather than copy/pasting above, you can find a working copy of this example (along with the instructions) in the Python EDOT repository <a href="https://github.com/elastic/elastic-otel-python/tree/main/examples/openai">here</a>.</p>
<p>Finally, if you would like to try a more comprehensive example, take a look at <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/chatbot-rag-app">chatbot-rag-app</a> which uses OpenAI with Elasticsearch’s <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html">Elser</a> retrieval model.</p>
<h2 id="java">Java</h2>
<p>There are multiple popular ways to initialize a Java project. Since we are using OpenAI, the first step is to configure the dependency <a href="https://central.sonatype.com/artifact/com.openai/openai-java"><code>com.openai:openai-java</code></a> and write the below source as <code>Chat.java.</code></p>
<pre><code>package openai.example;

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.*;


final class Chat {

  public static void main(String[] args) {
    String chatModel = System.getenv().getOrDefault("CHAT_MODEL", "gpt-4o-mini");

    OpenAIClient client = OpenAIOkHttpClient.fromEnv();

    String message = "Answer in up to 3 words: Which ocean contains Bouvet Island?";
    ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
        .addMessage(ChatCompletionUserMessageParam.builder()
          .content(message)
          .build())
        .model(chatModel)
        .build();

    ChatCompletion chatCompletion = client.chat().completions().create(params);
    System.out.println(chatCompletion.choices().get(0).message().content().get());
  }
}
</code></pre>
<p>Build the project such that all dependencies are in a single jar. For example, if using Gradle, you would use the <code>com.gradleup.shadow</code>plugin.</p>
<p>Next, create your <code>.env</code>file, as described earlier, and download shdotenv which we’ll use to load it.</p>
<pre><code>curl -O -L https://github.com/ko1nksm/shdotenv/releases/download/v0.14.0/shdotenv
chmod +x ./shdotenv
</code></pre>
<p>At this point, you have a jar and configuration you can use to run the OpenAI example. The next step is to download the EDOT Java javaagent binary. This is the part that records and exports logs, metrics and traces.</p>
<pre><code>curl -o elastic-otel-javaagent.jar -L 'https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&amp;g=co.elastic.otel&amp;a=elastic-otel-javaagent&amp;v=LATEST'
</code></pre>
<p>Assuming you assembled a file named <code>openai-example-all.jar</code>, run it with EDOT like this:</p>
<pre><code>./shdotenv java -javaagent:elastic-otel-javaagent.jar -jar openai-example-all.jar
</code></pre>
<p>Finally, look for a trace for the service named "openai-example" in Kibana. You should see a transaction named "chat gpt-4o-mini".</p>
<p>Rather than copy/pasting above, you can find a working copy of this example in the EDOT Java source repository <a href="https://github.com/elastic/elastic-otel-java/tree/main/examples/openai">here</a>.</p>
<h2 id="nodejs">Node.js</h2>
<p>Assuming you already have npm installed and configured, run the following commands to initialize a project for the example. This includes the <a href="https://www.npmjs.com/package/openai">openai</a> package and <a href="https://www.npmjs.com/package/@elastic/opentelemetry-node"><code>@elastic/opentelemetry-node</code></a> (EDOT Node.js)</p>
<pre><code>npm init -y
npm install openai @elastic/opentelemetry-node
</code></pre>
<p>Next, create your <code>.env</code> file, as described earlier in this article and the below source code in <code>index.js</code></p>
<pre><code>const {OpenAI} = require('openai');

let chatModel = process.env.CHAT_MODEL ?? 'gpt-4o-mini';

async function main() {
 const client = new OpenAI();
 const completion = await client.chat.completions.create({
  model: chatModel,
  messages: [
   {
    role: 'user',
    content: 'Answer in up to 3 words: Which ocean contains Bouvet Island?',
   },
  ],
 });
 console.log(completion.choices[0].message.content);
}

main();
</code></pre>
<p>With this in place, run the above source with EDOT like this:</p>
<pre><code>node --env-file .env --require @elastic/opentelemetry-node index.js
</code></pre>
<p>Finally, look for a trace for the service named "openai-example" in Kibana. You should see a transaction named "chat gpt-4o-mini".</p>
<p>Rather than copy/pasting above, you can find a working copy of this example in the EDOT Node.js source repository <a href="https://github.com/elastic/elastic-otel-node/tree/main/examples/openai">here</a>.</p>
<p>Finally, if you would like to try a more comprehensive example, take a look at <a href="https://github.com/elastic/elasticsearch-labs/tree/main/example-apps/openai-embeddings">openai-embeddings</a> which uses OpenAI with Elasticsearch as a vector database!</p>
<h2 id="closingnotes">Closing Notes</h2>
<p>Above you’ve seen how to observe the official OpenAI SDK in three different languages, using Elastic Distribution of OpenTelemetry (EDOT).</p>
<p>It is important to note that some of the OpenAI SDKs and also OpenTelemetry specifications around generative AI are experimental. If you find this helps you, or find glitches, please join our slack and let us know about it.</p>
<p>Several LLM platforms accept requests from the OpenAI client SDK, by setting <code>OPENAI_BASE_URL</code> and choosing relevant models. During development, we tested against OpenAI Platform and Azure OpenAI Service. We also ran integration tests against Ollama, contributing improvements its OpenAI support released in v0.5.12. Whatever your choice of OpenAI compatible platform, we hope this new tooling helps you understand your LLM usage.</p>
<p>Finally, while the first Generative AI SDK instrumented with EDOT is OpenAI, you’ll see more soon. We are already working on Bedrock, and collaborating with others in the OpenTelemetry community for other platforms. Keep watching this blog for exciting updates.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-openai</link>
    <guid isPermaLink="false">elastic-opentelemetry-openai</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Metrics]]></category>
    <dc:creator><![CDATA[Adrian Cole]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt43126fbb328992ce/6a84041c5751aa67087e402a/elastic-opentelemetry-openai.png" length="0" type="image/png"/>
    <pubDate>Thu, 23 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Observing Langchain applications with Elastic, OpenTelemetry, and Langtrace]]></title>
    <description><![CDATA[Langchain applications are growing in use. The ability to build out RAG-based applications, simple AI Assistants, and more is becoming the norm. Observing these applications is even harder. Given the various options that are out there, this blog shows how to use OpenTelemetry instrumentation with Langtrace and ingest it into Elastic Observability APM]]></description>
    <content:encoded><![CDATA[<p>As AI-driven applications become increasingly complex, the need for robust tools to monitor and optimize their performance is more critical than ever. LangChain has rapidly emerged as a crucial framework in the AI development landscape, particularly for building applications powered by large language models (LLMs). As its adoption has soared among developers, the need for effective debugging and performance optimization tools has become increasingly apparent. One such essential tool is the ability to obtain and analyze traces from Langchain applications. Tracing provides invaluable insights into the execution flow, helping developers understand and improve their AI-driven systems. <a href="https://www.elastic.co/observability/application-performance-monitoring">Elastic Observability's APM</a> provides an ability to trace your Langchain apps with OpenTelemetry, but you need third-party libraries.</p>
<p>There are several options to trace for Langchain. <a href="https://docs.langtrace.ai/introduction">Langtrace</a> is one such option. Langtrace is an <a href="https://github.com/Scale3-Labs/langtrace">open-source</a> observability software that lets you capture, debug and analyze traces and metrics from all your applications. Langtrace automatically captures traces from LLM APIs/inferences, Vector Databases, and LLM-based Frameworks. Langtrace stands out due to its seamless integration with popular LLM frameworks and its ability to provide deep insights into complex AI workflows without requiring extensive manual instrumentation.</p>
<p>Langtrace has an SDK, a lightweight library that can be installed and imported into your project to collect traces. The traces are OpenTelemetry-based and can be exported to Elastic without using a Langtrace API key.</p>
<p>OpenTelemetry (OTel) is now broadly accepted as the industry standard for tracing. As one of the major Cloud Native Computing Foundation (CNCF) projects, with as many commits as Kubernetes, it is gaining support from major ISVs and cloud providers delivering support for the framework. </p>
<p>Hence, many LangChain-based applications will have multiple components beyond just LLM interactions. Using OpenTelemetry with LangChain is essential. </p>
<p>This blog will cover how you can use Langtrace SDK to trace a simple LangChain Chat app connecting to Azure OpenAI, perform a search in DuckDuckGoSearch and export the output to Elastic.</p>
<h2 id="prerequisites">Pre-requisites:</h2>
<ul>
<li><p>An Elastic Cloud account — <a href="https://cloud.elastic.co/">sign up now</a>, and become familiar with <a href="https://www.elastic.co/guide/en/observability/current/apm-open-telemetry.html">Elastic’s OpenTelemetry configuration</a></p></li>
<li><p>Have a LangChain app to instrument</p></li>
<li><p>Be familiar with using <a href="https://opentelemetry.io/docs/languages/python/libraries/">OpenTelemetry’s Python SDK</a> </p></li>
<li><p>An account on your favorite LLM (AzureOpen AI), with API keys</p></li>
<li><p>The application we used in this blog, called <code>langchainChat</code> can be found in <a href="https://github.com/elastic/observability-examples/tree/main/langchainChat">Github langhcainChat</a>. It is built using Azure OpenAI and DuckDuckGo, but you can easily modify it for your LLM and search of choice.</p></li>
</ul>
<h2 id="appoverviewandoutputinelastic">App Overview and output in Elastic:</h2>
<p>To showcase the combined power of Langtrace and Elastic, we created a simple LangChain app that performs the following steps:</p>
<ol>
<li><p>Takes customer input on the command line. (Queries)</p></li>
<li><p>Sends these to the Azure OpenAI LLM via a LangChain.</p></li>
<li><p>Utilizes chain tools to perform a search using DuckDuckGo.</p></li>
<li><p>The LLM processes the search results and returns the relevant information to the user.</p></li>
</ol>
<p>Here is a sample interaction:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt76b2d020888007a7/6a7f08925967e5c1035dd10c/langchainchat-cli.png" alt="Chat Interaction" /></p>
<p>Here is what the service view looks like after we ran a few queries. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16c8c79d875d3a11/6a7f0895b6b7348147e48c42/langchainchat-overview.png" alt="Service Overview" /></p>
<p>As you can see, Elastic Observability’s APM recognizes the LangChain app and also shows the average latency, throughput, and transactions. Our average latency is 30s since it takes that log for humans to type the query (twice).</p>
<p>You can also select other tabs to see, dependencies, errors, metrics, and more. One interesting part of Elastic APM is the ability to use universal profiling (eBPF) output also analyzed for this service. Here is what our service’s dependency is (Azure OpenAI) with its average latency, throughput, and failed transactions:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8736bb62fef3dec2/6a7f08982f00b26dbbefe9e3/langchainchat-dependency.png" alt="Dependencies" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltccf60cbec05ce73d/6a7f089a448e4e59fa5c0540/langchainchat-dependency-metrics.png" alt="Dependency-metric" /></p>
<p>We see Azure OpenAI is on average 4s to give us the results.</p>
<p>If we drill into transactions and look at the trace for our queries on Taylor Swift and Pittsburgh Steelers, we can see both queries and their corresponding spans.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d3ebad3e3fdf95c/6a7f089e3cab1c74990e4694/langchainchat-trace.png" alt="Trace for two queries" /></p>
<p>In this trace:</p>
<ol>
<li><p>The user makes a query</p></li>
<li><p>Azure OpenAI is called, but it uses a tool (DuckDuckGo) to obtain some results</p></li>
<li><p>Azure OpenAI reviews and returns a summary to the end user</p></li>
<li><p>Repeats for another query</p></li>
</ol>
<p>We noticed that the other long span (other than Azure OpenAI) is Duckduckgo (~1000ms). We can individually look at the span and review the data:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt322bb5b1d8291b1e/6a7f08a12f00b27e54efe9e9/langchainchat-tools-span.png" alt="Span details" /></p>
<h2 id="configuration">Configuration:</h2>
<p>How do we make all this show up in Elastic? Let's go over the steps:</p>
<h3 id="opentelemetryconfiguration">OpenTelemetry Configuration</h3>
<p>To leverage the full capabilities of OpenTelemetry with Langtrace and Elastic, we need to configure the SDK to generate traces and properly set up Elastic’s endpoint and authorization. Detailed instructions can be found in the <a href="https://opentelemetry.io/docs/zero-code/python/#setup">OpenTelemetry Auto-Instrumentation setup documentation</a>.</p>
<h4 id="opentelemetryenvironmentvariables">OpenTelemetry Environment variables:</h4>
<p>For Elastic, you can set the following OpenTelemetry environment variables either in your Linux/Mac environment or directly in the code:</p>
<pre><code>OTEL_EXPORTER_OTLP_ENDPOINT=12345.apm.us-west-2.aws.cloud.es.io:443
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20ZZZZZZZ"
OTEL_RESOURCE_ATTRIBUTES="service.name=langchainChat,service.version=1.0,deployment.environment=production"
</code></pre>
<p>In this setup:</p>
<ul>
<li><p><strong>OTEL_EXPORTER_OTLP_ENDPOINT</strong> is configured to send traces to Elastic.</p></li>
<li><p><strong>OTEL_EXPORTER_OTLP_HEADERS</strong> provides the necessary authorization for the Elastic APM server.</p></li>
<li><p><strong>OTEL_RESOURCE_ATTRIBUTES</strong> define key attributes like the service name, version, and deployment environment.</p></li>
</ul>
<p>These values can be easily obtained from Elastic’s APM configuration screen under the OpenTelemetry section.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb5cb2d3359013d1/6a7f08a442a1178c6b95bcfe/langchainchat-OTelAPMsetup.png" alt="Span details" /></p>
<p><strong>Note: No agent is required; the OTLP trace messages are sent directly to Elastic’s APM server, simplifying the setup process.</strong></p>
<h3 id="langtracelibrary">Langtrace Library:</h3>
<p>OpenTelemetry's auto-instrumentation can be extended to trace additional frameworks using instrumentation packages. For this blog post, you will need to install the Langtrace Python SDK:</p>
<pre><code>pip install langtrace-python-sdk 
</code></pre>
<p>After installation, you can add the following code to your project:</p>
<pre><code>from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

from langtrace_python_sdk import langtrace, with_langtrace_root_span
</code></pre>
<h3 id="instrumentation">Instrumentation:</h3>
<p>Once the necessary libraries are installed and the environment variables are configured, you can use auto-instrumentation to trace your application. For example, run the following command to instrument your LangChain application with Elastic:</p>
<pre><code>opentelemetry-instrument python langtrace-elastic-demo.py
</code></pre>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5d3ebad3e3fdf95c/6a7f089e3cab1c74990e4694/langchainchat-trace.png" alt="Trace for two queries" /></p>
<p>The Langtrace OpenTelemetry library correctly captures the flow with minimal manual instrumentation, apart from integrating the OpenTelemetry library. Additionally, the LLM spans captured by Langtrace also include useful metadata such as token counts, model hyper-parameter settings etc. Note that the generated spans follow the OTEL GenAI semantics described <a href="https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/">here</a>.</p>
<p>In summary, the instrumentation process involves:</p>
<ol>
<li><p>Capturing customer input from the command line (Queries).</p></li>
<li><p>Sending these queries to the Azure OpenAI LLM via a LangChain.</p></li>
<li><p>Utilizing chain tools, such as DuckDuckGo, to perform searches.</p></li>
<li><p>The LLM processes the results and returns the relevant information to the user.</p></li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>By combining the power of <a href="https://langtrace.ai/">Langtrace</a> with Elastic, developers can achieve unparalleled visibility into their LangChain applications, ensuring optimized performance and quicker debugging. This powerful combination simplifies the complex task of monitoring AI-driven systems, enabling you to focus on what truly matters—delivering value to your users. Throughout this blog,we've covered the following essential steps and concepts:</p>
<ul>
<li><p>How to manually instrument Langchain with OpenTelemetry</p></li>
<li><p>How to properly initialize OpenTelemetry and add a custom span</p></li>
<li><p>How to easily set the OTLP ENDPOINT and OTLP HEADERS with Elastic without the need for a collector</p></li>
<li><p>How to view and analyze traces in Elastic Observability APM</p></li>
</ul>
<p>These steps provide a clear and actionable guide for developers looking to integrate robust tracing capabilities into their LangChain applications.</p>
<p>We hope this guide makes understanding and implementing OpenTelemetry tracing for LangChain simple, ensuring seamless integration with Elastic.</p>
<p><strong>Additional resources for OpenTelemetry with Elastic:</strong></p>
<ul>
<li><p><a href="https://www.elastic.co/blog/opentelemetry-observability">Independence with OpenTelemetry on Elastic</a></p></li>
<li><p><a href="https://www.elastic.co/blog/implementing-kubernetes-observability-security-opentelemetry">Modern observability and security on Kubernetes with Elastic and OpenTelemetry</a></p></li>
<li><p><a href="https://www.elastic.co/blog/3-models-logging-opentelemetry-elastic">3 models for logging with OpenTelemetry and Elastic</a></p></li>
<li><p><a href="https://www.elastic.co/blog/adding-free-and-open-elastic-apm-as-part-of-your-elastic-observability-deployment">Adding free and open Elastic APM as part of your Elastic Observability deployment</a></p></li>
<li><p><a href="https://www.elastic.co/blog/monitor-openai-api-gpt-models-opentelemetry-elastic">Monitor OpenAI API and GPT models with OpenTelemetry and Elastic</a></p></li>
<li><p>Futureproof<a href="https://www.elastic.co/virtual-events/future-proof-your-observability-platform-with-opentelemetry-and-elastic"> your observability platform with OpenTelemetry and Elastic</a></p></li>
<li><p>Instrumentation resources:</p></li>
<li><p>Python: <a href="https://www.elastic.co/blog/auto-instrumentation-of-python-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-python-applications-opentelemetry">Manual instrumentation</a></p></li>
<li><p>Java: <a href="https://www.elastic.co/blog/auto-instrumentation-of-java-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-java-applications-opentelemetry">Manual instrumentation </a></p></li>
<li><p>Node.js: <a href="https://www.elastic.co/blog/auto-instrument-nodejs-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-nodejs-applications-opentelemetry">Manual instrumentation</a></p></li>
<li><p>.NET: <a href="https://www.elastic.co/blog/auto-instrumentation-of-net-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-net-applications-opentelemetry">Manual instrumentation</a></p></li>
<li><p><a href="https://docs.langtrace.ai/supported-integrations/observability-tools/elastic">Elastic APM - Langtrace AI Docs</a></p></li>
</ul>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing-langtrace</link>
    <guid isPermaLink="false">elastic-opentelemetry-langchain-tracing-langtrace</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[APM]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <dc:creator><![CDATA[Bahubali Shetti,Karthik Kalyanaraman,Yemi Adejumobi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt405f53422a8d599e/6a7f08a81967ea8d8333057d/elastic-langtrace.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 02 Sep 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Tracing LangChain apps with Elastic, OpenLLMetry, and OpenTelemetry]]></title>
    <description><![CDATA[LangChain applications are growing in use. The ability to build out RAG-based applications, simple AI Assistants, and more is becoming the norm. Observing these applications is even harder. Given the various options that are out there, this blog shows how to use OpenTelemetry instrumentation with OpenLLMetry and ingest it into Elastic Observability APM]]></description>
    <content:encoded><![CDATA[<p>LangChain has rapidly emerged as a crucial framework in the AI development landscape, particularly for building applications powered by large language models (LLMs). As its adoption has soared among developers, the need for effective debugging and performance optimization tools has become increasingly apparent. One such essential tool is the ability to obtain and analyze traces from LangChain applications. Tracing provides invaluable insights into the execution flow, helping developers understand and improve their AI-driven systems. </p>
<p>There are several options to trace for LangChain. One is Langsmith, ideal for detailed tracing and a complete breakdown of requests to large language models (LLMs). However, it is specific to Langchain. OpenTelemetry (OTel) is now broadly accepted as the industry standard for tracing. As one of the major Cloud Native Computing Foundation (CNCF) projects, with as many commits as Kubernetes, it is gaining support from major ISVs and cloud providers delivering support for the framework. </p>
<p>Hence, many LangChain-based applications will have multiple components beyond just LLM interactions. Using OpenTelemetry with LangChain is essential. OpenLLMetry is an available option for tracing Langchain apps in addition to Langsmith.</p>
<p>This blog will show how you can get LangChain tracing into Elastic using the OpenLLMetry library <code>opentelemetry-instrumentation-langchain</code>.</p>
<h2 id="prerequisitesaidprerequisitesa">Pre-requisites:<a id="pre-requisites"></a></h2>
<ul>
<li><p>An Elastic Cloud account — <a href="https://cloud.elastic.co/">sign up now</a>, and become familiar with <a href="https://www.elastic.co/guide/en/observability/current/apm-open-telemetry.html">Elastic’s OpenTelemetry configuration</a></p></li>
<li><p>Have a LangChain app to instrument</p></li>
<li><p>Be familiar with using <a href="https://opentelemetry.io/docs/languages/python/libraries/">OpenTelemetry’s Python SDK</a> </p></li>
<li><p>An account on your favorite LLM, with API keys</p></li>
</ul>
<h2 id="overview">Overview</h2>
<p>In highlighting tracing I created a simple LangChain app that does the following:</p>
<ol>
<li><p>Takes customer input on the command line. (Queries)</p></li>
<li><p>Sends these to the Azure OpenAI LLM via a LangChain.</p></li>
<li><p>Chain tools are set to use the search with Tavily </p></li>
<li><p>The LLM uses the output which returns the relevant information to the user.</p></li>
</ol>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta85f2ad823158d9d/6a7f08acead8ec024fbaa6ad/LangChainAppCLI.png" alt="Chat Interaction" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt55c861f606e4c4f0/6a7f08af42a1170c6a95bd06/LangChainAppInAPM.png" alt="LangChainChat App in Elastic APM" /></p>
<p>As you can see Elastic Observability’s APM recognizes the LangChain App, and also shows the full trace (done with manual instrumentation):</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45bed91c1521dd6d/6a7f08b24c4bfb1a90ccd38b/LangChainAutoIntrument.png" alt="LangChainChat App in Elastic APM" /></p>
<p>As the above image shows:</p>
<ol>
<li>The user makes a query</li>
<li>Azure OpenAI is called, but it uses a tool (Tavily) to obtain some results</li>
<li>Azure OpenAI reviews and returns a summary to the end user</li>
</ol>
<p>The code was manually instrumented, but auto-instrument can also be used.</p>
<h2 id="opentelemetryconfigurationaidopentelemetryconfigurationa">OpenTelemetry Configuration<a id="opentelemetry-configuration"></a></h2>
<p>In using OpenTelemetry, we need to configure the SDK to generate traces and configure Elastic’s endpoint and authorization. Instructions can be found in <a href="https://opentelemetry.io/docs/zero-code/python/#setup">OpenTelemetry Auto-Instrumentation setup documentation</a>.</p>
<h3 id="opentelemetryenvironmentvariablesaidopentelemetryenvironmentvariablesa">OpenTelemetry Environment variables:<a id="opentelemetry-environment-variables"></a></h3>
<p>OpenTelemetry Environment variables for Elastic can be set as follows in linux (or in the code).</p>
<pre><code>OTEL_EXPORTER_OTLP_ENDPOINT=12345.apm.us-west-2.aws.cloud.es.io:443
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20ZZZZZZZ"
OTEL_RESOURCE_ATTRIBUTES="service.name=langchainChat,service.version=1.0,deployment.environment=production"
</code></pre>
<p>As you can see <code>OTEL_EXPORTER_OTLP_ENDPOINT</code> is set to Elastic, and the corresponding authorization header is also provided. These can be easily obtained from Elastic’s APM configuration screen under OpenTelemetry</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2273479708a89677/6a7f08b5b43770a9da4d6af5/LangChainAppOTelAPMsetup.png" alt="LangChainChat App in Elastic APM" /></p>
<p><strong>Note: No agent is needed, we simply send the OTLP trace messages directly to Elastic’s APM server.</strong> </p>
<h2 id="openllmetrylibraryaidopenllmetrylibrarya">OpenLLMetry Library:<a id="openllmetry-library"></a></h2>
<p>OpenTelemetry's auto-instrumentation can be extended to trace other frameworks via instrumentation packages.</p>
<p>First, you must install the following package: </p>
<p><code>pip install opentelemetry-instrumentation-langchain</code></p>
<p>This library was developed by OpenLLMetry. </p>
<p>Then you will need to add the following to the code.</p>
<pre><code>from opentelemetry.instrumentation.langchain import LangchainInstrumentor
LangchainInstrumentor().instrument()
</code></pre>
<h2 id="instrumentationaidinstrumentationa">Instrumentation<a id="instrumentation"></a></h2>
<p>Once the libraries are added, and the environment variables are set, you can use auto-instrumentation With auto-instrumentation, the following:</p>
<pre><code>opentelemetry-instrument python tavilyAzureApp.py
</code></pre>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45bed91c1521dd6d/6a7f08b24c4bfb1a90ccd38b/LangChainAutoIntrument.png" alt="LangChainChat App in Elastic APM" /></p>
<p>The OpenLLMetry library does pull out the flow correctly with minimal manual instrumentation except for adding the OpenLLMetry library.</p>
<ol>
<li><p>Takes customer input on the command line. (Queries)</p></li>
<li><p>Sends these to the Azure OpenAI LLM via a Lang chain.</p></li>
<li><p>Chain tools are set to use the search with Tavily </p></li>
<li><p>The LLM uses the output which returns the relevant information to the user.</p></li>
</ol>
<h3 id="manualinstrumentationaidmanualinstrumentationa">Manual-instrumentation<a id="manual-instrumentation"></a></h3>
<p>If you want to get more details out of the application, you will need to manually instrument. To get more traces follow my <a href="https://www.elastic.co/observability-labs/blog/manual-instrumentation-python-apps-opentelemetry">Python instrumentation guide</a>. This guide will walk you through setting up the necessary OpenTelemetry bits, Additionally, you can also look at the documentation in <a href="https://opentelemetry.io/docs/languages/python/instrumentation/">OTel for instrumenting in Python</a>.</p>
<p>Note that the env variables <code>OTEL_EXPORTER_OTLP_HEADERS</code> and <code>OTEL_EXPORTER_OTLP_ENDPOINT</code> are set as noted in the section above. You can also set up the <code>OTEL_RESOURCE_ATTRIBUTES</code>. </p>
<p>Once you follow the steps in either guide and initiate the tracer, you will have to essentially just add the span where you want to get more details. In the example below, only one line of code is added for span initialization. </p>
<p>Look at the placement of with <code>tracer.start_as_current_span("getting user query") as span:</code> below</p>
<pre><code># Creates a tracer from the global tracer provider
tracer = trace.get_tracer("newsQuery")

async def chat_interface():
    print("Welcome to the AI Chat Interface!")
    print("Type 'quit' to exit the chat.")

    with tracer.start_as_current_span("getting user query") as span:
        while True:
            user_input = input("\nYou: ").strip()

            if user_input.lower() == 'quit':
                print("Thank you for chatting. Goodbye!")
                break

            print("AI: Thinking...")
            try:
                result = await chain.ainvoke({"query": user_input})
                print(f"AI: {result.content}")
            except Exception as e:
                print(f"An error occurred: {str(e)}")


if __name__ == "__main__":
    asyncio.run(chat_interface())
</code></pre>
<p>As you can see, with manual instrumentation, we get the following trace:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt54624a5f8db253fa/6a7f08b82f00b2c4d8efe9f3/LangChainAppManualTrace.png" alt="LangChainChat App in Elastic APM" /></p>
<p>Which calls out when we enter our query function. <code>async def chat_interface()</code></p>
<h2 id="conclusionaidconclusiona">Conclusion<a id="conclusion"></a></h2>
<p>In this blog, we discussed the following:</p>
<ul>
<li><p>How to manually instrument LangChain with OpenTelemetry</p></li>
<li><p>How to properly initialize OpenTelemetry and add a custom span</p></li>
<li><p>How to easily set the OTLP ENDPOINT and OTLP HEADERS with Elastic without the need for a collector</p></li>
<li><p>See traces in Elastic Observability APM</p></li>
</ul>
<p>Hopefully, this provides an easy-to-understand walk-through of instrumenting LangChain with OpenTelemetry and how easy it is to send traces into Elastic.</p>
<p><strong>Additional resources for OpenTelemetry with Elastic:</strong></p>
<ul>
<li><p><a href="https://www.elastic.co/blog/opentelemetry-observability">Independence with OpenTelemetry on Elastic</a></p></li>
<li><p><a href="https://www.elastic.co/blog/implementing-kubernetes-observability-security-opentelemetry">Modern observability and security on Kubernetes with Elastic and OpenTelemetry</a></p></li>
<li><p><a href="https://www.elastic.co/blog/3-models-logging-opentelemetry-elastic">3 models for logging with OpenTelemetry and Elastic</a></p></li>
<li><p><a href="https://www.elastic.co/blog/adding-free-and-open-elastic-apm-as-part-of-your-elastic-observability-deployment">Adding free and open Elastic APM as part of your Elastic Observability deployment</a></p></li>
<li><p><a href="https://www.elastic.co/blog/monitor-openai-api-gpt-models-opentelemetry-elastic">Monitor OpenAI API and GPT models with OpenTelemetry and Elastic</a></p></li>
<li><p>Futureproof<a href="https://www.elastic.co/virtual-events/future-proof-your-observability-platform-with-opentelemetry-and-elastic"> your observability platform with OpenTelemetry and Elastic</a></p></li>
<li><p>Instrumentation resources:</p></li>
<li><p>Python: <a href="https://www.elastic.co/blog/auto-instrumentation-of-python-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-python-applications-opentelemetry">Manual instrumentation</a></p></li>
<li><p>Java: <a href="https://www.elastic.co/blog/auto-instrumentation-of-java-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-java-applications-opentelemetry">Manual instrumentation </a></p></li>
<li><p>Node.js: <a href="https://www.elastic.co/blog/auto-instrument-nodejs-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-nodejs-applications-opentelemetry">Manual instrumentation</a></p></li>
<li><p>.NET: <a href="https://www.elastic.co/blog/auto-instrumentation-of-net-applications-opentelemetry">Auto-instrumentation</a>, <a href="https://www.elastic.co/blog/manual-instrumentation-of-net-applications-opentelemetry">Manual instrumentation</a></p></li>
</ul>
<p>Also log into <a href="https://cloud.elastic.co">cloud.elastic.co</a> to try out Elastic with a free trial.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-langchain-tracing</link>
    <guid isPermaLink="false">elastic-opentelemetry-langchain-tracing</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[APM]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted3172bb9d8e783d/6a7f08bc9090b0b4ec84e853/LangChainBlogMainImage.png" length="0" type="image/png"/>
    <pubDate>Fri, 02 Aug 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Monitor dbt pipelines with Elastic Observability]]></title>
    <description><![CDATA[Learn how to set up a dbt monitoring system with Elastic that proactively alerts on data processing cost spikes, anomalies in rows per table, and data quality test failures]]></description>
    <content:encoded><![CDATA[<p>In the Data Analytics team within the Observability organization in Elastic, we use <a href="https://www.getdbt.com/product/what-is-dbt">dbt (dbt™, data build tool)</a> to execute our SQL data transformation pipelines. dbt is a SQL-first transformation workflow that lets teams quickly and collaboratively deploy analytics code. In particular, we use <a href="https://docs.getdbt.com/docs/core/installation-overview">dbt core</a>, the <a href="https://github.com/dbt-labs/dbt-core">open-source project</a>, where you can develop from the command line and run your dbt project.</p>
<p>Our data transformation pipelines run daily and process the data that feed our internal dashboards, reports, analyses, and Machine Learning (ML) models.</p>
<p>There have been incidents in the past when the pipelines have failed, the source tables contained wrong data or we have introduced a change into our SQL code that has caused data quality issues, and we only realized once we saw it in a weekly report that was showing an anomalous number of records. That’s why we have built a monitoring system that proactively alerts us about these types of incidents as soon as they happen and helps us with visualizations and analyses to understand their root cause, saving us several hours or days of manual investigations.</p>
<p>We have leveraged our own Observability Solution to help solve this challenge, monitoring the entire lifecycle of our dbt implementation. This setup enables us to track the behavior of our models and conduct data quality testing on the final tables. We export dbt process logs from run jobs and tests into Elasticsearch and utilize Kibana to create dashboards, set up alerts, and configure Machine Learning jobs to monitor and assess issues.</p>
<p>The following diagram shows our complete architecture. In a follow-up article, we’ll also cover how we observe our python data processing and ML model processes using OTEL and Elastic - stay tuned.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted013fc2f4985545/6a7f0df0e02fac34585d65ec/architecture.png" alt="1 - architecture" /></p>
<h2 id="whymonitordbtpipelineswithelastic">Why monitor dbt pipelines with Elastic?</h2>
<p>With every invocation, dbt generates and saves one or more JSON files called <a href="https://docs.getdbt.com/reference/artifacts/dbt-artifacts">artifacts</a> containing log data on the invocation results. <code>dbt run</code> and <code>dbt test</code> invocation logs are <a href="https://docs.getdbt.com/reference/artifacts/run-results-json">stored in the file <code>run_results.json</code></a>, as per the dbt documentation:</p>
<blockquote>
  <p>This file contains information about a completed invocation of dbt, including timing and status info for each node (model, test, etc) that was executed. In aggregate, many <code>run_results.json</code> can be combined to calculate average model runtime, test failure rates, the number of record changes captured by snapshots, etc.</p>
</blockquote>
<p>Monitoring <code>dbt run</code> invocation logs can help solve several issues, including tracking and alerting about table volumes, detecting excessive slot time from resource-intensive models, identifying cost spikes due to slot time or volume, and pinpointing slow execution times that may indicate scheduling issues. This system was crucial when we merged a PR with a change in our code that had an issue, producing a sudden drop in the number of daily rows in upstream Table A. By ingesting the <code>dbt run</code> logs into Elastic, our anomaly detection job quickly identified anomalies in the daily row counts for Table A and its downstream tables, B, C, and D. The Data Analytics team received an alert notification about the issue, allowing us to promptly troubleshoot, fix and backfill the tables before it affected the weekly dashboards and downstream ML models.</p>
<p>Monitoring <code>dbt test</code> invocation logs can also address several issues, such as identifying duplicates in tables, detecting unnoticed alterations in allowed values for specific fields through validation of all enum fields, and resolving various other data processing and quality concerns. With dashboards and alerts on data quality tests, we proactively identify issues like duplicate keys, unexpected category values, and increased nulls, ensuring data integrity. In our team, we had an issue where a change in one of our raw lookup tables produced duplicated rows in our user table, doubling the number of users reported. By ingesting the <code>dbt test</code> logs into Elastic, our rules detected that some duplicate tests had failed. The team received an alert notification about the issue, allowing us to troubleshoot it right away by finding the upstream table that was the root cause. These duplicates meant that downstream tables had to process 2x the amount of data, creating a spike in the bytes processed and slot time. The anomaly detection and alerts on the <code>dbt run</code> logs also helped us spot these spikes for individual tables and allowed us to quantify the impact on our billing.</p>
<p>Processing our dbt logs with Elastic and Kibana allows us to obtain real-time insights, helps us quickly troubleshoot potential issues, and keeps our data transformation processes running smoothly. We set up anomaly detection jobs and alerts in Kibana to monitor the number of rows processed by dbt, the slot time, and the results of the tests. This lets us catch real-time incidents, and by promptly identifying and fixing these issues, Elastic makes our data pipeline more resilient and our models more cost-effective, helping us stay on top of cost spikes or data quality issues.</p>
<p>We can also correlate this information with other events ingested into Elastic, for example using the <a href="https://www.elastic.co/guide/en/enterprise-search/current/connectors-github.html">Elastic Github connector</a>, we can correlate data quality test failures or other anomalies with code changes to find the root cause of the commit or PR that caused the issues. By ingesting application logs into Elastic, we can also analyze if these issues in our pipelines have affected downstream applications, increasing latency, throughput or error rates using APM. Ingesting billing, revenue data or web traffic, we could also see the impact in business metrics.</p>
<h2 id="howtoexportdbtinvocationlogstoelasticsearch">How to export dbt invocation logs to Elasticsearch</h2>
<p>We use the <a href="https://elasticsearch-py.readthedocs.io/en">Python Elasticsearch client</a> to send the dbt invocation logs to Elastic after we run our <code>dbt run</code> and <code>dbt test</code> processes daily in production. The setup just requires you to install the <a href="https://elasticsearch-py.readthedocs.io/en/v8.14.0/quickstart.html#installation">Elasticsearch Python client</a> and obtain your Elastic Cloud ID (go to https://cloud.elastic.co/deployments/, select your deployment and find the <code>Cloud ID</code>) and Elastic Cloud API Key <a href="https://elasticsearch-py.readthedocs.io/en/v8.14.0/quickstart.html#connecting">(following this guide)</a></p>
<p>This python helper function will index the results from your <code>run_results.json</code> file to the specified index. You just need to export the variables to the environment:</p>
<ul>
<li><code>RESULTS_FILE</code>: path to your <code>run_results.json</code> file</li>
<li><code>DBT_RUN_LOGS_INDEX</code>: the name you want to give to dbt run logs index in Elastic, e.g. <code>dbt_run_logs</code></li>
<li><code>DBT_TEST_LOGS_INDEX</code>: the name you want to give to the dbt test logs index in Elastic, e.g. <code>dbt_test_logs</code></li>
<li><code>ES_CLUSTER_CLOUD_ID</code></li>
<li><code>ES_CLUSTER_API_KEY</code></li>
</ul>
<p>Then call the function <code>log_dbt_es</code> from your python code or save this code as a python script and run it after executing your <code>dbt run</code> or <code>dbt test</code> commands:</p>
<pre><code>from elasticsearch import Elasticsearch, helpers
import os
import sys
import json

def log_dbt_es():
   RESULTS_FILE = os.environ["RESULTS_FILE"]
   DBT_RUN_LOGS_INDEX = os.environ["DBT_RUN_LOGS_INDEX"]
   DBT_TEST_LOGS_INDEX = os.environ["DBT_TEST_LOGS_INDEX"]
   es_cluster_cloud_id = os.environ["ES_CLUSTER_CLOUD_ID"]
   es_cluster_api_key = os.environ["ES_CLUSTER_API_KEY"]


   es_client = Elasticsearch(
       cloud_id=es_cluster_cloud_id,
       api_key=es_cluster_api_key,
       request_timeout=120,
   )


   if not os.path.exists(RESULTS_FILE):
       print(f"ERROR: {RESULTS_FILE} No dbt run results found.")
       sys.exit(1)


   with open(RESULTS_FILE, "r") as json_file:
       results = json.load(json_file)
       timestamp = results["metadata"]["generated_at"]
       metadata = results["metadata"]
       elapsed_time = results["elapsed_time"]
       args = results["args"]
       docs = []
       for result in results["results"]:
           if result["unique_id"].split(".")[0] == "test":
               result["_index"] = DBT_TEST_LOGS_INDEX
           else:
               result["_index"] = DBT_RUN_LOGS_INDEX
           result["@timestamp"] = timestamp
           result["metadata"] = metadata
           result["elapsed_time"] = elapsed_time
           result["args"] = args
           docs.append(result)
        = helpers.bulk(es_client, docs)
   return "Done"

# Call the function
log_dbt_es()
</code></pre>
<p>If you want to add/remove any other fields from <code>run_results.json</code>, you can modify the above function to do it.</p>
<p>Once the results are indexed, you can use Kibana to create Data Views for both indexes and start exploring them in Discover.</p>
<p>Go to Discover, click on the data view selector on the top left and “Create a data view”.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt86858215f11dfac8/6a7f0df24c4bfb0553ccd595/discover-create-dataview.png" alt="2 - discover create a data view" /></p>
<p>Now you can create a data view with your preferred name. Do this for both dbt run (<code>DBT_RUN_LOGS_INDEX</code> in your code) and dbt test (<code>DBT_TEST_LOGS_INDEX</code> in your code) indices:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta4284fecea8b3f0b/6a7f0df5e3a219e42799f51a/create-dataview.png" alt="3 - create a data view" /></p>
<p>Going back to Discover, you’ll be able to select the Data Views and explore the data.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd49dbf639fdef6b3/6a7f0df8448e4e20545c0781/discover-logs-explorer.png" alt="4 - discover logs explorer" /></p>
<h2 id="dbtrunalertsdashboardsandmljobs">dbt run alerts, dashboards and ML jobs</h2>
<p>The invocation of <a href="https://docs.getdbt.com/reference/commands/run"><code>dbt run</code></a> executes compiled SQL model files against the current database. <code>dbt run</code> invocation logs contain the <a href="https://docs.getdbt.com/reference/artifacts/run-results-json">following fields</a>:</p>
<ul>
<li><code>unique_id</code>: Unique model identifier</li>
<li><code>execution_time</code>: Total time spent executing this model run</li>
</ul>
<p>The logs also contain the following metrics about the job execution from the adapter:</p>
<ul>
<li><code>adapter_response.bytes_processed</code></li>
<li><code>adapter_response.bytes_billed</code></li>
<li><code>adapter_response.slot_ms</code></li>
<li><code>adapter_response.rows_affected</code></li>
</ul>
<p>We have used Kibana to set up <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-ad-run-jobs.html">Anomaly Detection jobs</a> on the above-mentioned metrics. You can configure a <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-anomaly-detection-job-types.html#multi-metric-jobs">multi-metric job</a> split by <code>unique_id</code> to be alerted when the sum of rows affected, slot time consumed, or bytes billed is anomalous per table. You can track one job per metric. If you have built a dashboard of the metrics per table, you can use <a href="https://www.elastic.co/guide/en/machine-learning/8.14/ml-jobs-from-lens.html">this shortcut</a> to create the Anomaly Detection job directly from the visualization. After the jobs are created and are running on incoming data, you can <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-ad-view-results.html">view the jobs</a> and add them to a dashboard using the three dots button in the anomaly timeline:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt15b36788c551c5df/6a7f0dfb73d9bd41df29db95/ml-job-add-to-dashboard.png" alt="5 - add ML job to dashboard" /></p>
<p>We have used the <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-configuring-alerts.html">ML job to set up alerts</a> that send us emails/slack messages when anomalies are detected. Alerts can be created directly from the Jobs (Machine Learning &gt; Anomaly Detection Jobs) page, by clicking on the three dots at the end of the ML job row:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06a4d48c8c462c07/6a7f0dfe96b5a6b37687b4cf/ml-job-create-alert.png" alt="6 - create alert from ML job" /></p>
<p>We also use <a href="https://www.elastic.co/guide/en/kibana/current/dashboard.html">Kibana dashboards</a> to visualize the anomaly detection job results and related metrics per table, to identify which tables consume most of our resources, to have visibility on their temporal evolution, and to measure aggregated metrics that can help us understand month over month changes.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt792d7ad77ab8b974/6a7f0e02b437704d0b4d6cf1/ml-job-dashboard.png" alt="7 - ML job in dashboard" />
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt995625988df0518b/6a7f0e041967ea82403307cd/dashboard-slot-time.png" alt="8 - dashboard slot time chart" />
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1bd2f5b6a0aab3fc/6a7f0e07fc63ab1c4364ccd9/dashboard-aggregated-metrics.png" alt="9 - dashboard aggregated metrics" /></p>
<h2 id="dbttestalertsanddashboards">dbt test alerts and dashboards</h2>
<p>You may already be familiar with <a href="https://docs.getdbt.com/docs/build/data-tests">tests in dbt</a>, but if you’re not, dbt data tests are assertions you make about your models. Using the command <a href="https://docs.getdbt.com/reference/commands/test"><code>dbt test</code></a>, dbt will tell you if each test in your project passes or fails. <a href="https://docs.getdbt.com/docs/build/data-tests#example">Here is an example of how to set them up</a>. In our team, we use out-of-the-box dbt tests (<code>unique</code>, <code>not_null</code>, <code>accepted_values</code>, and <code>relationships</code>) and the packages <a href="https://hub.getdbt.com/dbt-labs/dbt_utils/latest/">dbt_utils</a> and <a href="https://hub.getdbt.com/calogica/dbt_expectations/latest/">dbt_expectations</a> for some extra tests. When the command <code>dbt test</code> is run, it generates logs that are stored in <code>run_results.json</code>.</p>
<p>dbt test logs contain the <a href="https://docs.getdbt.com/reference/artifacts/run-results-json">following fields</a>:</p>
<ul>
<li><code>unique_id</code>: Unique test identifier, tests contain the “test” prefix in their unique identifier</li>
<li><code>status</code>: result of the test, <code>pass</code> or <code>fail</code></li>
<li><code>execution_time</code>: Total time spent executing this test</li>
<li><code>failures</code>: will be 0 if the test passes and 1 if the test fails</li>
<li><code>message</code>: If the test fails, reason why it failed</li>
</ul>
<p>The logs also contain the metrics about the job execution from the adapter.</p>
<p>We have set up alerts on document count (see <a href="https://www.elastic.co/guide/en/observability/8.14/custom-threshold-alert.html">guide</a>) that will send us an email / slack message when there are any failed tests. The rule for the alerts is set up on the dbt test Data View that we have created before, the query filtering on <code>status:fail</code> to obtain the logs for the tests that have failed, and the rule condition is document count bigger than 0.
Whenever there is a failure in any test in production, we get an alert with links to the alert details and dashboards to be able to troubleshoot them:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2ff19480a02d48c6/6a7f0e0a6693f8c2fe663fa5/email-alert.png" alt="10 - alert" /></p>
<p>We have also built a dashboard to visualize the tests run, tests failed, and their execution time and slot time to have a historical view of the test run:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5950dccdea7e0424/6a7f0e0d4c4bfb2ba0ccd5a1/dashboard-tests.png" alt="11 - dashboard dbt tests" /></p>
<h2 id="findingrootcauseswiththeaiassistant">Finding Root Causes with the AI Assistant</h2>
<p>The most effective way for us to analyze these multiple sources of information is using the AI Assistant to help us troubleshoot the incidents. In our case, we got an alert about a test failure, and we used the AI Assistant to give us context on what happened. Then we asked if there were any downstream consequences, and the AI Assistant interpreted the results of the Anomaly Detection job, which indicated a spike in slot time for one of our downstream tables and the increase of the slot time vs. the baseline. Then, we asked for the root cause, and the AI Assistant was able to find and provide us a link to a PR from our Github changelog that matched the start of the incident and was the most probable cause.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte69b3d0db1c5f71a/6a7f0e10227b1c608e59865a/ai-assistant.png" alt="12 - ai assistant troubleshoot" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>As a Data Analytics team, we are responsible for guaranteeing that the tables, charts, models, reports, and dashboards we provide to stakeholders are accurate and contain the right sources of information. As teams grow, the number of models we own becomes larger and more interconnected, and it isn’t easy to guarantee that everything is running smoothly and providing accurate results. Having a monitoring system that proactively alerts us on cost spikes, anomalies in row counts, or data quality test failures is like having a trusted companion that will alert you in advance if something goes wrong and help you get to the root cause of the issue.</p>
<p>dbt invocation logs are a crucial source of information about the status of our data pipelines, and Elastic is the perfect tool to extract the maximum potential out of them. Use this blog post as a starting point for utilizing your dbt logs to help your team achieve greater reliability and peace of mind, allowing them to focus on more strategic tasks rather than worrying about potential data issues.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/monitor-dbt-pipelines-with-elastic-observability</link>
    <guid isPermaLink="false">monitor-dbt-pipelines-with-elastic-observability</guid>
    <category><![CDATA[Data Management]]></category>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Almudena Sanz Olivé,Tamara Dancheva]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7b9a1fc65967a172/6a7f0e13c2e914c297016c54/monitoring-dbt-with-elastic.png" length="0" type="image/png"/>
    <pubDate>Fri, 26 Jul 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[NGNIX log analytics with GenAI in Elastic]]></title>
    <description><![CDATA[Elastic has a set of embedded capabilities such as a GenAI RAG-based AI Assistant and a machine learning platform as part of the product baseline. These make analyzing the vast number of logs you get from NGINX easier.]]></description>
    <content:encoded><![CDATA[<p>Elastic Observability provides a full observability solution, supporting metrics, traces, and logs for applications and infrastructure. NGINX, which is highly used for web serving, load balancing, http caching, and reverse proxy, is the key to many applications and outputs a large volume of logs. NGINX’s access logs, which detail all requests made to the NGINX server, and error logs which record server-related issues and problems are key to managing and analyzing NGINX issues along with understanding what is happening to your application. </p>
<p>In managing NGINX Elastic provides several capabilities:</p>
<ol>
<li><p>Easy ingest, parsing, and out-of-the-box dashboards. Check out the simple how-to in our <a href="https://www.elastic.co/guide/en/fleet/current/example-standalone-monitor-nginx.html">docs</a>. Based on logs, these dashboards show several items over time, response codes, errors, top pages, data volume, browsers used, active connections, drop rates, and much more.</p></li>
<li><p>Out-of-the-box ML-based anomaly detection jobs for your NGINX logs. These jobs help pinpoint anomalies against request rates, IP address request rates, URL access, status codes, and visitor rate anomalies.</p></li>
<li><p>ES|QL which helps work through logs and build out charts during analysis.</p></li>
<li><p>Elastic’s GenAI Assistant provides a simple natural language interface that helps analyze all the logs and can pull out issues from ML jobs and even create dashboards. The Elastic AI Assistant also automatically uses ES|QL.</p></li>
<li><p>NGINX SLOs - Finally Elastic provides the ability to define and monitor SLOs for your NGINX logs. While most SLOs are metrics-based, Elastic allows you to create logs-based SLOs. We detailed this in a previous <a href="https://www.elastic.co/observability-labs/blog/service-level-objectives-slos-logs-metrics">blog</a>.</p></li>
</ol>
<p>NGINX logs are another example of why logs are great.  Logging is an important part of Observability, for which we generally think of metrics and tracing. However, the amount of logs an application and the underlying infrastructure output can be significantly daunting and NGINX is usually the starting point for most analyses. </p>
<p>In today’s blog, we’ll cover how the out-of-the-box ML-based anomaly detection jobs can help RCA, and how Elastic’s GenAI Assistant helps easily work through logs to pinpoint issues in minutes. </p>
<h2 id="prerequisitesandconfigaidprerequisitesandconfiga">Prerequisites and config<a id="prerequisites-and-config"></a></h2>
<p>If you plan on following this blog, here are some of the components and details we used to set up this demonstration:</p>
<ul>
<li><p>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</p></li>
<li><p>Bring up an <a href="https://docs.nginx.com/nginx/admin-guide/web-server/">NGINX server</a> on a host. OR run an application with NGINX as a front end and drive traffic.</p></li>
<li><p>Install the NGINX integration and assets and review the dashboards as noted in the <a href="https://www.elastic.co/guide/en/fleet/current/example-standalone-monitor-nginx.html">docs</a>.</p></li>
<li><p>Ensure you have an <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-settings.html">ML node configured</a> in your Elastic stack</p></li>
<li><p>To use the AI Assistant you will need a trial or upgrade to Platinum.</p></li>
</ul>
<p>In our scenario, we use data from 3 months from our Elastic environment to help highlight the features. Hence you might need to run your application with traffic for a specific time frame to follow along.</p>
<h2 id="analyzingtheissueswithaiassistantaidanalyzingtheissueswithaiassistanta">Analyzing the issues with AI Assistant<a id="analyzing-the-issues-with-ai-assistant"></a></h2>
<p>As detailed in a previous <a href="https://www.elastic.co/observability-labs/blog/service-level-objectives-slos-logs-metrics">blog</a>, you can get alerted on issues via SLO monitoring against NGINX logs. Let’s assume you have an SLO based on status codes as we outlined in the previous <a href="https://www.elastic.co/observability-labs/blog/service-level-objectives-slos-logs-metrics">blog</a>. You can immediately analyze the issue via the AI Assistant. Because it's a chat interface we simply open the AI Assistant and work through some simple analysis: (See Animated GIF for a demo)</p>
<h3 id="aiassistantanalysisaidaiassistantanalysisa">AI Assistant analysis:<a id="ai-assistant-analysis"></a></h3>
<ul>
<li><p><strong><em>Using lens graph all http response status codes &lt; 400 and &gt; =400 from filebeat-nginx-elasticco-anon-2017. http.response.status.code is not an integer</em></strong> <em>-</em> We wanted to simply understand the amount of requests resulting in status code &gt;= 400 and graph the results. We see that 15% of the requests were not successful, hence an SLO alert being triggered.</p></li>
<li><p><strong>Which ip address (field source.adress) has the highest number of http.response.status.code &gt;= 400 from filebeat-nginx-elasticco-anon-2017. http.response.status.code is not an integer</strong>  - We were curious is there was a specific IP address not having successful requests. 72.57.0.53, with a count of 25,227 occurrences is daily high but not the ensure 2 failed requests.</p></li>
<li><p><strong><em>What country (source.geo.country_iso_code) is source.address=72.57.0.53 coming from. Use filebeat-nginx-elasticco-anon-2017.</em></strong> - Again we were curious if this came from a specific country. And the IP address 72.57.0.53 is coming from the country with the ISO code IN, which corresponds to India. Nothing out of the ordinary.</p></li>
<li><p><strong><em>Did source.address=72.57.0.53 have any (http.response.status.code &lt; 400) from filebeat-nginx-elasticco-anon-2017. http.response.status.code is not an integer -</em></strong>  Oddly the IP address in question only had 4000+ successful responses. Meaning its not malicious, and points to something else.</p></li>
<li><p><strong><em>What are the different status codes (http.response.status.code&gt;=400), from source.address=72.57.0.53. Use filebeat-nginx-elasticco-anon-2017. http.response.status.code is not an integer. Provide counts for each status code -</em></strong> We are curious whether or not we see any 502, which there were none, but most of the failures were 404. </p></li>
<li><p><strong><em>What are the different status codes (http.response.status.code&gt;=400). Use filebeat-nginx-elasticco-anon-2017. http.response.status.code is not an integer. Provide counts for each status code</em></strong> - Regardless of a specific address, what is the largest number of status code occurrences &gt; 400. This also points to 404. </p></li>
<li><p><strong><em>What does a high 404 count from a specific IP address mean from NGINX logs?</em></strong> - Asking this question, we need to understand the potential causes of this from our application. From the answers, we can rule out security probing and web scraping, as we validated that a specific address 72.57.0.53 has a low non-success request status code. It also rules out User error. Hence this points potentially to Broken Links or Missing Resources.</p></li>
</ul>
<h3 id="watchtheflowaidwatchtheflowa">Watch the flow:<a id="watch-the-flow"></a></h3>
<div>
    
</div>
<h3 id="potentialissue">Potential issue:</h3>
<p>It seems that we potentially have an issue with the backend serving specific answers or having issues with resources (database, or broken links). This is cursing the higher-than-normal non-successful status codes&gt;=400.</p>
<h3 id="keyhighlightsfromaiassistant">Key highlights from AI Assistant:</h3>
<p>As you watched this video you will notice a few things:</p>
<ol>
<li><p>We analyzed millions of logs in a matter of minutes using a set of simple natural language queries. </p></li>
<li><p>We didn’t need to know any special query language. The AI Assistant used Elastic’s ES|QL but can similarly use KQL also. </p></li>
<li><p>The AI Assistant easily builds out graphs</p></li>
<li><p>The AI Assistant is accessing and using internal information stored in Elastic’s indices. Vs a simple “google foo” based AI Assistant. This is enabled through RAG, and the AI Assistant can also bring up known issues in github, runbooks, and other useful internal information.</p></li>
</ol>
<p>Check out the following <a href="https://www.elastic.co/observability-labs/blog/elastic-rag-ai-assistant-application-issues-llm-github">blog</a> on how the AI Assistant uses RAG to retrieve internal information. Specifically using github and runbooks.</p>
<h2 id="locatinganomalieswithml">Locating anomalies with ML</h2>
<p>While using the AI Assistant is great for analyzing information, another important aspect of NGINX log management is to ensure you can manage log spikes and anomalies. Elastic has a machine learning platform that allows you to develop jobs to analyze specific metrics or multiple metrics to look for anomalies.When using NGINX, there are several <a href="https://www.elastic.co/guide/en/machine-learning/current/ootb-ml-jobs-nginx.html">out-of-the-box anomaly detection jobs</a>. These work specifically on NGINX access logs.</p>
<ul>
<li><p>Low_request_rate_nginx - Detect low request rates</p></li>
<li><p>Source_ip_request_rate_nginx - Detect unusual source IPs - high request rates</p></li>
<li><p>Source_ip_url_count_nginx - Detect unusual source IPs - high distinct count of URLs</p></li>
<li><p>Status_code_rate_nginx - Detect unusual status code rates</p></li>
<li><p>Visitor_rate_nginx - Detect unusual visitor rates</p></li>
</ul>
<p>Being right out of the box, lets look at the job - Status_code_rate_nginx, which is related to our previous analysis.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt30ec8d10aaf46a17/6a7f0e9073d9bda62429dbcb/nginx-ml-log-analytics.png" alt="NGINX ML Log Analytics" /></p>
<p>With a few simple clicks we immediately get an analysis showing a specific IP address - 72.57.0.53, having higher than normal non-successful requests. Oddly we also found this is using the AI Assistant.</p>
<p>We can take this further with conversations with the AI Assistant, look at the logs, and/or even look at the other ML anomaly jobs.</p>
<h2 id="conclusionaidconclusiona">Conclusion:<a id="conclusion"></a></h2>
<p>You’ve now seen how easily Elastic’s RAG-based AI Assistant can help analyze NGINX logs without even the need to know query syntax, understand where the data is, and understand even the fields. Additionally, you’ve also seen how we can alert you when a potential issue or degradation in service (SLO). </p>
<p>Check out other resources on NGINX logs:</p>
<p><a href="https://www.elastic.co/guide/en/machine-learning/current/ootb-ml-jobs-nginx.html">Out-of-the-box anomaly detection jobs for NGINX</a></p>
<p><a href="https://www.elastic.co/guide/en/fleet/current/example-standalone-monitor-nginx.html">Using the NGINX integration to ingest and analyze NGINX Logs</a></p>
<p><a href="https://www.elastic.co/observability-labs/blog/service-level-objectives-slos-logs-metrics">NGINX Logs based SLOs in Elastic</a></p>
<p><a href="https://www.elastic.co/observability-labs/blog/elastic-rag-ai-assistant-application-issues-llm-github">Using GitHub issues, runbooks, and other internal information for RCAs with Elastic’s RAG based AI Assistant</a></p>
<h2 id="tryitoutaidtryitouta">Try it out<a id="try-it-out"></a></h2>
<p>Existing Elastic Cloud customers can access many of these features directly from the <a href="https://cloud.elastic.co/">Elastic Cloud console</a>. Not taking advantage of Elastic on the cloud? <a href="https://www.elastic.co/cloud/cloud-trial-overview">Start a free trial</a>.</p>
<p>All of this is also possible in your environment. <a href="https://www.elastic.co/observability/universal-profiling">Learn how to get started today</a>.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
<p><em>In this blog post, we may have used or referred to third party generative AI tools, which are owned and operated by their respective owners. Elastic does not have any control over the third party tools and we have no responsibility or liability for their content, operation or use, nor for any loss or damage that may arise from your use of such tools. Please exercise caution when using AI tools with personal, sensitive or confidential information. Any data you submit may be used for AI training or other purposes. There is no guarantee that information you provide will be kept secure or confidential. You should familiarize yourself with the privacy practices and terms of use of any generative AI tools prior to use.</em></p>
<p><em>Elastic, Elasticsearch, ESRE, Elasticsearch Relevance Engine and associated marks are trademarks, logos or registered trademarks of Elasticsearch N.V. in the United States and other countries. All other company and product names are trademarks, logos or registered trademarks of their respective owners.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/nginx-log-analytics-with-genai-elastic</link>
    <guid isPermaLink="false">nginx-log-analytics-with-genai-elastic</guid>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd89bddfe4a0532b5/6a7f0e936c6eaca022f141b7/blog-thumb-observability-pattern-color.png" length="0" type="image/png"/>
    <pubDate>Fri, 05 Jul 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[AWS VPC Flow log analysis with GenAI in Elastic]]></title>
    <description><![CDATA[Elastic has a set of embedded capabilities such as a GenAI RAG-based AI Assistant and a machine learning platform as part of the product baseline. These make analyzing the vast number of logs you get from AWS VPC Flows easier.]]></description>
    <content:encoded><![CDATA[<p>Elastic Observability provides a full observability solution, by supporting metrics, traces and logs for applications and infrastructure. In managing AWS deployments, VPC flow logs are critical in managing performance, network visibility, security, compliance, and overall management of your AWS environment. Several examples of :</p>
<ol>
<li><p>Where traffic is coming in from and going out to from the deployment, and within the deployment. This helps identify unusual or unauthorized communications</p></li>
<li><p>Traffic volumes detecting spikes or drops which could indicate service issues in production or an increase in customer traffic</p></li>
<li><p>Latency and Performance bottlenecks - with VPC Flow logs, you can look at latency for a flow (in and outflows), and understand patterns</p></li>
<li><p>Accepted and rejected traffic helps determine where potential security threats and misconfigurations lie. </p></li>
</ol>
<p>AWS VPC Logs is a great example of how logs are great. Logging is an important part of Observability, for which we generally think of metrics and tracing. However, the amount of logs an application and the underlying infrastructure output can be significantly daunting with VPC Logs. However, it also provides a significant amount of insight.</p>
<p>Before we proceed, it is important to understand what Elastic provides in managing AWS and VPC Flow logs:</p>
<ol>
<li><p>A full set of integrations to manage VPC Flows and the <a href="https://www.elastic.co/observability-labs/blog/aws-service-metrics-monitor-observability-easy">entire end-to-end deployment on AWS</a>. </p></li>
<li><p>Elastic has a simple-to-use <a href="https://www.elastic.co/observability-labs/blog/aws-kinesis-data-firehose-observability-analytics">AWS Firehose integration</a>. </p></li>
<li><p>Elastic’s tools such as <a href="https://www.elastic.co/observability-labs/blog/vpc-flow-logs-monitoring-analytics-observability">Discover, spike analysis,  and anomaly detection help provide you with better insights and analysis</a>.</p></li>
<li><p>And a set of simple <a href="https://www.elastic.co/guide/en/observability/current/monitor-amazon-vpc-flow-logs.html#aws-firehose-dashboard">Out-of-the-box dashboards</a></p></li>
</ol>
<p>In today’s blog, we’ll cover how Elastics’ other features can support analyzing and RCA for potential VPC flow logs even more easily. Specifically, we will focus on managing the number of rejects, as this helps ensure there weren’t any unauthorized or unusual activities:</p>
<ol>
<li><p>Set up an easy-to-use SLO (newly released) to detect when things are potentially degrading</p></li>
<li><p>Create an ML job to analyze different fields of the VPC Flow log</p></li>
<li><p>Using our newly released RAG-based AI Assistant to help analyze the logs without needing to know Elastic’s query language nor how to even graph on Elastic</p></li>
<li><p>ES|QL will help understand and analyze add latency for patterns.</p></li>
</ol>
<p>In subsequent blogs, we will use AI Assistant and ESQL to show how to get other insights beyond just REJECT/ACCEPT from VPC Flow log.</p>
<h2 id="prerequisitesandconfig">Prerequisites and config</h2>
<p>If you plan on following this blog, here are some of the components and details we used to set up this demonstration:</p>
<ul>
<li><p>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</p></li>
<li><p>Follow the steps in the following blog to get <a href="https://github.com/aws-samples/aws-three-tier-web-architecture-workshop">AWS’s three-tier app</a> installed instructed in git, and bring in the <a href="https://www.elastic.co/observability-labs/blog/aws-kinesis-data-firehose-observability-analytics">AWS VPC Flow logs</a>.</p></li>
<li><p>Ensure you have an <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-settings.html">ML node configured</a> in your Elastic stack</p></li>
<li><p>To use the AI Assistant you will need a trial or upgrade to Platinum.</p></li>
</ul>
<h2 id="slowithvpcflowlogs">SLO with VPC Flow Logs</h2>
<p>Elastic’s SLO capability is based directly on the Google SRE Handbook. All the definitions and semantics are utilized as described in Google’s SRE handbook. Hence users can perform the following on SLOs in Elastic:</p>
<ul>
<li>Define an SLO on Logs not just metrics - Users can use KQL (log-based query), service availability, service latency, custom metric, histogram metric, or a timeslice metric.</li>
<li>Define SLO, SLI, Error budget and burn rates. Users can also use occurrence versus time slice-based budgeting. </li>
<li>Manage, with dashboards, all the SLOs in a singular location.</li>
<li>Trigger alerts from the defined SLO, whether the SLI is off, the burn rate is used up, or the error rate is X.</li>
</ul>
<p>Setting up an SLO for VPC is easy. You simply create a query you want to trigger off. In our case, we look for all the good events where <em>aws.vpcflow.action=ACCEPT</em> and we define the target at 85%. </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd21d06910b861cd4/6a7f037f33fa8a81e0202287/VPCFlowSLOsetup.png" alt="Setting up SLO for VPC FLow log" /></p>
<p>As the following example shows, over the last 7 days, we have exceeded our budget by 43%. Additionally, we have not complied for the last 7 days.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdce0dcb24898fd24/6a7f038296b5a69c6487b03d/VPCFlowSLOMiss.png" alt="VPC Flow Reject SLO" /></p>
<h2 id="analyzingtheslowithaiassistant">Analyzing the SLO with AI Assistant</h2>
<p>Now that we see that there is an issue with the VPC Flows, we immediately work with the AI Assistant to start analyzing the SLO. Because it's a chat interface we simply open the AI Assistant and work through some simple analysis: (See Animated GIF for a demo below)</p>
<h3 id="aiassistantanalysis">AI Assistant analysis:</h3>
<ul>
<li><p><strong>what were the top 3 source.address that had <em>aws.vpcflow.action=REJECT</em> over the last 7 days, which is causing this SLO issue?</strong> - We wanted to simply see what could be causing the loss in error budget. Were there any particular source.addresses causing a heavy reject rate.</p></li>
<li><p>The answer: A table with the highest count = 42670 and <em>source.address = 79.110.62.185</em></p></li>
<li><p>There is one singular <em>source.address</em> that is causing the loss in SLO. </p></li>
<li><p><strong>What is the largest number of  <em>aws.vpcflow.action=REJECT</em> in a 30 min time frame for the last 3 days where the <em>source.address=79.110.62.185</em>?</strong> - After understanding that a specific source.address is causing the loss in SLO, we want to understand the averages. </p></li>
<li><p>**The answer: ** "The largest number of <em>aws.vpcflow.action=REJECT</em> in a 30-minute time frame for the last 3 days where the <em>source.address</em> is 79.110.62.185 is 229. This occurred on 2024-06-01T04:00:00.000Z.”</p></li>
<li><p>It means there must be a low REJECT rate but fairly consistent vs spiky over the last 7 days. </p></li>
<li><p><strong>for the logs with <em>source.address</em>="79.110.62.185" was there any country code of <em>source.geo.country_iso_code</em> field present. If yes what is the value</strong> - Given the last question showed a low REJECT rate, it only means that this was fairly consistent vs spiky over the last 7 days.</p></li>
<li><p><strong>The answer:</strong> Yes, there is a country code present in the <em>source.geo.country_iso_code</em> field for logs with <em>source.address</em>="79.110.62.185". The value is BG (Bulgaria).</p></li>
<li><p><strong>Is there a specific destination.address where <em>source.address=79.110.62.185</em> is getting a <em>aws.vpcflow.action=REJECT</em>. Give me both the destination.address and the number of REJECTs for that destination.address?</strong></p></li>
<li><p><strong>The answer:</strong> destination.address of 10.0.0.27 is giving a reject number of 53433 in this time frame.</p></li>
<li><p><strong>Graph the number of REJECT vs ACCEPT for <em>source.address</em>="79.110.62.185" over the last 7 days. The graph is on a daily basis in a singular graph</strong> - We asked this question to see what the comparison is between ACCEPT and REJECT. </p></li>
<li><p><strong>The answer:</strong> See the animated GIF to see that the generated graph is fairly stable</p></li>
<li><p><strong>Were there any source.address that had a spike, high reject rate in. a 30min period over the 30 days?</strong> - We wanted to see if there was any other spike </p></li>
<li><p><strong>The answer</strong> - Yes, there was a source.address that had a spike in high reject rates in a 30-minute period over the last 30 days. <em>source.address</em>: 185.244.212.67, Reject Count: 8975, Time Period: 2024-05-22T03:00:00.000Z</p></li>
</ul>
<hr />
<h3 id="watchtheflow">Watch the flow</h3>
<div>
    
</div>
<h3 id="potentialissue">Potential issue:</h3>
<p>he server handling requests from source <strong><em>79.110.62.185</em></strong> is potentially having an issue.</p>
<p>Again using logs, we essentially asked the AI Assistant to give the <em>eni</em> ids where the internal ip address was 10.0.0.27</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2ec3d25d096c3357/6a7f038605b7b5b00a18b519/VPCFlow-findingwebserver.png" alt="Finding the issue - webserver" /></p>
<p>From our AWS console, we know that this is the webserver. Further analysis in Elastic, and with the developers we realized there is a new version that was installed recently causing a problem with connections.</p>
<h2 id="locatinganomalieswithml">Locating anomalies with ML</h2>
<p>While using the AI Assistant is great for analyzing information, another important aspect of VPC flow management is to ensure you can manage log spikes and anomalies. Elastic has a machine learning platform that allows you to develop jobs to analyze specific metrics or multiple metrics to look for anomalies.</p>
<p>VPC Flow logs come with a large amount of information. The full set of fields is listed in <a href="https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-logs-basics">AWS docs</a>. We will use a specific subset to help detect anomalies.</p>
<p>We were setting up anomalies for aws.vpcflow.action=REJECT, which requires us to use multimetric anomaly detection in Elastic.</p>
<p>The config we used utilizes:</p>
<p>Detectors:</p>
<ul>
<li><p>destination.address</p></li>
<li><p>destination.port</p></li>
</ul>
<p>Influencers:</p>
<ul>
<li><p>source.address</p></li>
<li><p>aws.vpcflow.action</p></li>
<li><p>destination.geo.region_iso_code</p></li>
</ul>
<p>The way we set this up will help us understand if there is a large spike in REJECT/ACCEPT against <em>destination.address</em> values from a specific <em>source.address</em> and/or <em>destination.geo.region_iso_code</em> location.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta48754a0753271b1/6a7f03896c6eac6468f13cdd/VPCFlowanomalysetup.png" alt="Anomaly detection job config" /></p>
<p>The job once run reveals something interesting:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9f3aee82193c8e44/6a7f038c05b7b54b1718b51d/VPCFlowAnomalyDetection.png" alt="Anomaly detected" /></p>
<p>Notice that <em>source.address</em> 185.244.212.67 has had a high REJECT rate in the last 30 days. </p>
<p>Notice where we found this before? In the AI Assistant!!!!!</p>
<p>While we can run the AI Assistant and find this sort of anomaly, the ML job can be setup to run continuously and alert us on such spikes. This will help us understand if there are any issues with the webserver like we found above or even potential security attacks.</p>
<h2 id="conclusion">Conclusion:</h2>
<p>You’ve now seen how easily Elastic’s RAG-based AI Assistant can help analyze VPC Flows without even the need to know query syntax, understand where the data is, and understand even the fields. Additionally, you’ve also seen how we can alert you when a potential issue or degradation in service (SLO). Check out our other blogs on AWS VPC Flow analysis in Elastic:</p>
<ol>
<li><p>A full set of integrations to manage VPC Flows and the <a href="https://www.elastic.co/observability-labs/blog/aws-service-metrics-monitor-observability-easy">entire end-to-end deployment on AWS</a>. </p></li>
<li><p>Elastic has a simple-to-use <a href="https://www.elastic.co/observability-labs/blog/aws-kinesis-data-firehose-observability-analytics">AWS Firehose integration</a>. </p></li>
<li><p>Elastic’s tools such as <a href="https://www.elastic.co/observability-labs/blog/vpc-flow-logs-monitoring-analytics-observability">Discover, spike analysis,  and anomaly detection help provide you with better insights and analysis</a>.</p></li>
<li><p>And a set of simple <a href="https://www.elastic.co/guide/en/observability/current/monitor-amazon-vpc-flow-logs.html#aws-firehose-dashboard">Out-of-the-box dashboards</a></p></li>
</ol>
<h2 id="tryitout">Try it out</h2>
<p>Existing Elastic Cloud customers can access many of these features directly from the <a href="https://cloud.elastic.co/">Elastic Cloud console</a>. Not taking advantage of Elastic on the cloud? <a href="https://www.elastic.co/cloud/cloud-trial-overview">Start a free trial</a>.</p>
<p>All of this is also possible in your environment. <a href="https://www.elastic.co/observability/universal-profiling">Learn how to get started today</a>.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
<p><em>In this blog post, we may have used or referred to third party generative AI tools, which are owned and operated by their respective owners. Elastic does not have any control over the third party tools and we have no responsibility or liability for their content, operation or use, nor for any loss or damage that may arise from your use of such tools. Please exercise caution when using AI tools with personal, sensitive or confidential information. Any data you submit may be used for AI training or other purposes. There is no guarantee that information you provide will be kept secure or confidential. You should familiarize yourself with the privacy practices and terms of use of any generative AI tools prior to use.</em></p>
<p><em>Elastic, Elasticsearch, ESRE, Elasticsearch Relevance Engine and associated marks are trademarks, logos or registered trademarks of Elasticsearch N.V. in the United States and other countries. All other company and product names are trademarks, logos or registered trademarks of their respective owners.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/aws-vpc-flow-log-analysis-with-genai-elastic</link>
    <guid isPermaLink="false">aws-vpc-flow-log-analysis-with-genai-elastic</guid>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5265effb8d313486/6a7f038fde23157404fd7786/21-cubes.jpeg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 07 Jun 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Enhancing SRE troubleshooting with the AI Assistant for Observability and your organization's runbooks]]></title>
    <description><![CDATA[Empower your SRE team with this guide to enriching Elastic's AI Assistant Knowledge Base with your organization's internal observability information for enhanced alert remediation and incident management.]]></description>
    <content:encoded><![CDATA[<p>The <a href="https://www.elastic.co/blog/context-aware-insights-elastic-ai-assistant-observability">Observability AI Assistant</a> helps users explore and analyze observability data using a natural language interface, by leveraging automatic function calling to request, analyze, and visualize your data to transform it into actionable observability. The Assistant can also set up a Knowledge Base, powered by <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html">Elastic Learned Sparse EncodeR</a> (ELSER) to provide additional context and recommendations from private data, alongside the large language models (LLMs) using RAG (Retrieval Augmented Generation). Elastic’s Stack — as a vector database with out-of-the-box semantic search and connectors to LLM integrations and the Observability solution — is the perfect toolkit to extract the maximum value of combining your company's unique observability knowledge with generative AI.</p>
<h2 id="enhancedtroubleshootingforsres">Enhanced troubleshooting for SREs</h2>
<p>Site reliability engineers (SRE) in large organizations often face challenges in locating necessary information for troubleshooting alerts, monitoring systems, or deriving insights due to scattered and potentially outdated resources. This issue is particularly significant for less experienced SREs who may require assistance even with the presence of a runbook. Recurring incidents pose another problem, as the on-call individual may lack knowledge about previous resolutions and subsequent steps. Mature SRE teams often invest considerable time in system improvements to minimize "fire-fighting," utilizing extensive automation and documentation to support on-call personnel.</p>
<p>Elastic® addresses these challenges by combining generative AI models with relevant search results from your internal data using RAG. The <a href="https://www.elastic.co/guide/en/observability/current/obs-ai-assistant.html">Observability AI Assistant's internal Knowledge Base</a>, powered by our semantic search retrieval model <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html">ELSER</a>, can recall information at any point during a conversation, providing RAG responses based on internal knowledge.</p>
<p>This Knowledge Base can be enriched with your organization's information, such as runbooks, GitHub issues, internal documentation, and Slack messages, allowing the AI Assistant to provide specific assistance. The Assistant can also document and store specific information from an ongoing conversation with an SRE while troubleshooting issues, effectively creating runbooks for future reference. Furthermore, the Assistant can generate summaries of incidents, system status, runbooks, post-mortems, or public announcements.</p>
<p>This ability to retrieve, summarize, and present contextually relevant information is a game-changer for SRE teams, transforming the work from chasing documents and data to an intuitive, contextually sensitive user experience.The Knowledge Base (see <a href="https://www.elastic.co/guide/en/observability/current/obs-ai-assistant.html#obs-ai-requirements">requirements</a>) serves as a central repository of Observability knowledge, breaking documentation silos and integrating tribal knowledge, making this information accessible to SREs enhanced with the power of LLMs.</p>
<p>Your LLM provider may collect query telemetry when using the AI Assistant. If your data is confidential or has sensitive details, we recommend you verify the data treatment policy of the LLM connector you provided to the AI Assistant.</p>
<p>In this blog post, we will cover different ways to enrich your Knowledge Base (KB) with internal information. We will focus on a specific alert, indicating that there was an increase in logs with “502 Bad Gateway” errors that has surpassed the alert’s threshold.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt432418d2871ff281/6a7f1b0873d9bd18b729df69/elastic-blog-1.png" alt="1 - threshold breached" /></p>
<h2 id="howtotroubleshootanalertwiththeknowledgebase">How to troubleshoot an alert with the Knowledge Base</h2>
<p>Before the KB has been enriched with internal information, when the SRE asks the AI Assistant about how to troubleshoot an alert, the response from the LLM will be based on the data it learned during training; however, the LLM is not able to answer questions related to private, recent, or emerging knowledge. In this case, when asking for the steps to troubleshoot the alert, the response will be based on generic information.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf2577ea1ce6b71b1/6a7f1b0b05b7b519c318bd51/elastic-blog-2.png" alt="2 - troubleshooting steps" /></p>
<p>However, once the KB has been enriched with your runbooks, when your team receives a new alert on “502 Bad Gateway” Errors, they can use AI Assistant to access the internal knowledge to troubleshoot it, using semantic search to find the appropriate runbook in the Knowledge Base.</p>
<p>In this blog, we will cover different ways to add internal information on how to troubleshoot an alert to the Knowledge Base:</p>
<ol>
<li><p>Ask the assistant to remember the content of an existing runbook.</p></li>
<li><p>Ask the Assistant to summarize and store in the Knowledge Base the steps taken during a conversation and store it as a runbook.</p></li>
<li><p>Import your runbooks from GitHub or another external source to the Knowledge Base using our Connector and APIs.</p></li>
</ol>
<p>After the runbooks have been added to the KB, the AI Assistant is now able to recall the internal and specific information in the runbooks. By leveraging the retrieved information, the LLM could provide more accurate and relevant recommendations for troubleshooting the alert. This could include suggesting potential causes for the alert, steps to resolve the issue, preventative measures for future incidents, or asking the assistant to help execute the steps mentioned in the runbook using functions. With more accurate and relevant information at hand, the SRE could potentially resolve the alert more quickly, reducing downtime and improving service reliability.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte9f381e6f96debcb/6a7f1b0e73d9bd5ba529df6d/Screenshot_2023-11-10_at_9.52.38_AM.png" alt="3 - troubleshooting 502 Bad gateway" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb7975cbd842b6cd8/6a7f1b11c2e91480da016ffa/elastic-blog-4.png" alt="4 - (5) test the backend directly" /></p>
<p>Your Knowledge Base documents will be stored in the indices <em>.kibana-observability-ai-assistant-kb-</em>*. Have in mind that LLMs have restrictions on the amount of information the model can read and write at once, called token limit. Imagine you're reading a book, but you can only remember a certain number of words at a time. Once you've reached that limit, you start to forget the earlier words you've read. That's similar to how a token limit works in an LLM.</p>
<p>To keep runbooks within the token limit for Retrieval Augmented Generation (RAG) models, ensure the information is concise and relevant. Use bullet points for clarity, avoid repetition, and use links for additional information. Regularly review and update the runbooks to remove outdated or irrelevant information. The goal is to provide clear, concise, and effective troubleshooting information without compromising the quality due to token limit constraints. LLMs are great for summarization, so you could ask the AI Assistant to help you make the runbooks more concise.</p>
<h2 id="asktheassistanttorememberthecontentofanexistingrunbook">Ask the assistant to remember the content of an existing runbook</h2>
<p>The easiest way to store a runbook into the Knowledge Base is to just ask the AI Assistant to do it! Open a new conversation and ask “Can you store this runbook in the KB for future reference?” followed by pasting the content of the runbook in plain text.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt88e751fe6aabf649/6a7f1b146c6eac1f20f145b5/elastic-blog-5.png" alt="5 - new conversation - let's work on this together" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbdbc2440f80ddda/6a7f1b1696b5a6f0e687b89f/elastic-blog-6.png" alt="6 - new converastion" /></p>
<p>The AI Assistant will then store it in the Knowledge Base for you automatically, as simple as that.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt678daca55cfe0ff7/6a7f1b19fc63ab131a64d08e/elastic-blog-7.png" alt="7 - storing a runbook" /></p>
<h2 id="asktheassistanttosummarizeandstorethestepstakenduringaconversationintheknowledgebase">Ask the Assistant to summarize and store the steps taken during a conversation in the Knowledge Base</h2>
<p>You can also ask the AI Assistant to remember something while having a conversation — for example, after you have troubleshooted an alert using the AI Assistant, you could ask to "remember how to troubleshoot this alert for next time." The AI Assistant will create a summary of the steps taken to troubleshoot the alert and add it to the Knowledge Base, effectively creating runbooks for future reference. Next time you are faced with a similar situation, the AI Assistant will recall this information and use it to assist you.</p>
<p>In the following demo, the user asks the Assistant to remember the steps that have been followed to troubleshoot the root cause of an alert, and also to ping the Slack channel when this happens again. In a later conversation with the Assistant, the user asks what can be done about a similar problem, and the AI Assistant is able to remember the steps and also reminds the user to ping the Slack channel.</p>
<p>After receiving the alert, you can open the AI Assistant chat and test troubleshooting the alert. After investigating an alert, ask the AI Assistant to summarize the analysis and the steps taken to root cause. To remember them for the next time, we have a similar alert and add extra instruction like to warn the Slack channel.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt59ebedea4c01cbd8/6a7f1b1dbd21980b3c7584bf/elastic-blog-8.png" alt="8. -teal box" /></p>
<p>The Assistant will use the built-in functions to summarize the steps and store them into your Knowledge Base, so they can be recalled in future conversations.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ab3c30c33361206/6a7f1b20c2cc0977992499ca/Screenshot_2023-11-08_at_11.34.08_AM.png" alt="9 - Elastic assistant chat (CROP)" /></p>
<p>Open a new conversation, and ask what are the steps to take when troubleshooting a similar alert to the one we just investigated. The Assistant will be able to recall the information stored in the KB that is related to the specific alert, using semantic search based on <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html">ELSER</a>, and provide a summary of the steps taken to troubleshoot it, including the last indication of informing the Slack channel.</p>
<div>
    
</div>
<h2 id="importyourrunbooksstoredingithubtotheknowledgebaseusingapisorourgithubconnector">Import your runbooks stored in GitHub to the Knowledge Base using APIs or our GitHub Connector</h2>
<p>You can also add proprietary data into the Knowledge Base programmatically by ingesting it (e.g., GitHub Issues, Markdown files, Jira tickets, text files) into Elastic.</p>
<p>If your organization has created runbooks that are stored in Markdown documents in GitHub, follow the steps in the next section of this blog post to index the runbook documents into your Knowledge Base.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt55e94e2bbca1d4c5/6a7f1b23ead8ec8c11baac5e/elastic-blog-10.png" alt="10 - github handling 502" /></p>
<p>The steps to ingest documents into the Knowledge Base are the following:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte50ccc306ed43ff6/6a7f1b26227b1cac36598a09/elastic-blog-11.png" alt="11 - using internal knowledge" /></p>
<h3 id="ingestyourorganizationsknowledgeintoelasticsearch">Ingest your organization’s knowledge into Elasticsearch</h3>
<p><strong>Option 1:</strong> <strong>Use the</strong> <a href="https://www.elastic.co/guide/en/enterprise-search/current/crawler.html"><strong>Elastic web crawler</strong></a> <strong>.</strong> Use the web crawler to programmatically discover, extract, and index searchable content from websites and knowledge bases. When you ingest data with the web crawler, a search-optimized <a href="https://www.elastic.co/blog/what-is-an-elasticsearch-index">Elasticsearch® index</a> is created to hold and sync webpage content.</p>
<p><strong>Option 2: Use Elasticsearch's</strong> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html"><strong>Index API</strong></a> <strong>.</strong> <a href="https://www.elastic.co/guide/en/cloud/current/ec-ingest-guides.html">Watch tutorials</a> that demonstrate how you can use the Elasticsearch language clients to ingest data from an application.</p>
<p><strong>Option 3: Build your own connector.</strong> Follow the steps described in this blog: <a href="https://www.elastic.co/search-labs/how-to-create-customized-connectors-for-elasticsearch">How to create customized connectors for Elasticsearch</a>.</p>
<p><strong>Option 4: Use Elasticsearch</strong> <a href="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-content-sources.html"><strong>Workplace Search connectors</strong></a> <strong>.</strong> For example, the <a href="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-github-connector.html">GitHub connector</a> can automatically capture, sync, and index issues, Markdown files, pull requests, and repos.</p>
<ul>
<li>Follow the steps to <a href="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-github-connector.html#github-configuration">configure the GitHub Connector in GitHub</a> to create an OAuth App from the GitHub platform.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt934623424f99c138/6a7f1b29bd21985ea47584c3/elastic-blog-12.png" alt="12 - elastic workplace search" /></p>
<ul>
<li>Now you can connect a GitHub instance to your organization. Head to your organization’s <strong>Search &gt; Workplace Search</strong> administrative dashboard, and locate the Sources tab.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt562317ca772f6b3d/6a7f1b2ceab5be27ce20ab08/Screenshot_2023-11-08_at_10.19.19_AM.png" alt="13 - screenshot" /></p>
<ul>
<li>Select <strong>GitHub</strong> (or GitHub Enterprise) in the Configured Sources list, and follow the GitHub authentication flow as presented. Upon the successful authentication flow, you will be redirected to Workplace Search and will be prompted to select the Organization you would like to synchronize.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6c465cdefe93ce4d/6a7f1b2fde231504f2fd80af/elastic-blog-14.png" alt="14 - configure and connect" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt54d1b7727cb79ab9/6a7f1b32eab5be3b6220ab0c/elastic-blog-15.png" alt="15 - how to add github" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf86ab1779e93317c/6a7f1b35bdcff09009c432af/elastic-blog-16.png" alt="16 - github" /></p>
<ul>
<li>After configuring the connector and selecting the organization, the content should be synchronized and you will be able to see it in Sources. If you don’t need to index all the available content, you can specify the indexing rules via the API. This will help shorten indexing times and limit the size of the index. See <a href="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-customizing-indexing-rules.html">Customizing indexing</a>.</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltded840b7b410baf3/6a7f1b37eab5be779e20ab10/elastic-blog-17.png" alt="17 - source overview" /></p>
<ul>
<li>The source has created an index in Elastic with the content (Issues, Markdown Files…) from your organization. You can find the index name by navigating to <strong>Stack Management &gt; Index Management</strong> , activating the <strong>Include hidden Indices</strong> button on the right, and searching for “GitHub.”</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt22ee12a22538f12f/6a7f1b3b05b7b517f518bd55/elastic-blog-18.png" alt="18 - index mgmt" /></p>
<ul>
<li>You can explore the documents you have indexed by creating a Data View and exploring it in Discover. Go to <strong>Stack Management &gt; Kibana &gt; Data Views &gt; Create data view</strong> and introduce the data view Name, Index pattern (make sure you activate “Allow hidden and system indices” in advanced options), and Timestamp field:</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt10bb270db2987d53/6a7f1b3eb437702e514d711e/elastic-blog-19.png" alt="19 - create data view" /></p>
<ul>
<li>You can now explore the documents in Discover using the data view:</li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0626e95bf462405f/6a7f1b4142a11770e795c32b/elastic-blog-20.png" alt="20 - data view" /></p>
<h3 id="reindexyourinternalrunbooksintotheaiassistantsknowledgebaseindexusingitssemanticsearchpipeline">Reindex your internal runbooks into the AI Assistant’s Knowledge Base Index, using it's semantic search pipeline</h3>
<p>Your Knowledge Base documents are stored in the indices <em>.kibana-observability-ai-assistant-kb-*</em>. To add your internal runbooks imported from GitHub to the KB, you just need to reindex the documents from the index you created in the previous step to the KB’s index. To add the semantic search capabilities to the documents in the KB, the reindex should also use the ELSER pipeline preconfigured for the KB, <em>.kibana-observability-ai-assistant-kb-ingest-pipeline</em>.</p>
<p>By creating a Data View with the KB index, you can explore the content in Discover.</p>
<p>You execute the query below in <strong>Management &gt; Dev Tools</strong> , making sure to replace the following, both on “_source” and “inline”:</p>
<ul>
<li>InternalDocsIndex : name of the index where your internal docs are stored</li>
<li>text_field : name of the field with the text of your internal docs</li>
<li>timestamp : name of the field of the timestamp in your internal docs</li>
<li>public : (true or false) if true, makes a document available to all users in the defined <a href="https://www.elastic.co/guide/en/kibana/current/xpack-spaces.html">Kibana Space</a> (if is defined) or in all spaces (if is not defined); if false, document will be restricted to the user indicated in</li>
<li>(optional) space : if defined, restricts the internal document to be available in a specific <a href="https://www.elastic.co/guide/en/kibana/current/xpack-spaces.html">Kibana Space</a></li>
<li>(optional) user.name : if defined, restricts the internal document to be available for a specific user</li>
<li>(optional) "query" filter to index only certain docs (see below)</li>
</ul>
<pre><code>POST _reindex
{
    "source": {
        "index": "&lt;InternalDocsIndex&gt;",
        "_source": [
            "&lt;text_field&gt;",
            "&lt;timestamp&gt;",
            "namespace",
            "is_correction",
            "public",
            "confidence"
        ]
    },
    "dest": {
        "index": ".kibana-observability-ai-assistant-kb-000001",
        "pipeline": ".kibana-observability-ai-assistant-kb-ingest-pipeline"
    },
    "script": {
        "inline": "ctx._source.text=ctx._source.remove(\"&lt;text_field&gt;\");ctx._source.namespace=\"&lt;space&gt;\";ctx._source.is_correction=false;ctx._source.public=&lt;public&gt;;ctx._source.confidence=\"high\";ctx._source['@timestamp']=ctx._source.remove(\"&lt;timestamp&gt;\");ctx._source['user.name'] = \"&lt;user.name&gt;\""
    }
}
</code></pre>
<p>You may want to specify the type of documents that you reindex in the KB — for example, you may only want to reindex Markdown documents (like Runbooks). You can add a “query” filter to the documents in the source. In the case of GitHub, runbooks are identified with the “type” field containing the string “file,” and you could add that to the reindex query like indicated below. To add also GitHub Issues, you can also include in the query “type” field containing the string “issues”:</p>
<pre><code>"source": {
        "index": "&lt;InternalDocsIndex&gt;",
        "_source": [
            "&lt;text_field&gt;",
            "&lt;timestamp&gt;",
            "namespace",
            "is_correction",
            "public",
            "confidence"
        ],
    "query": {
      "terms": {
        "type": ["file"]
      }
    }
</code></pre>
<p>Great! Now that the data is stored in your Knowledge Base, you can ask the Observability AI Assistant any questions about it:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta473e0043f5dbf04/6a7f1b442f00b25aabefef31/elastic-blog-21.png" alt="21 - new conversation" /></p>
<div>
    
</div>
<div>
    
</div>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, leveraging internal Observability knowledge and adding it to the Elastic Knowledge Base can greatly enhance the capabilities of the AI Assistant. By manually inputting information or programmatically ingesting documents, SREs can create a central repository of knowledge accessible through the power of Elastic and LLMs. The AI Assistant can recall this information, assist with incidents, and provide tailored observability to specific contexts using Retrieval Augmented Generation. By following the steps outlined in this article, organizations can unlock the full potential of their Elastic AI Assistant.</p>
<p><a href="https://www.elastic.co/generative-ai/ai-assistant">Start enriching your Knowledge Base with the Elastic AI Assistant today</a> and empower your SRE team with the tools they need to excel. Follow the steps outlined in this article and take your incident management and alert remediation processes to the next level. Your journey toward a more efficient and effective SRE operation begins now.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
<p><em>In this blog post, we may have used or referred to third party generative AI tools, which are owned and operated by their respective owners. Elastic does not have any control over the third party tools and we have no responsibility or liability for their content, operation or use, nor for any loss or damage that may arise from your use of such tools. Please exercise caution when using AI tools with personal, sensitive or confidential information. Any data you submit may be used for AI training or other purposes. There is no guarantee that information you provide will be kept secure or confidential. You should familiarize yourself with the privacy practices and terms of use of any generative AI tools prior to use.</em></p>
<p><em>Elastic, Elasticsearch, ESRE, Elasticsearch Relevance Engine and associated marks are trademarks, logos or registered trademarks of Elasticsearch N.V. in the United States and other countries. All other company and product names are trademarks, logos or registered trademarks of their respective owners.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/sre-troubleshooting-ai-assistant-observability-runbooks</link>
    <guid isPermaLink="false">sre-troubleshooting-ai-assistant-observability-runbooks</guid>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Kubernetes]]></category>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Almudena Sanz Olivé,Katrin Freihofner,Tom Grabowski]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d0f6fc2d38fa05b/6a7f1b47bd21987d717584c9/11-hand.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 08 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Optimizing Observability with ES|QL: Streamlining SRE operations and issue resolution for Kubernetes and OTel]]></title>
    <description><![CDATA[ES|QL enhances operational efficiency, data analysis, and issue resolution for SREs. This blog covers the advantages of ES|QL in Elastic Observability and how it can apply to managing issues instrumented with OpenTelemetry and running on Kubernetes.]]></description>
    <content:encoded><![CDATA[<p>As an operations engineer (SRE, IT Operations, DevOps), managing technology and data sprawl is an ongoing challenge. Simply managing the large volumes of high dimensionality and high cardinality data is overwhelming.</p>
<p>As a single platform, Elastic® helps SREs unify and correlate limitless telemetry data, including metrics, logs, traces, and profiling, into a single datastore — Elasticsearch®. By then applying the power of Elastic’s advanced machine learning (ML), AIOps, AI Assistant, and analytics, you can break down silos and turn data into insights. As a full-stack observability solution, everything from infrastructure monitoring to log monitoring and application performance monitoring (APM) can be found in a single, unified experience.</p>
<p>In Elastic 8.11, a technical preview is now available of <a href="https://www.elastic.co/blog/esql-elasticsearch-piped-query-language">Elastic’s new piped query language, ES|QL (Elasticsearch Query Language)</a>, which transforms, enriches, and simplifies data investigations. Powered by a new query engine, ES|QL delivers advanced search capabilities with concurrent processing, improving speed and efficiency, irrespective of data source and structure. Accelerate resolution by creating aggregations and visualizations from one screen, delivering an iterative, uninterrupted workflow.</p>
<h2 id="advantagesofesqlforsres">Advantages of ES|QL for SREs</h2>
<p>SREs using Elastic Observability can leverage ES|QL to analyze logs, metrics, traces, and profiling data, enabling them to pinpoint performance bottlenecks and system issues with a single query. SREs gain the following advantages when managing high dimensionality and high cardinality data with ES|QL in Elastic Observability:</p>
<ul>
<li><strong>Improved operational efficiency:</strong> By using ES|QL, SREs can create more actionable notifications with aggregated values as thresholds from a single query, which can also be managed through the Elastic API and integrated into DevOps processes.</li>
<li><strong>Enhanced analysis with insights:</strong> ES|QL can process diverse observability data, including application, infrastructure, business data, and more, regardless of the source and structure. ES|QL can easily enrich the data with additional fields and context, allowing the creation of visualizations for dashboards or issue analysis with a single query.</li>
<li><strong>Reduced mean time to resolution:</strong> ES|QL, when combined with Elastic Observability's AIOps and AI Assistant, enhances detection accuracy by identifying trends, isolating incidents, and reducing false positives. This improvement in context facilitates troubleshooting and the quick pinpointing and resolution of issues.</li>
</ul>
<p>ES|QL in Elastic Observability not only enhances an SRE's ability to manage the customer experience, an organization's revenue, and SLOs more effectively but also facilitates collaboration with developers and DevOps by providing contextualized aggregated data.</p>
<p>In this blog, we will cover some of the key use cases SREs can leverage with ES|QL:</p>
<ul>
<li>ES|QL integrated with the Elastic AI Assistant, which uses public LLM and private data, enhances the analysis experience anywhere in Elastic Observability.</li>
<li>SREs can, in a single ES|QL query, break down, analyze, and visualize observability data from multiple sources and across any time frame.</li>
<li>Actionable alerts can be easily created from a single ES|QL query, enhancing operations.</li>
</ul>
<p>I will work through these use cases by showcasing how an SRE can solve a problem in an application instrumented with OpenTelemetry and running on Kubernetes. The OpenTelemetry (OTel) demo is on an Amazon EKS cluster, with Elastic Cloud 8.11 configured.</p>
<p>You can also check out our <a href="https://www.youtube.com/watch?v=vm0pBWI2l9c">Elastic Observability ES|QL Demo</a>, which walks through ES|QL functionality for Observability.</p>
<h2 id="esqlwithaiassistant">ES|QL with AI Assistant</h2>
<p>As an SRE, you are monitoring your OTel instrumented application with Elastic Observability, and while in Elastic APM, you notice some issues highlighted in the service map.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt67931374daecc7f2/6a85cdd8eaf2450312a49fab/elastic-blog-1-services.png" alt="1 - services" /></p>
<p>Using Elastic AI Assistant, you can easily ask for analysis, and in particular, we check on what the overall latency is across the application services.</p>
<pre><code>My APM data is in traces-apm*. What's the average latency per service over the last hour? Use ESQL, the data is mapped to ECS
</code></pre>
<div>
    
</div>
<p>The Elastic AI Assistant generates an ES|QL query, which we run in the AI Assistant to get a list of the average latencies across all the application services. We can easily see the top four are:</p>
<ul>
<li>load generator</li>
<li>front-end proxy</li>
<li>frontendservice</li>
<li>checkoutservice</li>
</ul>
<p>With a simple natural language query in the AI Assistant, it generated a single ES|QL query that helped list out the latencies across the services.</p>
<p>Noticing that there is an issue with several services, we decide to start with the frontend proxy. As we work through the details, we see significant failures, and through <strong>Elastic APM failure correlation</strong> , it becomes apparent that the frontend proxy is not properly completing its calls to downstream services.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt497215d42651cc18/6a85cddbd7b2e75e41fe853e/elastic-blog-2-failed-transaction.png" alt="2 - failed transaction" /></p>
<h2 id="esqlinsightfulandcontextualanalysisindiscover">ES|QL insightful and contextual analysis in Discover</h2>
<p>Knowing that the application is running on Kubernetes, we investigate if there are issues in Kubernetes. In particular, we want to see if there are any services having issues.</p>
<p>We use the following query in ES|QL in Elastic Discover:</p>
<pre><code>from metrics-* | where kubernetes.container.status.last_terminated_reason != "" and kubernetes.namespace == "default" | stats reason_count=count(kubernetes.container.status.last_terminated_reason) by kubernetes.container.name, kubernetes.container.status.last_terminated_reason | where reason_count &gt; 0
</code></pre>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt837d9acfc045bf02/6a85cddeeaf245c0cea49faf/elastic-blog-3-two-horizontal-bar-graphs.png" alt="3 - horizontal graph" /></p>
<p>ES|QL helps analyze 1,000s/10,000s of metric events from Kubernetes and highlights two services that are restarting due to OOMKilled.</p>
<p>The Elastic AI Assistant, when asked about OOMKilled, indicates that a container in a pod was killed due to an out-of-memory condition.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4e0b7f31ffb0e6f7/6a85cde1501a854b28fbb38d/elastic-blog-4-understanding-oomkilled.png" alt="4 - understanding oomkilled" /></p>
<p>We run another ES|QL query to understand the memory usage for emailservice and productcatalogservice.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf8feafaa0a4b2fa6/6a85cde4d7b2e78477fe8542/elastic-blog-5-split-bar-graphs.png" alt="5 - split bar graphs" /></p>
<p>ES|QL easily found the average memory usage fairly high.</p>
<p>We can now further investigate both of these services’ logs, metrics, and Kubernetes-related data. However, before we continue, we create an alert to track heavy memory usage.</p>
<h2 id="actionablealertswithesql">Actionable alerts with ES|QL</h2>
<p>Suspecting a specific issue, that might recur, we simply create an alert that brings in the ES|QL query we just ran that will track for any service that exceeds 50% in memory utilization.</p>
<p>We modify the last query to find any service with high memory usage:</p>
<pre><code>FROM metrics*
| WHERE @timestamp &gt;= NOW() - 1 hours
| STATS avg_memory_usage = AVG(kubernetes.pod.memory.usage.limit.pct) BY kubernetes.deployment.name | where avg_memory_usage &gt; .5
</code></pre>
<p>With that query, we create a simple alert. Notice how the ES|QL query is brought into the alert. We simply connect this to pager duty. But we can choose from multiple connectors like ServiceNow, Opsgenie, email, etc.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16f1d7ecefc9df0f/6a85cde627c5cd53fd5f7450/elastic-blog-6-create-rule.png" alt="6 - create rule" /></p>
<p>With this alert, we can now easily monitor for any services that exceed 50% memory utilization in their pods.</p>
<h2 id="makethemostofyourdatawithesql">Make the most of your data with ES|QL</h2>
<p>In this post, we demonstrated the power ES|QL brings to analysis, operations, and reducing MTTR. In summary, the three use cases with ES|QL in Elastic Observability are as follows:</p>
<ul>
<li>ES|QL integrated with the Elastic AI Assistant, which uses public LLM and private data, enhances the analysis experience anywhere in Elastic Observability.</li>
<li>SREs can, in a single ES|QL query, break down, analyze, and visualize observability data from multiple sources and across any time frame.</li>
<li>Actionable alerts can be easily created from a single ES|QL query, enhancing operations.</li>
</ul>
<p>Elastic invites SREs and developers to experience this transformative language firsthand and unlock new horizons in their data tasks. Try it today at <a href="https://ela.st/free-trial">https://ela.st/free-trial</a> now in technical preview.</p>
<blockquote>
  <ul>
  <li><a href="https://www.elastic.co/demo-gallery/observability">Elastic Observability Tour</a></li>
  <li><a href="https://www.elastic.co/blog/log-management-observability-operations">The power of effective log management</a></li>
  <li><a href="https://www.elastic.co/blog/context-aware-insights-elastic-ai-assistant-observability">Transforming Observability with the AI Assistant</a></li>
  <li><a href="https://www.elastic.co/blog/esql-elasticsearch-piped-query-language">ES|QL announcement blog</a></li>
  </ul>
</blockquote>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/opentelemetry-kubernetes-esql</link>
    <guid isPermaLink="false">opentelemetry-kubernetes-esql</guid>
    <category><![CDATA[Kubernetes]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Logs Analytics]]></category>
    <category><![CDATA[Agentic Observability]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd21cab120ad20933/6a85cde980984ce0f666902e/ES_QL_blog-720x420-05.png" length="0" type="image/png"/>
    <pubDate>Wed, 01 Nov 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Gain insights into Kubernetes errors with Elastic Observability logs and OpenAI]]></title>
    <description><![CDATA[This blog post provides an example of how one can analyze error messages in Elasticsearch with ChatGPT using the OpenAI API via Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>As we’ve shown in previous blogs, Elastic<sup>®</sup> provides a way to ingest and manage telemetry from the <a href="https://www.elastic.co/blog/kubernetes-cluster-metrics-logs-monitoring">Kubernetes cluster</a> and the <a href="https://www.elastic.co/blog/opentelemetry-observability">application</a> running on it. Elastic provides out-of-the-box dashboards to help with tracking metrics, <a href="https://www.elastic.co/blog/log-management-observability-operations">log management and analytics</a>, <a href="https://www.elastic.co/blog/adding-free-and-open-elastic-apm-as-part-of-your-elastic-observability-deployment">APM functionality</a> (which also supports <a href="https://www.elastic.co/blog/opentelemetry-observability">native OpenTelemetry</a>), and the ability to analyze everything with <a href="https://www.elastic.co/blog/observability-logs-machine-learning-aiops">AIOps features</a> and <a href="https://www.elastic.co/what-is/elasticsearch-machine-learning?elektra=home">machine learning</a> (ML). While you can use pre-existing <a href="https://www.elastic.co/blog/improving-information-retrieval-elastic-stack-search-relevance">ML models in Elastic</a>, <a href="https://www.elastic.co/blog/aiops-automation-analytics-elastic-observability-use-cases">out-of-the-box AIOps features</a>, or your own ML models, there is a need to dig deeper into the root cause of an issue.</p>
<p>Elastic helps reduce the operational work to support more efficient operations, but users still need a way to investigate and understand everything from the cause of an issue to the meaning of specific error messages. As an operations user, if you haven’t run into a particular error before or it's part of some runbook, you will likely go to Google and start searching for information.</p>
<p>OpenAI’s ChatGPT is becoming an interesting generative AI tool that helps provide more information using the models behind it. What if you could use OpenAI to obtain deeper insights (even simple semantics) for an error in your production or development environment? You can easily tie Elastic to OpenAI’s API to achieve this.</p>
<p>Kubernetes, a mainstay in most deployments (on-prem or in a cloud service provider) requires a significant amount of expertise — even if that expertise is to manage a service like GKE, EKS, or AKS.</p>
<p>In this blog, I will cover how you can use <a href="https://www.elastic.co/guide/en/kibana/current/watcher-ui.html">Elastic’s watcher</a> capability to connect Elastic to OpenAI and ask it for more information about the error logs Elastic is ingesting from a Kubernetes cluster(s). More specifically, we will use <a href="https://azure.microsoft.com/en-us/products/cognitive-services/openai-service">Azure’s OpenAI Service</a>. Azure OpenAI is a partnership between Microsoft and OpenAI, so the same models from OpenAI are available in the Microsoft version.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blteb7528d40990ace0/6a85cc4de2447afd238b1428/blog-elastic-azure-openai.png" alt="elastic azure openai" /></p>
<p>While this blog goes over a specific example, it can be modified for other types of errors Elastic receives in logs. Whether it's from AWS, the application, databases, etc., the configuration and script described in this blog can be modified easily.</p>
<h2 id="prerequisitesandconfig">Prerequisites and config</h2>
<p>If you plan on following this blog, here are some of the components and details we used to set up the configuration:</p>
<ul>
<li>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</li>
<li>We used a GCP GKE Kubernetes cluster, but you can use any Kubernetes cluster service (on-prem or cloud based) of your choice.</li>
<li>We’re also running with a version of the OpenTelemetry Demo. Directions for using Elastic with OpenTelemetry Demo are <a href="https://github.com/elastic/opentelemetry-demo">here</a>.</li>
<li>We also have an Azure account and <a href="https://azure.microsoft.com/en-us/products/cognitive-services/openai-service">Azure OpenAI service configured</a>. You will need to get the appropriate tokens from Azure and the proper URL endpoint from Azure’s OpenAI service.</li>
<li>We will use <a href="https://www.elastic.co/guide/en/kibana/current/devtools-kibana.html">Elastic’s dev tools</a>, the console to be specific, to load up and run the script, which is an <a href="https://www.elastic.co/guide/en/kibana/current/watcher-ui.html">Elastic watcher</a>.</li>
<li>We will also add a new index to store the results from the OpenAI query.</li>
</ul>
<p>Here is the configuration we will set up in this blog:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5a82668ffd902a5/6a85cc5033f2444aab49f528/blog-elastic-configuration.png" alt="Configuration to analyze Kubernetes cluster errors" /></p>
<p>As we walk through the setup, we’ll also provide the alternative setup with OpenAI versus Azure OpenAI Service.</p>
<h2 id="settingitallup">Setting it all up</h2>
<p>Over the next few steps, I’ll walk through:</p>
<ul>
<li>Getting an account on Elastic Cloud and setting up your K8S cluster and application</li>
<li>Gaining Azure OpenAI authorization (alternative option with OpenAI)</li>
<li>Identifying Kubernetes error logs</li>
<li>Configuring the watcher with the right script</li>
<li>Comparing the output from Azure OpenAI/OpenAI versus ChatGPT UI</li>
</ul>
<h3 id="step0createanaccountonelasticcloud">Step 0: Create an account on Elastic Cloud</h3>
<p>Follow the instructions to <a href="https://cloud.elastic.co/registration?fromURI=/home">get started on Elastic Cloud</a>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3c2915ffc1f2fa55/6a85cc538c2944b302b89067/blog-elastic-start-cloud-trial.png" alt="elastic start cloud trial" /></p>
<p>Once you have the Elastic Cloud login, set up your Kubernetes cluster and application. A complete step-by-step instructions blog is available <a href="https://www.elastic.co/blog/kubernetes-cluster-metrics-logs-monitoring">here</a>. This also provides an overview of how to see Kubernetes cluster metrics in Elastic and how to monitor them with dashboards.</p>
<h3 id="step1azureopenaiserviceandauthorization">Step 1: Azure OpenAI Service and authorization</h3>
<p>When you log in to your Azure subscription and set up an instance of Azure OpenAI Service, you will be able to get your keys under Manage Keys.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc803bb9220bc5e6a/6a85cc56abdc296504122528/blog-elastic-microsoft-azure-manage-keys.png" alt="microsoft azure manage keys" /></p>
<p>There are two keys for your OpenAI instance, but you only need KEY 1 .</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd656cf4c96ad1ded/6a85cc5993ffb96abab9145d/blog-elastic-pme-openai-keys-and-endpoint.png" alt="Used with permission from Microsoft." /></p>
<p>Additionally, you will need to get the service URL. See the image above with our service URL blanked out to understand where to get the KEY 1 and URL.</p>
<p>If you are not using Azure OpenAI Service and the standard OpenAI service, then you can get your keys at:</p>
<pre><code>**https** ://platform.openai.com/account/api-keys
</code></pre>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltda718eafc61eb455/6a85cc5c5c27903359f59b35/blog-elastic-api-keys.png" alt="api keys" /></p>
<p>You will need to create a key and save it. Once you have the key, you can go to Step 2.</p>
<h3 id="step2identifyingkuberneteserrorsinelasticlogs">Step 2: Identifying Kubernetes errors in Elastic logs</h3>
<p>As your Kubernetes cluster is running, <a href="https://docs.elastic.co/en/integrations/kubernetes">Elastic’s Kubernetes integration</a> running on the Elastic agent daemon set on your cluster is sending logs and metrics to Elastic. <a href="https://www.elastic.co/blog/log-monitoring-management-enterprise">The telemetry is ingested, processed, and indexed</a>. Kubernetes logs are stored in an index called .ds-logs-kubernetes.container_logs-default-* (* is for the date), and an automatic data stream logs-kubernetes.container_logs is also pre-loaded. So while you can use some of the out-of-the-box dashboards to investigate the metrics, you can also look at all the logs in Elastic Discover.</p>
<p>While any error from Kubernetes can be daunting, the more nuanced issues occur with errors from the pods running in the kube-system namespace. Take the pod konnectivity agent, which is essentially a network proxy agent running on the node to help establish tunnels and is a vital component in Kubernetes. Any error will cause the cluster to have connectivity issues and lead to a cascade of issues, so it’s important to understand and troubleshoot these errors.</p>
<p>When we filter out for error logs from the konnectivity agent, we see a good number of errors.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt61aec76988119b34/6a85cc604710c6e78bd3cb7d/blog-elastic-expanded-document.png" alt="expanded document" /></p>
<p>But unfortunately, we still can’t understand what these errors mean.</p>
<p>Enter OpenAI to help us understand the issue better. Generally, you would take the error message from Discover and paste it with a question in ChatGPT (or run a Google search on the message).</p>
<p>One error in particular that we’ve run into but do not understand is:</p>
<pre><code>E0510 02:51:47.138292       1 client.go:388] could not read stream err=rpc error: code = Unavailable desc = error reading from server: read tcp 10.120.0.8:46156-&gt;35.230.74.219:8132: read: connection timed out serverID=632d489f-9306-4851-b96b-9204b48f5587 agentID=e305f823-5b03-47d3-a898-70031d9f4768
</code></pre>
<p>The OpenAI output is as follows:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1cdff890473ba8c8/6a85cc63bc5bb35efdf81b21/blog-elastic-openai-output.png" alt="openai output" /></p>
<p>ChatGPT has given us a fairly nice set of ideas on why this rpc error is occurring against our konnectivity-agent.</p>
<p>So how can we get this output automatically for any error when those errors occur?</p>
<h3 id="step3configuringthewatcherwiththerightscript">Step 3: Configuring the watcher with the right script</h3>
<p><a href="https://www.elastic.co/guide/en/kibana/current/watcher-ui.html">What is an Elastic watcher?</a> Watcher is an Elasticsearch feature that you can use to create actions based on conditions, which are periodically evaluated using queries on your data. Watchers are helpful for analyzing mission-critical and business-critical streaming data. For example, you might watch application logs for errors causing larger operational issues.</p>
<p>Once a watcher is configured, it can be:</p>
<ol>
<li>Manually triggered</li>
<li>Run periodically</li>
<li>Created using a UI or a script</li>
</ol>
<p>In this scenario, we will use a script, as we can modify it easily and run it as needed.</p>
<p>We’re using the DevTools Console to enter the script and test it out:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt009cda608e30cff4/6a85cc66f61d6e61f59c2b4f/blog-elastic-test-script.png" alt="test script" /></p>
<p>The script is listed at the end of the blog in the <strong>appendix</strong>. It can also be downloaded <a href="https://github.com/elastic/chatgpt-error-analysis"><strong>here</strong></a> <strong>.</strong></p>
<p>The script does the following:</p>
<ol>
<li>It runs continuously every five minutes.</li>
<li>It will search the logs for errors from the container konnectivity-agent.</li>
<li>It will take the first error’s message, transform it (re-format and clean up), and place it into a variable first_hit.</li>
</ol>
<pre><code>"script": "return ['first_hit': ctx.payload.first.hits.hits.0._source.message.replace('\"', \"\")]"
</code></pre>
<ol>
<li>The error message is sent into OpenAI with a query:</li>
</ol>
<pre><code>What are the potential reasons for the following kubernetes error:
  { { ctx.payload.second.first_hit } }
</code></pre>
<ol>
<li>If the search yielded an error, it will proceed to then create an index and place the error message, pod.name (which is konnectivity-agent-6676d5695b-ccsmx in our setup), and OpenAI output into a new index called chatgpt_k8_analyzed.</li>
</ol>
<p>To see the results, we created a new data view called chatgpt_k8_analyzed against the newly created index:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte281840a289fb3f9/6a85cc6899083f864140f9f9/blog-elastic-edit-data-view.png" alt="edit data view" /></p>
<p>In Discover, the output on the data view provides us with the analysis of the errors.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf80847d904c25e91/6a85cc6c2d64d54455081d6a/blog-elastic-analysis-of-errors.png" alt="analysis of errors" /></p>
<p>For every error the script sees in the five minute interval, it will get an analysis of the error. We could alternatively also use a range as needed to analyze during a specific time frame. The script would just need to be modified accordingly.</p>
<h3 id="step4outputfromazureopenaiopenaivschatgptui">Step 4. Output from Azure OpenAI/OpenAI vs. ChatGPT UI</h3>
<p>As you noticed above, we got relatively the same result from the Azure OpenAI API call as we did by testing out our query in the ChatGPT UI. This is because we configured the API call to run the same/similar model as what was selected in the UI.</p>
<p>For the API call, we used the following parameters:</p>
<pre><code>"request": {
             "method" : "POST",
             "Url": "https://XXX.openai.azure.com/openai/deployments/pme-gpt-35-turbo/chat/completions?api-version=2023-03-15-preview",
             "headers": {"api-key" : "XXXXXXX",
                         "content-type" : "application/json"
                        },
             "body" : "{ \"messages\": [ { \"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, { \"role\": \"user\", \"content\": \"What are the potential reasons for the following kubernetes error: {{ctx.payload.second.first_hit}}\"}], \"temperature\": 0.5, \"max_tokens\": 2048}" ,
              "connection_timeout": "60s",
               "read_timeout": "60s"
                            }
</code></pre>
<p>By setting the role: system with You are a helpful assistant and using the gpt-35-turbo url portion, we are essentially setting the API to use the davinci model, which is the same as the ChatGPT UI model set by default.</p>
<p>Additionally, for Azure OpenAI Service, you will need to set the URL to something similar the following:</p>
<pre><code>https://YOURSERVICENAME.openai.azure.com/openai/deployments/pme-gpt-35-turbo/chat/completions?api-version=2023-03-15-preview
</code></pre>
<p>If you use OpenAI (versus Azure OpenAI Service), the request call (against <a href="https://api.openai.com/v1/completions">https://api.openai.com/v1/completions</a>) would be as such:</p>
<pre><code>"request": {
            "scheme": "https",
            "host": "api.openai.com",
            "port": 443,
            "method": "post",
            "path": "\/v1\/completions",
            "params": {},
            "headers": {
               "content-type": "application\/json",
               "authorization": "Bearer YOUR_ACCESS_TOKEN"
                        },
            "body": "{ \"model\": \"text-davinci-003\",  \"prompt\": \"What are the potential reasons for the following kubernetes error: {{ctx.payload.second.first_hit}}\",  \"temperature\": 1,  \"max_tokens\": 512,     \"top_p\": 1.0,      \"frequency_penalty\": 0.0,   \"presence_penalty\": 0.0 }",
            "connection_timeout_in_millis": 60000,
            "read_timeout_millis": 60000
          }
</code></pre>
<p>If you are interested in creating a more OpenAI-based version, you can <a href="https://elastic-content-share.eu/downloads/watcher-job-to-integrate-chatgpt-in-elasticsearch/">download an alternative script</a> and look at <a href="https://mar1.hashnode.dev/unlocking-the-power-of-aiops-with-chatgpt-and-elasticsearch">another blog from an Elastic community member</a>.</p>
<h2 id="gainingotherinsightsbeyondkuberneteslogs">Gaining other insights beyond Kubernetes logs</h2>
<p>Now that the script is up and running, you can modify it using different:</p>
<ul>
<li>Inputs</li>
<li>Conditions</li>
<li>Actions</li>
<li>Transforms</li>
</ul>
<p>Learn more on how to modify it <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/xpack-alerting.html">here</a>. Some examples of modifications could include:</p>
<ol>
<li>Look for error logs from application components (e.g., cartService, frontEnd, from the OTel demo), cloud service providers (e.g., AWS/Azure/GCP logs), and even logs from components such as Kafka, databases, etc.</li>
<li>Vary the time frame from running continuously to running over a specific <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html">range</a>.</li>
<li>Look for specific errors in the logs.</li>
<li>Query for analysis on a set of errors at once versus just one, which we demonstrated.</li>
</ol>
<p>The modifications are endless, and of course you can run this with OpenAI rather than Azure OpenAI Service.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I hope you’ve gotten an appreciation for how Elastic Observability can help you connect to OpenAI services (Azure OpenAI, as we showed, or even OpenAI) to better analyze an error log message instead of having to run several Google searches and hunt for possible insights.</p>
<p>Here’s a quick recap of what we covered:</p>
<ul>
<li>Developing an Elastic watcher script that can be used to find and send Kubernetes errors into OpenAI and insert them into a new index</li>
<li>Configuring Azure OpenAI Service or OpenAI with the right authorization and request parameters</li>
</ul>
<p>Ready to get started? Sign up <a href="https://cloud.elastic.co/registration">for Elastic Cloud</a> and try out the features and capabilities I’ve outlined above to get the most value and visibility out of your OpenTelemetry data.</p>
<h2 id="appendix">Appendix</h2>
<p>Watcher script</p>
<pre><code>PUT _watcher/watch/chatgpt_analysis
{
    "trigger": {
      "schedule": {
        "interval": "5m"
      }
    },
    "input": {
      "chain": {
          "inputs": [
              {
                  "first": {
                      "search": {
                          "request": {
                              "search_type": "query_then_fetch",
                              "indices": [
                                "logs-kubernetes*"
                              ],
                              "rest_total_hits_as_int": true,
                              "body": {
                                "query": {
                                  "bool": {
                                    "must": [
                                      {
                                        "match": {
                                          "kubernetes.container.name": "konnectivity-agent"
                                        }
                                      },
                                      {
                                        "match" : {
                                          "message":"error"
                                        }
                                      }
                                    ]
                                  }
                                },
                                "size": "1"
                              }
                            }
                        }
                    }
                },
                {
                    "second": {
                        "transform": {
                            "script": "return ['first_hit': ctx.payload.first.hits.hits.0._source.message.replace('\"', \"\")]"
                        }
                    }
                },
                {
                    "third": {
                        "http": {
                            "request": {
                                "method" : "POST",
                                "url": "https://XXX.openai.azure.com/openai/deployments/pme-gpt-35-turbo/chat/completions?api-version=2023-03-15-preview",
                                "headers": {
                                    "api-key" : "XXX",
                                    "content-type" : "application/json"
                                },
                                "body" : "{ \"messages\": [ { \"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, { \"role\": \"user\", \"content\": \"What are the potential reasons for the following kubernetes error: {{ctx.payload.second.first_hit}}\"}], \"temperature\": 0.5, \"max_tokens\": 2048}" ,
                                "connection_timeout": "60s",
                                "read_timeout": "60s"
                            }
                        }
                    }
                }
            ]
        }
    },
    "condition": {
      "compare": {
        "ctx.payload.first.hits.total": {
          "gt": 0
        }
      }
    },
    "actions": {
        "index_payload" : {
            "transform": {
                "script": {
                    "source": """
                        def payload = [:];
                        payload.timestamp = new Date();
                        payload.pod_name = ctx.payload.first.hits.hits[0]._source.kubernetes.pod.name;
                        payload.error_message = ctx.payload.second.first_hit;
                        payload.chatgpt_analysis = ctx.payload.third.choices[0].message.content;
                        return payload;
                    """
                }
            },
            "index" : {
                "index" : "chatgpt_k8s_analyzed"
            }
        }
    }
}
</code></pre>
<h3 id="additionalloggingresources">Additional logging resources:</h3>
<ul>
<li><a href="https://www.elastic.co/getting-started/observability/collect-and-analyze-logs">Getting started with logging on Elastic (quickstart)</a></li>
<li><a href="https://www.elastic.co/guide/en/observability/current/logs-metrics-get-started.html">Ingesting common known logs via integrations (compute node example)</a></li>
<li><a href="https://docs.elastic.co/integrations">List of integrations</a></li>
<li><a href="https://www.elastic.co/blog/log-monitoring-management-enterprise">Ingesting custom application logs into Elastic</a></li>
<li><a href="https://www.elastic.co/blog/observability-logs-parsing-schema-read-write">Enriching logs in Elastic</a></li>
<li>Analyzing Logs with <a href="https://www.elastic.co/blog/reduce-mttd-ml-machine-learning-observability">Anomaly Detection (ML)</a> and <a href="https://www.elastic.co/blog/observability-logs-machine-learning-aiops">AIOps</a></li>
</ul>
<h3 id="commonusecaseexampleswithlogs">Common use case examples with logs:</h3>
<ul>
<li><a href="https://youtu.be/ax04ZFWqVCg">Nginx log management</a></li>
<li><a href="https://www.elastic.co/blog/vpc-flow-logs-monitoring-analytics-observability">AWS VPC Flow log management</a></li>
<li><a href="https://youtu.be/Li5TJAWbz8Q">PostgreSQL issue analysis with AIOps</a></li>
</ul>
<p><em>In this blog post, we may have used third party generative AI tools, which are owned and operated by their respective owners. Elastic does not have any control over the third party tools and we have no responsibility or liability for their content, operation or use, nor for any loss or damage that may arise from your use of such tools. Please exercise caution when using AI tools with personal, sensitive or confidential information. Any data you submit may be used for AI training or other purposes. There is no guarantee that information you provide will be kept secure or confidential. You should familiarize yourself with the privacy practices and terms of use of any generative AI tools prior to use.</em></p>
<p><em>Elastic, Elasticsearch and associated marks are trademarks, logos or registered trademarks of Elasticsearch N.V. in the United States and other countries. All other company and product names are trademarks, logos or registered trademarks of their respective owners.</em></p>
<p><em>Screenshots of Microsoft products used with permission from Microsoft.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/kubernetes-errors-observability-logs-openai</link>
    <guid isPermaLink="false">kubernetes-errors-observability-logs-openai</guid>
    <category><![CDATA[Kubernetes]]></category>
    <category><![CDATA[Infrastructure Monitoring]]></category>
    <category><![CDATA[LLM Observability]]></category>
    <dc:creator><![CDATA[Bahubali Shetti]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf5a82668ffd902a5/6a85cc5033f2444aab49f528/blog-elastic-configuration.png" length="0" type="image/png"/>
    <pubDate>Thu, 18 May 2023 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Monitor OpenAI API and GPT models with OpenTelemetry and Elastic]]></title>
    <description><![CDATA[Get ready to be blown away by this game-changing approach to monitoring cutting-edge ChatGPT applications! As the ChatGPT phenomenon takes the world by storm, it's time to supercharge your monitoring game with OpenTelemetry and Elastic Observability.]]></description>
    <content:encoded><![CDATA[<p>ChatGPT is so hot right now, it broke the internet. As an avid user of ChatGPT and a developer of ChatGPT applications, I am incredibly excited by the possibilities of this technology. What I see happening is that there will be exponential growth of ChatGPT-based solutions, and people are going to need to monitor those solutions.</p>
<p>Since this is a pretty new technology, we wouldn’t want to burden our shiny new code with proprietary technology, would we? No, we would not, and that is why we are going to use OpenTelemetry to monitor our ChatGPT code in this blog. This is particularly relevant for me as I recently created a service to generate meeting notes from Zoom calls. If I am to release this into the wild, how much is it going to cost me and how do I make sure it is available?</p>
<h2 id="openaiapistotherescue">OpenAI APIs to the rescue</h2>
<p>The OpenAI API is pretty awesome, there is no doubt. It also gives us the information shown below in each response to each API call, which can help us with understanding what we are being charged. By using the token counts, the model, and the pricing that OpenAI has put up on its website, we can calculate the cost. The question is, how do we get this information into our monitoring tools?</p>
<pre><code>{
  "choices": [
    {
      "finish_reason": "length",
      "index": 0,
      "logprobs": null,
      "text": "\n\nElastic is an amazing observability tool because it provides a comprehensive set of features for monitoring"
    }
  ],
  "created": 1680281710,
  "id": "cmpl-70CJq07gibupTcSM8xOWekOTV5FRF",
  "model": "text-davinci-003",
  "object": "text_completion",
  "usage": {
    "completion_tokens": 20,
    "prompt_tokens": 9,
    "total_tokens": 29
  }
}
</code></pre>
<h2 id="opentelemetrytotherescue">OpenTelemetry to the rescue</h2>
<p><a href="https://www.elastic.co/blog/opentelemetry-observability">OpenTelemetry</a> is truly a fantastic piece of work. It has had so much adoption and work committed to it over the years, and it seems to really be getting to the point where we can call it the Linux of Observability. We can use it to record logs, metrics, and traces and get those in a vendor neutral way into our favorite observability tool — in this case, Elastic Observability.</p>
<p>With the latest and greatest otel libraries in Python, we can auto-instrument external calls, and this will help us understand how OpenAI calls are performing. Let's take a sneak peek at our sample Python application, which implements Flask and the ChatGPT API and also has OpenTelemetry. If you want to try this yourself, take a look at the GitHub link at the end of this blog and follow these steps.</p>
<h3 id="setupelasticcloudaccountifyoualreadydonthaveone">Set up Elastic Cloud account (if you already don’t have one)</h3>
<ol>
<li>Sign up for a two-week free trial at <a href="https://www.elastic.co/cloud/elasticsearch-service/signup">https://www.elastic.co/cloud/elasticsearch-service/signup</a>.</li>
<li>Create a deployment.</li>
</ol>
<p>Once you are logged in, click <strong>Add integrations</strong>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2a530a6a1d8ae18c/6a85cd3eeaf2458371a49f8f/blog-elastic-cloud-deployment-add-integrations.png" alt="elastic cloud deployment add integrations" /></p>
<p>Click on <strong>APM Integration</strong>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt12f670bb3d7aad2c/6a85cd411aa1e1660eff8da3/blog-elastic-apm-integration.png" alt="elastic apm integration" /></p>
<p>Then scroll down to get the details you need for this blog:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfa14098df2f3aab7/6a85cd44d6cf2912dcbb0925/blog-elastic-opentelemetry-download.png" alt="elastic opentelemetry download" /></p>
<p>Be sure to set the following Environment variables, replacing the variables with data you get from Elastic as above and OpenAI from <a href="https://platform.openai.com/account/api-keys">here</a>, and then run these export commands on the command line.</p>
<pre><code>export OPEN_AI_KEY=sk-abcdefgh5ijk2l173mnop3qrstuvwxyzab2cde47fP2g9jij
export OTEL_EXPORTER_OTLP_AUTH_HEADER=abc9ldeofghij3klmn
export OTEL_EXPORTER_OTLP_ENDPOINT=https://123456abcdef.apm.us-west2.gcp.elastic-cloud.com:443
</code></pre>
<p>And install the following Python libraries:</p>
<pre><code>pip3 install opentelemetry-api
pip3 install opentelemetry-sdk
pip3 install opentelemetry-exporter-otlp
pip3 install opentelemetry-instrumentation
pip3 install opentelemetry-instrumentation-requests
pip3 install openai
pip3 install flask
</code></pre>
<p>Here is a look at the code we are using for the example application. In the real world, this would be your own code. All this does is call OpenAI APIs with the following message: “Why is Elastic an amazing observability tool?”</p>
<pre><code>import openai
from flask import Flask
import monitor  # Import the module
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
import urllib
import os
from opentelemetry import trace
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.requests import RequestsInstrumentor

# OpenTelemetry setup up code here, feel free to replace the “your-service-name” attribute here.
resource = Resource(attributes={
    SERVICE_NAME: "your-service-name"
})
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint=os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT'),
        headers="Authorization=Bearer%20"+os.getenv('OTEL_EXPORTER_OTLP_AUTH_HEADER')))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
RequestsInstrumentor().instrument()



# Initialize Flask app and instrument it

app = Flask(__name__)
# Set OpenAI API key
openai.api_key = os.getenv('OPEN_AI_KEY')


@app.route("/completion")
@tracer.start_as_current_span("do_work")
def completion():
    response = openai.Completion.create(
        model="text-davinci-003",
        prompt="Why is Elastic an amazing observability tool?",
        max_tokens=20,
        temperature=0
    )
    return response.choices[0].text.strip()

if __name__ == "__main__":
    app.run()
</code></pre>
<p>This code should be fairly familiar to anyone who has implemented OpenTelemetry with Python here — there is no specific magic. The magic happens inside the “monitor” code that you can use freely to instrument your own OpenAI applications.</p>
<h2 id="monkeyingaround">Monkeying around</h2>
<p>Inside the monitor.py code, you will see we do something called “Monkey Patching.” Monkey patching is a technique in Python where you dynamically modify the behavior of a class or module at runtime by modifying its attributes or methods. Monkey patching allows you to change the functionality of a class or module without having to modify its source code. It can be useful in situations where you need to modify the behavior of an existing class or module that you don't have control over or cannot modify directly.</p>
<p>What we want to do here is modify the behavior of the “Completion” call so we can steal the response metrics and add them to our OpenTelemetry spans. You can see how we do that below:</p>
<pre><code>def count_completion_requests_and_tokens(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        counters['completion_count'] += 1
        response = func(*args, **kwargs)
        token_count = response.usage.total_tokens
        prompt_tokens = response.usage.prompt_tokens
        completion_tokens = response.usage.completion_tokens
        cost = calculate_cost(response)
        strResponse = json.dumps(response)
        # Set OpenTelemetry attributes
        span = trace.get_current_span()
        if span:
            span.set_attribute("completion_count", counters['completion_count'])
            span.set_attribute("token_count", token_count)
            span.set_attribute("prompt_tokens", prompt_tokens)
            span.set_attribute("completion_tokens", completion_tokens)
            span.set_attribute("model", response.model)
            span.set_attribute("cost", cost)
            span.set_attribute("response", strResponse)
        return response
    return wrapper
# Monkey-patch the openai.Completion.create function
openai.Completion.create = count_completion_requests_and_tokens(openai.Completion.create)
</code></pre>
<p>By adding all this data to our Span, we can actually send it to our OpenTelemetry OTLP endpoint (in this case it will be Elastic). The benefit of doing this is that you can easily use the data for search or to build dashboards and visualizations. In the final step, we also want to calculate the cost. We do this by implementing the following function, which will calculate the cost of a single request to the OpenAI APIs.</p>
<pre><code>def calculate_cost(response):
    if response.model in ['gpt-4', 'gpt-4-0314']:
        cost = (response.usage.prompt_tokens * 0.03 + response.usage.completion_tokens * 0.06) / 1000
    elif response.model in ['gpt-4-32k', 'gpt-4-32k-0314']:
        cost = (response.usage.prompt_tokens * 0.06 + response.usage.completion_tokens * 0.12) / 1000
    elif 'gpt-3.5-turbo' in response.model:
        cost = response.usage.total_tokens * 0.002 / 1000
    elif 'davinci' in response.model:
        cost = response.usage.total_tokens * 0.02 / 1000
    elif 'curie' in response.model:
        cost = response.usage.total_tokens * 0.002 / 1000
    elif 'babbage' in response.model:
        cost = response.usage.total_tokens * 0.0005 / 1000
    elif 'ada' in response.model:
        cost = response.usage.total_tokens * 0.0004 / 1000
    else:
        cost = 0
    return cost
</code></pre>
<h2 id="elastictotherescue">Elastic to the rescue</h2>
<p>Once we are capturing all this data, it’s time to have some fun with it in Elastic. In Discover, we can see all the data points we sent over using the OpenTelemetry library:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfce6ddd6aa2ec67b/6a85cd460782905a9f3217aa/blog-elastic-discover-apm.png" alt="elastic discover apm" /></p>
<p>With these labels in place, it is very easy to build a dashboard. Take a look at this one I built earlier (<a href="https://github.com/davidgeorgehope/ChatGPTMonitoringWithOtel/blob/main/chatGPTDashboard.ndjson">which is also checked into my GitHub Repository</a>):</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt771ed8e0409e9e81/6a85cd4907829032893217ae/blog-elastic-labels-dashboard.png" alt="elastic labels dashboard" /></p>
<p>We can also see Transactions, Latency of the OpenAI service, and all the spans related to our ChatGPT service calls.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt090652b31aa8510a/6a85cd4c4710c62948d3cba0/blog-elastic-observability-service-name.png" alt="observability service name" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta8534a667cecc5f1/6a85cd4f18249c222918f803/blog-elastic-your-service-name.png" alt="elastic your service name" /></p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc32738277650edf/6a85cd529bf994220f0a05b5/blog-elastic-api-openai.png" alt="elastic api openai" /></p>
<p>In the transaction view, we can also see how long specific OpenAI calls have taken:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0101e66241fca1b4/6a85cd54f9373dad1d96f5de/blog-elastic-latency-distribution.png" alt="elastic latency distribution" /></p>
<p>Some requests to OpenAI here have taken over 3 seconds. ChatGPT can be very slow, so it’s important for us to understand how slow this is and if users are becoming frustrated.</p>
<h2 id="summary">Summary</h2>
<p>We looked at monitoring ChatGPT with OpenTelemetry with Elastic. ChatGPT is a worldwide phenomenon and it’s going to no doubt grow and grow, and pretty soon everyone will be using it. Because it can be slow to get responses out, it is critical that people are able to understand the performance of any code that is using this service.</p>
<p>There is also the issue of cost, since it’s incredibly important to understand if this service is eating into your margins and if what you are asking for is profitable for your business. With the current economic environment, we have to keep an eye on profitability.</p>
<p>Take a look at the code for this solution <a href="https://github.com/davidgeorgehope/ChatGPTMonitoringWithOtel">here</a>. And please feel free to use the “monitor” library to instrument your own OpenAI code.</p>
<p>Interested in learning more about Elastic Observability? Check out the following resources:</p>
<ul>
<li><a href="https://www.elastic.co/virtual-events/intro-to-elastic-observability">An Introduction to Elastic Observability</a></li>
<li><a href="https://www.elastic.co/training/observability-fundamentals">Observability Fundamentals Training</a></li>
<li><a href="https://www.elastic.co/observability/demo">Watch an Elastic Observability demo</a></li>
<li><a href="https://www.elastic.co/blog/observability-predictions-trends-2023">Observability Predictions and Trends for 2023</a></li>
</ul>
<p>And sign up for our <a href="https://www.elastic.co/virtual-events/emerging-trends-in-observability">Elastic Observability Trends Webinar</a> featuring AWS and Forrester, not to be missed!</p>
<p><em>In this blog post, we may have used third party generative AI tools, which are owned and operated by their respective owners. Elastic does not have any control over the third party tools and we have no responsibility or liability for their content, operation or use, nor for any loss or damage that may arise from your use of such tools. Please exercise caution when using AI tools with personal, sensitive or confidential information. Any data you submit may be used for AI training or other purposes. There is no guarantee that information you provide will be kept secure or confidential. You should familiarize yourself with the privacy practices and terms of use of any generative AI tools prior to use.</em></p>
<p><em>Elastic, Elasticsearch and associated marks are trademarks, logos or registered trademarks of Elasticsearch N.V. in the United States and other countries. All other company and product names are trademarks, logos or registered trademarks of their respective owners.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/monitor-openai-api-gpt-models-opentelemetry</link>
    <guid isPermaLink="false">monitor-openai-api-gpt-models-opentelemetry</guid>
    <category><![CDATA[LLM Observability]]></category>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[APM]]></category>
    <dc:creator><![CDATA[David Hope]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc8ce30804f9f5a2b/6a85cd5743c0b79e872f0666/opentelemetry-graphic-ad-2-1920x1080.png" length="0" type="image/png"/>
    <pubDate>Tue, 04 Apr 2023 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>