<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>OpenTelemetry on David Parry</title>
    <link>https://davidparry.com/tags/opentelemetry/</link>
    <description>Recent content in OpenTelemetry on David Parry</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 06 Oct 2026 20:00:00 -0500</lastBuildDate>
    <atom:link href="https://davidparry.com/tags/opentelemetry/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>🔥 The Code Runs. The Logs Say Nothing.</title>
      <link>https://davidparry.com/blog/2026/10/06/the-code-runs-the-logs-say-nothing/</link>
      <pubDate>Tue, 06 Oct 2026 20:00:00 -0500</pubDate>
      <guid>https://davidparry.com/blog/2026/10/06/the-code-runs-the-logs-say-nothing/</guid>
      <description>&lt;img src=&#34;https://davidparry.com/images/the-code-runs-the-logs-say-nothing-linkedin.jpg&#34; alt=&#34;A panicking developer throws both hands in the air beside a spilled coffee mug, one monitor showing an empty terminal that reads NO LOGS FOUND and another showing an error graph spiking off the chart, while server racks burn under a sign reading PRODUCTION and a cheerful robot calmly holds up a green clipboard reading ALL SYSTEMS NORMAL, NO EVIDENCE OF ANY ISSUE&#34; style=&#34;display: block; margin: 0 auto; width: 70%; max-width: 560px;&#34; /&gt;&#xA;&lt;p&gt;I once helped troubleshoot a problem in production and went looking for the application logs. There were none. No error explaining the failure, no info message saying the service had started, and no way to turn up logging while we investigated.&lt;/p&gt;</description>
      <content:encoded>&lt;img src=&#34;https://davidparry.com/images/the-code-runs-the-logs-say-nothing-linkedin.jpg&#34; alt=&#34;A panicking developer throws both hands in the air beside a spilled coffee mug, one monitor showing an empty terminal that reads NO LOGS FOUND and another showing an error graph spiking off the chart, while server racks burn under a sign reading PRODUCTION and a cheerful robot calmly holds up a green clipboard reading ALL SYSTEMS NORMAL, NO EVIDENCE OF ANY ISSUE&#34; style=&#34;display: block; margin: 0 auto; width: 70%; max-width: 560px;&#34; /&gt;&#xA;&lt;p&gt;I once helped troubleshoot a problem in production and went looking for the application logs. There were none. No error explaining the failure, no info message saying the service had started, and no way to turn up logging while we investigated.&lt;/p&gt;&#xA;&lt;p&gt;The story behind that silence was more complicated than a developer forgetting to add log statements. The team responsible for keeping the system running had built software that read the application&amp;rsquo;s logs to detect problems. At some point an included library changed its logging output. The operations team saw that as an unapproved change to something their tooling depended on. As I understood it, the engineers&amp;rsquo; response was to stop emitting application logs in production.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-logs-become-an-interface&#34;&gt;When logs become an interface&lt;/h2&gt;&#xA;&lt;p&gt;That was an extreme outcome, and the disagreement underneath it was real. Once another system reads your logs, their format is an interface, and a change to a library&amp;rsquo;s logging output can break that interface while the product&amp;rsquo;s behavior stays exactly the same.&lt;/p&gt;&#xA;&lt;p&gt;The fix was available. Agree on stable, structured events for the tooling, review format changes against the systems that consume them, and leave the diagnostic detail free to evolve underneath. OpenTelemetry&amp;rsquo;s &lt;a href=&#34;https://opentelemetry.io/docs/specs/otel/logs/data-model/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;log data model&lt;/a&gt;&#xA; is built for that split: &lt;code&gt;EventName&lt;/code&gt; identifies the class of event, &lt;code&gt;SeverityText&lt;/code&gt; and &lt;code&gt;SeverityNumber&lt;/code&gt; carry the level, &lt;code&gt;Attributes&lt;/code&gt; carry the detail that varies, and &lt;code&gt;TraceId&lt;/code&gt; ties the record to the request it came from. Tooling can bind to an event name and the fields it needs without owning every string a developer writes.&lt;/p&gt;&#xA;&lt;p&gt;Nobody took that path, and we ended up with a running application that could tell us almost nothing about itself. That is the one outcome &lt;a href=&#34;https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OWASP&amp;rsquo;s logging cheat sheet&lt;/a&gt;&#xA; rules out by name: &amp;ldquo;It should not be possible to completely deactivate application logging or logging of events that are necessary for compliance requirements.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;I think about that experience when I review AI-generated code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-statement-that-gets-cleaned-up&#34;&gt;The statement that gets cleaned up&lt;/h2&gt;&#xA;&lt;p&gt;I have watched AI add log statements to debug a problem, use them to get a test passing, and then remove them as part of its cleanup. Sometimes removal is exactly right. A temporary dump of a request body may be noisy or unsafe to keep. But sometimes the statement captured a decision, a retry, or a state transition that would be worth having the next time the problem showed up in production. The judgment call between those two cases is the entire job.&lt;/p&gt;&#xA;&lt;p&gt;Production problems are rarely considerate enough to reproduce locally. If the useful statement has been deleted, raising the log level reveals nothing, and putting it back means a code change and another deployment, possibly while customers are already affected. Google&amp;rsquo;s &lt;a href=&#34;https://sre.google/sre-book/effective-troubleshooting/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;SRE troubleshooting chapter&lt;/a&gt;&#xA; is direct about what you want instead: &amp;ldquo;It&amp;rsquo;s really useful to have multiple verbosity levels available, along with a way to increase these levels on the fly,&amp;rdquo; without restarting the process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-the-research-measured&#34;&gt;What the research measured&lt;/h2&gt;&#xA;&lt;p&gt;Is this actually an AI problem? The research supports something narrower and more useful than a complaint.&lt;/p&gt;&#xA;&lt;p&gt;Start with what models do well. A &lt;a href=&#34;https://arxiv.org/abs/2307.05950&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;2024 study in IEEE Transactions on Software Engineering&lt;/a&gt;&#xA;, posted on arXiv under the better title &amp;ldquo;Can LLMs Log?&amp;rdquo;, built a benchmark of 6,849 logging statements pulled from GitHub and measured how well language models fill them in. The best model picked the correct log level 74.3% of the time, and every model in the study got the level right in at least 60% of cases. AI has a working concept of severity.&lt;/p&gt;&#xA;&lt;p&gt;The content is where it comes apart. Log text topped out at a BLEU score of 0.249. And when the same code was mechanically transformed so the models had not seen it before, the degradation was not evenly spread: level accuracy fell by 1.4%, variable selection by 11.6%, and log text by 15%. The part that is a label held up. The part that carries the information did not.&lt;/p&gt;&#xA;&lt;p&gt;A &lt;a href=&#34;https://arxiv.org/abs/2607.05785&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;2026 preprint on coding agents&lt;/a&gt;&#xA; finds the same split at the system level. The researchers stripped the human-written observability out of 10 open-source and 8 industrial repositories and asked agents to put it back. Agents often picked the right places and then filled them with the wrong things. GPT-5.5 scored 0.551 on placement against 0.357 on diagnostic content; Claude Opus 4.8 scored 0.580 against 0.294.&lt;/p&gt;&#xA;&lt;p&gt;Then they ran it. Two hundred microservice systems generated from specifications, deployed on Kubernetes, with 13 kinds of production fault injected across 1,615 failure instances. The systems produced logs. Explicit, fault-specific evidence showed up for 4.95% to 13.99% of the failures depending on the model. Between a quarter and a third of the generated systems never ran at all, and scoring only the ones that did lifts the best model to 20.62%. Either number tells the same story: &lt;strong&gt;the limitation was not missing logs, it was logs that could not say which failure had happened.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The uncomfortable part is what happened when the researchers asked for observability explicitly. The agents complied by volume. Statements per instance went from 2.1 to 4.9 and diagnostic tokens from 11.5 to 22.9, while quality went down, content F1 falling from 0.36 to 0.26 as precision dropped from 0.33 to 0.20. A packaged observability skill did better on fault signals, worth between one and nine percentage points, but moved the semantic scores by 0.003 to 0.015, which is the argument I made about &lt;a href=&#34;https://davidparry.com/blog/2026/09/25/the-jig/&#34;&gt;Skills in The Jig&lt;/a&gt;&#xA; showing up in someone else&amp;rsquo;s data.&lt;/p&gt;&#xA;&lt;p&gt;Two caveats and then I will stop hedging. This is one experimental setup, and it cannot tell us how often this happens across production software generally. The agents were also generating whole systems from a specification, which is harder than the incremental work most of us actually hand them.&lt;/p&gt;&#xA;&lt;p&gt;None of this is new. Developers have always logged too little, logged too much, or picked the wrong level. What AI changes is the ratio, because a great deal of working code can now be produced without anyone spending the corresponding time learning how it fails. When the task ends at a passing test, emitting a log line is easier than deciding what a future investigator will need to know.&lt;/p&gt;&#xA;&lt;h2 id=&#34;levels-are-a-control-surface&#34;&gt;Levels are a control surface&lt;/h2&gt;&#xA;&lt;p&gt;Good logging is a set of choices about content and about control, and the levels are where those two meet.&lt;/p&gt;&#xA;&lt;p&gt;At &lt;code&gt;INFO&lt;/code&gt; I want a small number of meaningful lifecycle and business events, including enough to know which version started and whether it became ready. At &lt;code&gt;WARN&lt;/code&gt; and &lt;code&gt;ERROR&lt;/code&gt; I want the outcome and the context needed to investigate it. At &lt;code&gt;DEBUG&lt;/code&gt; and &lt;code&gt;TRACE&lt;/code&gt; I want carefully chosen detail around decisions and state changes, off during normal operation and switchable when an incident calls for it. &amp;ldquo;Payment failed&amp;rdquo; is a label. An event that identifies the dependency, the operation, the failure category, the retry attempt, and the trace ID, without carrying payment data, is a diagnosis.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-the-framework-hands-you&#34;&gt;What the framework hands you&lt;/h2&gt;&#xA;&lt;p&gt;There is a stronger version of this argument that I do not think holds: that some languages and frameworks are for production and the rest are for throwaway proof-of-concept work. Instagram runs on Django. Python&amp;rsquo;s standard library &lt;code&gt;logging&lt;/code&gt; module was modeled on log4j and has had hierarchical loggers and severity levels for more than twenty years. Serious money rides on TypeScript services. The language is not the thing that is missing.&lt;/p&gt;&#xA;&lt;p&gt;What differs is the default, and defaults are what you get when nobody is paying attention.&lt;/p&gt;&#xA;&lt;p&gt;Spring Boot is the clearest case in the other direction. Actuator ships a &lt;a href=&#34;https://docs.spring.io/spring-boot/reference/actuator/loggers.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;loggers&lt;/code&gt; endpoint&lt;/a&gt;&#xA; that reads and changes a logger&amp;rsquo;s level on a running process: &lt;code&gt;POST&lt;/code&gt; a body of &lt;code&gt;{&amp;quot;configuredLevel&amp;quot;: &amp;quot;DEBUG&amp;quot;}&lt;/code&gt; and the level changes with no restart and no deployment. That is the SRE book&amp;rsquo;s requirement, already implemented. Worth being precise about the cost, because it is not zero: only &lt;code&gt;/health&lt;/code&gt; is exposed over HTTP by default, so you opt in through &lt;code&gt;management.endpoints.web.exposure.include&lt;/code&gt; and you put it behind authentication before it goes anywhere. Add SLF4J&amp;rsquo;s per-package levels and MDC for request-scoped context, and &amp;ldquo;turn up logging for this one package on this one pod&amp;rdquo; becomes a conventional request rather than a project. I made the adjacent argument about &lt;a href=&#34;https://davidparry.com/blog/2023/03/18/redefining-error-monitoring-breaking-free-from-brittle-logs/&#34;&gt;Micrometer and stable error events&lt;/a&gt;&#xA; years ago, for the same reason.&lt;/p&gt;&#xA;&lt;p&gt;Express ships none of that. &lt;code&gt;console.log&lt;/code&gt; is the path of least resistance, the logging library is a decision someone has to make, and the endpoint for changing a level at runtime is something you build. Flask and FastAPI land in between: the levels are there because Python gives them to you, the packaged surface for changing them on a running process is not.&lt;/p&gt;&#xA;&lt;p&gt;Which is what makes this a generated-code problem rather than a taste problem. An agent reaches for the ecosystem&amp;rsquo;s default path, because that is what its training data is full of and what the scaffolding produces. Ask for a Spring Boot service and it inherits a facade, levels, and an actuator it may never have reasoned about. Ask for an Express service and it inherits &lt;code&gt;console.log&lt;/code&gt;. Neither study I cited measured language choice, so this is an argument about defaults and not a finding. But inheriting a default is still a decision about what the service will be able to tell you, and it is worth making on purpose.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-is-not-better&#34;&gt;More is not better&lt;/h2&gt;&#xA;&lt;p&gt;Volume costs money and buries the signal, and the SRE chapter points out that turning on verbose logging can make a latency problem worse and confuse the result you were trying to read. Sensitive values turn a useful diagnostic record into a security problem, which is why OWASP&amp;rsquo;s list of what to keep out of logs includes session identifiers, access tokens, passwords, encryption keys, and personal data.&lt;/p&gt;&#xA;&lt;p&gt;Logs are also one signal of three. Metrics tell you a service is failing, traces show where a request went, and logs explain the decision or state at a point along the way. &lt;a href=&#34;https://opentelemetry.io/docs/concepts/observability-primer/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenTelemetry treats all three&lt;/a&gt;&#xA; as what instrumentation has to emit, and sets the bar this way: an application is properly instrumented when developers do not need to add more instrumentation to troubleshoot an issue.&lt;/p&gt;&#xA;&lt;p&gt;That is the bar a deleted log statement fails.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-review-question&#34;&gt;The review question&lt;/h2&gt;&#xA;&lt;p&gt;So yes, logs still matter, and they matter more when code can be produced faster than a team can learn how it behaves. Where that gets settled is the runtime, which is the &lt;a href=&#34;https://davidparry.com/blog/2026/09/23/the-runtime-is-the-product-the-model-is-a-component/&#34;&gt;argument I keep coming back to&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;The review question is no longer just whether the code works. It is what the people keeping it running will be able to see when it fails, and whether they can get the detail they need without deploying again.&lt;/p&gt;&#xA;</content:encoded>
    </item>
    <item>
      <title>🔍 MCP: Enterprise Trust Through Traceability</title>
      <link>https://davidparry.com/blog/2026/07/22/mcp-enterprise-trust-through-traceability/</link>
      <pubDate>Wed, 22 Jul 2026 09:30:00 -0500</pubDate>
      <guid>https://davidparry.com/blog/2026/07/22/mcp-enterprise-trust-through-traceability/</guid>
      <description>&lt;p&gt;The headline everyone pulled out of the &lt;a href=&#34;https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Model Context Protocol (MCP) 2026-07-28 Release Candidate&lt;/a&gt;&#xA; is that MCP is going &lt;strong&gt;stateless&lt;/strong&gt;. Fair enough — it&amp;rsquo;s a genuine architectural improvement. Stateless protocols scale horizontally without sticky sessions, they cut operational complexity, and they make the infrastructure easier to deploy and reason about.&lt;/p&gt;&#xA;&lt;p&gt;But I don&amp;rsquo;t think statelessness is the change that will matter most for enterprise adoption. I think &lt;strong&gt;traceability&lt;/strong&gt; is.&lt;/p&gt;&#xA;&lt;p&gt;When I gave a conference talk on building MCP servers earlier this year, the hallway questions afterward were rarely about what a server could do. They were about what it takes to run one: how the traffic shows up in gateway logs, what a trace looks like when a tool call fails, whether any of it can be audited later. So when the release candidate landed, I read it with those questions in mind.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;The headline everyone pulled out of the &lt;a href=&#34;https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Model Context Protocol (MCP) 2026-07-28 Release Candidate&lt;/a&gt;&#xA; is that MCP is going &lt;strong&gt;stateless&lt;/strong&gt;. Fair enough — it&amp;rsquo;s a genuine architectural improvement. Stateless protocols scale horizontally without sticky sessions, they cut operational complexity, and they make the infrastructure easier to deploy and reason about.&lt;/p&gt;&#xA;&lt;p&gt;But I don&amp;rsquo;t think statelessness is the change that will matter most for enterprise adoption. I think &lt;strong&gt;traceability&lt;/strong&gt; is.&lt;/p&gt;&#xA;&lt;p&gt;When I gave a conference talk on building MCP servers earlier this year, the hallway questions afterward were rarely about what a server could do. They were about what it takes to run one: how the traffic shows up in gateway logs, what a trace looks like when a tool call fails, whether any of it can be audited later. So when the release candidate landed, I read it with those questions in mind.&lt;/p&gt;&#xA;&lt;p&gt;Two changes stood out to me, and they work as a pair.&lt;/p&gt;&#xA;&lt;p&gt;The first is &lt;a href=&#34;https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2243&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;SEP-2243&lt;/a&gt;&#xA;, which makes two headers, &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt;, required on the Streamable HTTP transport. The spec is clear about their job: they exist so load balancers, gateways, and rate limiters can route on the operation without inspecting the JSON-RPC body. What interests me is the side effect. Every layer of the stack now gets a piece of standardized, protocol-level metadata — and standardized metadata is exactly the raw material enterprise observability and audit tooling is built on.&lt;/p&gt;&#xA;&lt;p&gt;The second is &lt;a href=&#34;https://modelcontextprotocol.io/seps/414-request-meta&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;SEP-414&lt;/a&gt;&#xA;, which locks the &lt;strong&gt;W3C Trace Context&lt;/strong&gt; keys — &lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;tracestate&lt;/code&gt;, and &lt;code&gt;baggage&lt;/code&gt; — into the spec as reserved keys inside &lt;code&gt;params._meta&lt;/code&gt; of every JSON-RPC request. Note where they live: in the message, not in HTTP headers. That&amp;rsquo;s deliberate. MCP is transport-agnostic and stdio has no headers, and a single Streamable HTTP connection can multiplex many JSON-RPC messages, so trace context has to belong to the individual request rather than the connection. A trace that starts in the host application can now follow a tool call through the client SDK, the MCP server, and whatever the server calls downstream, and land in an OpenTelemetry-compatible backend as one span tree:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;jsonrpc&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tools/call&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;params&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;get_weather&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;location&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;New York&amp;#34;&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;_meta&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;traceparent&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Several SDKs were already doing this — the release candidate fixes the key names so traces correlate across implementations instead of by convention. And in the same release, MCP&amp;rsquo;s own logging capability is deprecated, with OpenTelemetry named as the path for structured observability. Read those together and the direction is unambiguous: the protocol didn&amp;rsquo;t invent its own tracing story, it adopted the one enterprises already run.&lt;/p&gt;&#xA;&lt;p&gt;That matters because enterprises are not building greenfield. They already have API gateways, OpenTelemetry, centralized logging, SIEM platforms, operational dashboards, and distributed tracing — and years of trust invested in all of it. A new protocol gets adopted when it slots into that existing machinery, not when it asks to be operated as a special case beside it. Routing headers at the transport layer, W3C Trace Context in the message — small design decisions with a large consequence, because together they mean MCP can be operated alongside everything else instead of babysat beside it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-enterprise-traceability-looks-like&#34;&gt;What Enterprise Traceability Looks Like&lt;/h2&gt;&#xA;&lt;p&gt;The important property is that the new metadata enriches an existing trace without changing how distributed tracing works.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;                    End User&#xA;                       │&#xA;                       ▼&#xA;                  API Gateway ────────────────┐&#xA;                       │                      │&#xA;                       ▼                      │&#xA;            Spring Boot / Spring AI           │&#xA;                       │                      │&#xA;                       ▼                      ▼&#xA;                  MCP Client         Logs · Metrics · SIEM&#xA;                       │                      ▲&#xA;    Mcp-Method         │                      │&#xA;    Mcp-Name    ──────►│ ─────────────────────┤&#xA;    (HTTP headers)     │                      │&#xA;                       │                      │&#xA;    traceparent        │                      │&#xA;    tracestate  ──────►│                      │&#xA;    (in _meta)         │                      │&#xA;                       ▼                      │&#xA;                  MCP Server ─────────────────┤&#xA;                       │                      │&#xA;                       ▼                      │&#xA;                      Tool ───────────────────┘&#xA;&#xA;  W3C Trace Context propagates through every hop above — over HTTP&#xA;  headers on ordinary hops, inside _meta on the MCP hop. The routing&#xA;  headers add protocol-specific metadata to that same trace.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The distributed trace flows exactly as it does today. The routing headers give the infrastructure something to key on, and the &lt;code&gt;_meta&lt;/code&gt; trace keys keep the MCP hop stitched into the trace you&amp;rsquo;re already collecting.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-questions-a-platform-team-asks-first&#34;&gt;The Questions a Platform Team Asks First&lt;/h2&gt;&#xA;&lt;p&gt;Enterprise engineering organizations rarely get stuck because they can&amp;rsquo;t scale a service. They get stuck because they can&amp;rsquo;t answer questions after the fact:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Which MCP method executed, on which server, running which tool?&lt;/li&gt;&#xA;&lt;li&gt;Which distributed trace contains this interaction, and how does it line up with the gateway logs?&lt;/li&gt;&#xA;&lt;li&gt;Which agent initiated the request, and why did it fail?&lt;/li&gt;&#xA;&lt;li&gt;Can we reproduce it — and can we audit it six months from now?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These aren&amp;rsquo;t exotic questions. They&amp;rsquo;re the ones a platform team asks before it agrees to support new infrastructure in production, and standardized protocol metadata is what makes them answerable. With &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; riding alongside the trace context, requests correlate across services and gateways without custom parsing, dashboards and rate limits key off the operation instead of the payload, and the telemetry looks the same across different MCP implementations. That&amp;rsquo;s the difference between something a platform team can confidently run in production and something that stays a proof of concept.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fan-out-is-where-this-gets-expensive&#34;&gt;Fan-Out Is Where This Gets Expensive&lt;/h2&gt;&#xA;&lt;p&gt;The stakes go up as organizations move toward agentic software. A single user request can fan out across multiple agents, several MCP servers, and dozens of tool invocations before anything comes back. Without standardized metadata, reconstructing what actually happened in that fan-out is slow and often guesswork.&lt;/p&gt;&#xA;&lt;p&gt;With the routing headers and trace-context keys in place, each MCP interaction correlates cleanly with the telemetry you already collect, and the whole system gets easier to operate and troubleshoot. This is the same argument I keep coming back to: agentic systems only become &lt;em&gt;enterprise&lt;/em&gt; systems when they&amp;rsquo;re as observable, governable, and auditable as every other critical application in the estate. This release moves MCP another step toward that bar.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-than-stateless&#34;&gt;More Than Stateless&lt;/h2&gt;&#xA;&lt;p&gt;Statelessness earns its headlines. Simpler deployments, better scalability, and lower operational complexity are real wins, and the &lt;a href=&#34;https://modelcontextprotocol.io/specification/draft/changelog&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;changelog&lt;/a&gt;&#xA; is worth reading in full. But the larger enterprise story is the standardized metadata that integrates naturally with the observability and tracing ecosystems organizations already trust.&lt;/p&gt;&#xA;&lt;p&gt;Platform teams want a protocol that fits the infrastructure they already run, and the technologies that win in the enterprise are rarely the ones with the longest feature lists.&lt;/p&gt;&#xA;&lt;p&gt;The claim I&amp;rsquo;ll defend is narrower than &amp;ldquo;MCP is enterprise-ready&amp;rdquo;: two required routing headers and three reserved trace-context keys quietly gave every gateway, trace, and audit log a common vocabulary for MCP traffic. In my experience, that&amp;rsquo;s the kind of unglamorous change that decides whether a protocol makes it out of the proof-of-concept stage.&lt;/p&gt;&#xA;</content:encoded>
    </item>
  </channel>
</rss>
