<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: opentelemetry</title><link href="http://feeds.simonwillison.net/" rel="alternate"/><link href="http://feeds.simonwillison.net/tags/opentelemetry.atom" rel="self"/><id>http://feeds.simonwillison.net/</id><updated>2026-08-31T23:59:36+00:00</updated><author><name>Simon Willison</name></author><entry><title>Introducing wrapture</title><link href="https://simonwillison.net/2026/Aug/31/introducing-wrapture/" rel="alternate"/><published>2026-08-31T23:59:36+00:00</published><updated>2026-08-31T23:59:36+00:00</updated><id>https://simonwillison.net/2026/Aug/31/introducing-wrapture/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/08/introducing-wrapture/"&gt;Introducing wrapture&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
New from Graham Dumpleton (of &lt;a href="https://pypi.org/project/wrapt/"&gt;wrapt&lt;/a&gt;, mod_wsgi, and New Relic's Python agent fame), who describes Wrapture as taking the monkeypatching ideas from wrapt and extending them to apply to testing and tracing at the same time.&lt;/p&gt;
&lt;p&gt;Wrapture (&lt;a href="https://wrapture.readthedocs.io/"&gt;full documentation here&lt;/a&gt;) makes it easy to wrap any function or method such that all access can be traced, or can be overridden to return a different value.&lt;/p&gt;
&lt;p&gt;It acts as both an alternative to &lt;code&gt;unittest.mock&lt;/code&gt; and a way to implement tracing against an existing project:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Attaching observation to code you do not control, recording what flows through it, and doing so without disturbing the program being watched, is a problem I have never really stopped thinking about.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Wrapture includes &lt;a href="https://wrapture.readthedocs.io/en/latest/otel-export.html"&gt;OpenTelemetry support&lt;/a&gt; and even has an entirely configuration-based mechanism for adding tracing to an existing Python project, which looks like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-toml"&gt;&lt;pre&gt;&lt;span class="pl-smi"&gt;capture&lt;/span&gt; = &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;summary&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;

[[&lt;span class="pl-en"&gt;observe&lt;/span&gt;]]
&lt;span class="pl-smi"&gt;target&lt;/span&gt; = &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;domain:Calculator&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-smi"&gt;name&lt;/span&gt; = [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;outer&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;inner&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;]

[[&lt;span class="pl-en"&gt;sink&lt;/span&gt;]]
&lt;span class="pl-smi"&gt;type&lt;/span&gt; = &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;jsonlines&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-smi"&gt;path&lt;/span&gt; = &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;trace.jsonl&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is still a very young project - just a few weeks old - but it's off to a very promising start.&lt;/p&gt;
&lt;p&gt;Interestingly, this is also Graham's first attempt at  large entirely agent-driven project:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every line of code and documentation in wrapture was written by an AI assistant working under my direction. I want to be upfront about that, and equally upfront about what it was not. This was not vibe coding, where a one-shot prompt produces a pile of generated code and the person driving hopes for the best because they lack the knowledge to judge what came back. Vibe coding has earned its bad reputation. I engineered wrapture carefully from the start. I have spent a long time in this particular corner of Python and knew exactly what the result needed to be, and the AI was the means of producing it rather than the source of the design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a follow-up post, &lt;a href="https://grahamdumpleton.me/posts/2026/09/unit-testing-with-wrapture/"&gt;Unit testing with wrapture&lt;/a&gt;, Graham shows the testing patterns supported by the new library:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;def&lt;/span&gt; &lt;span class="pl-en"&gt;test_stub_with_wrapture&lt;/span&gt;():
    &lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-s1"&gt;wrapture&lt;/span&gt;.&lt;span class="pl-c1"&gt;binding&lt;/span&gt;(
        &lt;span class="pl-v"&gt;Gateway&lt;/span&gt;, &lt;span class="pl-s"&gt;"charge"&lt;/span&gt;
    ).&lt;span class="pl-c1"&gt;on_call&lt;/span&gt;.&lt;span class="pl-c1"&gt;returns&lt;/span&gt;({
        &lt;span class="pl-s"&gt;"id"&lt;/span&gt;: &lt;span class="pl-s"&gt;"stub"&lt;/span&gt;, &lt;span class="pl-s"&gt;"amount"&lt;/span&gt;: &lt;span class="pl-c1"&gt;0&lt;/span&gt;}
    ):
        &lt;span class="pl-k"&gt;assert&lt;/span&gt; &lt;span class="pl-en"&gt;OrderService&lt;/span&gt;().&lt;span class="pl-c1"&gt;place&lt;/span&gt;(
            &lt;span class="pl-c1"&gt;500&lt;/span&gt;
        )[&lt;span class="pl-s"&gt;"id"&lt;/span&gt;] &lt;span class="pl-c1"&gt;==&lt;/span&gt; &lt;span class="pl-s"&gt;"stub"&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;And this neat example of a test that calls and then modifies the return value from the original method:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;def&lt;/span&gt; &lt;span class="pl-en"&gt;test_pinned_result_with_wrapture&lt;/span&gt;():
    &lt;span class="pl-s1"&gt;charge&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;wrapture&lt;/span&gt;.&lt;span class="pl-c1"&gt;binding&lt;/span&gt;(
        &lt;span class="pl-v"&gt;Gateway&lt;/span&gt;, &lt;span class="pl-s"&gt;"charge"&lt;/span&gt;
    )
    &lt;span class="pl-s1"&gt;charge&lt;/span&gt;.&lt;span class="pl-c1"&gt;on_call&lt;/span&gt;.&lt;span class="pl-c1"&gt;transforms_result&lt;/span&gt;(
        &lt;span class="pl-k"&gt;lambda&lt;/span&gt; &lt;span class="pl-s1"&gt;r&lt;/span&gt;: {&lt;span class="pl-c1"&gt;**&lt;/span&gt;&lt;span class="pl-s1"&gt;r&lt;/span&gt;, &lt;span class="pl-s"&gt;"id"&lt;/span&gt;: &lt;span class="pl-s"&gt;"ch_TEST"&lt;/span&gt;}
    )
    &lt;span class="pl-k"&gt;with&lt;/span&gt; &lt;span class="pl-s1"&gt;charge&lt;/span&gt;:
        &lt;span class="pl-k"&gt;assert&lt;/span&gt; &lt;span class="pl-en"&gt;OrderService&lt;/span&gt;().&lt;span class="pl-c1"&gt;place&lt;/span&gt;(
           &lt;span class="pl-c1"&gt;500&lt;/span&gt;
        ) &lt;span class="pl-c1"&gt;==&lt;/span&gt; {
            &lt;span class="pl-s"&gt;"id"&lt;/span&gt;: &lt;span class="pl-s"&gt;"ch_TEST"&lt;/span&gt;, &lt;span class="pl-s"&gt;"amount"&lt;/span&gt;: &lt;span class="pl-c1"&gt;500&lt;/span&gt;
        }&lt;/pre&gt;

&lt;p&gt;(In both of these examples the &lt;code&gt;OrderService().place(...)&lt;/code&gt; method calls &lt;code&gt;Gateway().charge(...)&lt;/code&gt;.)


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/graham-dumpleton"&gt;graham-dumpleton&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/monkey-patching"&gt;monkey-patching&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/testing"&gt;testing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pytest"&gt;pytest&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/agentic-engineering"&gt;agentic-engineering&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/opentelemetry"&gt;opentelemetry&lt;/a&gt;&lt;/p&gt;



</summary><category term="graham-dumpleton"/><category term="monkey-patching"/><category term="python"/><category term="testing"/><category term="pytest"/><category term="observability"/><category term="ai-assisted-programming"/><category term="agentic-engineering"/><category term="opentelemetry"/></entry><entry><title>Mermaid Gantt diagrams are great for displaying distributed traces in Markdown</title><link href="https://simonwillison.net/2024/Jul/16/mermaid-gantt-diagrams/" rel="alternate"/><published>2024-07-16T22:10:33+00:00</published><updated>2024-07-16T22:10:33+00:00</updated><id>https://simonwillison.net/2024/Jul/16/mermaid-gantt-diagrams/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://brycemecum.com/2023/03/31/til-mermaid-tracing/"&gt;Mermaid Gantt diagrams are great for displaying distributed traces in Markdown&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Bryce Mecum demonstrates how Mermaid &lt;code&gt;gantt&lt;/code&gt; diagrams can be used to render trace information, such as the traces you might get from OpenTelemetry. I tried this out &lt;a href="https://gist.github.com/simonw/01c0440845516be42ddc4a9023181e75"&gt;in a Gist&lt;/a&gt; and it works really well - GitHub Flavored Markdown will turn any fenced code block tagged &lt;code&gt;mermaid&lt;/code&gt; containing a &lt;code&gt;gantt&lt;/code&gt; definition into a neat rendered diagram.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/markdown"&gt;markdown&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mermaid"&gt;mermaid&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/opentelemetry"&gt;opentelemetry&lt;/a&gt;&lt;/p&gt;



</summary><category term="markdown"/><category term="mermaid"/><category term="opentelemetry"/></entry><entry><title>All you need is Wide Events, not “Metrics, Logs and Traces”</title><link href="https://simonwillison.net/2024/Feb/27/all-you-need-is-wide-events-not-metrics-logs-and-traces/" rel="alternate"/><published>2024-02-27T22:57:14+00:00</published><updated>2024-02-27T22:57:14+00:00</updated><id>https://simonwillison.net/2024/Feb/27/all-you-need-is-wide-events-not-metrics-logs-and-traces/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://isburmistrov.substack.com/p/all-you-need-is-wide-events-not-metrics"&gt;All you need is Wide Events, not “Metrics, Logs and Traces”&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I’ve heard great things about Meta’s internal observability platform Scuba, here’s an explanation from ex-Meta engineer Ivan Burmistrov describing the value it provides and comparing it to the widely used OpenTelemetry stack.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=39529775"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/facebook"&gt;facebook&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/opentelemetry"&gt;opentelemetry&lt;/a&gt;&lt;/p&gt;



</summary><category term="facebook"/><category term="observability"/><category term="opentelemetry"/></entry></feed>