<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: observability</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/observability.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2026-10-06T19:07:31+00:00</updated><author><name>Simon Willison</name></author><entry><title>Using Parseable with Datasette for OpenTelemetry traces</title><link href="https://simonwillison.net/2026/Oct/6/datasette-parseable-opentelemetry/" rel="alternate"/><published>2026-10-06T19:07:31+00:00</published><updated>2026-10-06T19:07:31+00:00</updated><id>https://simonwillison.net/2026/Oct/6/datasette-parseable-opentelemetry/</id><summary type="html">
    
        &lt;p&gt;&lt;strong&gt;TIL:&lt;/strong&gt; &lt;a href="https://til.simonwillison.net/datasette/datasette-parseable-opentelemetry"&gt;Using Parseable with Datasette for OpenTelemetry traces&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;I &lt;a href="https://news.ycombinator.com/item?id=49978171"&gt;saw Parseable in a Show HN&lt;/a&gt; today - it's a new observability platform with both an &lt;a href="https://github.com/parseablehq/parseable"&gt;open source (AGPL)&lt;/a&gt; Rust implementation (a single ~180MB binary), an "Enterprise" version with extra features and a cloud hosted option.&lt;/p&gt;
&lt;p&gt;Since &lt;a href="https://docs.datasette.io/en/latest/changelog.html#a41-2026-09-24"&gt;Datasette 1.0a41 added OpenTelemetry support&lt;/a&gt; (thanks, Alex Garcia), I decided to fire up Codex and have it figure out how to run Parseable and feed it traces from Datasette.&lt;/p&gt;
&lt;p&gt;Here's my (human-written) TIL showing the patterns that worked, and here's a screenshot of a Datasette trace displayed within the Parseable localhost web application:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of a trace detail view in an observability web app, with a span waterfall overlaid on a dimmed navigation sidebar and filter column. Dimmed sidebar: breadcrumb &amp;quot;Community &amp;gt; Traces &amp;gt; datas&amp;quot; (cut off), search box &amp;quot;Search... ⌘K&amp;quot;, nav items &amp;quot;Home&amp;quot;, &amp;quot;Ingest telemetry&amp;quot;, section &amp;quot;ANALYZE&amp;quot;: &amp;quot;Keystone&amp;quot;, &amp;quot;Dashboards&amp;quot;, &amp;quot;SQL Editor&amp;quot;, section &amp;quot;OBSERVE&amp;quot;: &amp;quot;Logs&amp;quot;, &amp;quot;Metrics&amp;quot;, &amp;quot;Traces&amp;quot; (selected), &amp;quot;APM&amp;quot;, &amp;quot;Agents&amp;quot;, section &amp;quot;MONITOR&amp;quot;: &amp;quot;Alerts&amp;quot;, &amp;quot;Errors&amp;quot;, section &amp;quot;DATA&amp;quot;: &amp;quot;Datasets&amp;quot;, and at the bottom &amp;quot;Settings&amp;quot;, &amp;quot;Book a call&amp;quot;, &amp;quot;Support&amp;quot;. Dimmed filter column, cut off at the right edge: &amp;quot;Search fi&amp;quot;, &amp;quot;Core&amp;quot;, &amp;quot;Log format&amp;quot;, &amp;quot;User agent&amp;quot;, &amp;quot;Source IPs&amp;quot;, &amp;quot;Error&amp;quot;, &amp;quot;Service&amp;quot;, &amp;quot;service.ins&amp;quot;, &amp;quot;service.na&amp;quot;, &amp;quot;datasett&amp;quot; (checked), &amp;quot;Span&amp;quot;, &amp;quot;Database&amp;quot;, &amp;quot;HTTP&amp;quot;, &amp;quot;http.reque&amp;quot;, &amp;quot;NULL&amp;quot; (unchecked), &amp;quot;GET&amp;quot; (checked), &amp;quot;http.respo&amp;quot;, &amp;quot;http.route&amp;quot;, &amp;quot;Server&amp;quot;, &amp;quot;server.add&amp;quot;, &amp;quot;Telemetry&amp;quot;, &amp;quot;URL&amp;quot;, &amp;quot;All fields&amp;quot;. Trace panel header: &amp;quot;Trace detail &amp;gt; 6f819a2170bcd1e91c6ea3ae236ec60b&amp;quot; with a copy icon, a &amp;quot;Related logs&amp;quot; button and a close X. Summary: &amp;quot;Start time 6:56 PM, Oct 6, 2026 UTC&amp;quot;, &amp;quot;Duration 40.9 ms&amp;quot;, &amp;quot;Spans 247&amp;quot;. A minimap with axis &amp;quot;0ns 10.2ms 20.5ms 30.7ms 40.9ms&amp;quot; shows many short span bars cascading diagonally from top left toward the lower middle, with a few longer bars. Below is a span table with a &amp;quot;Span name&amp;quot; header, a &amp;quot;Search spans...&amp;quot; box, collapse and expand buttons, and a timeline axis &amp;quot;0ns 10.2ms 20.5ms 30.7ms 40.9ms&amp;quot;. Rows (name, service, duration): root span with collapse toggle &amp;quot;123&amp;quot;, &amp;quot;GET /...&amp;quot; &amp;quot;datasette...&amp;quot; 40.9ms spanning the full timeline; then alternating rows where each &amp;quot;db.query&amp;quot; has a collapse toggle &amp;quot;1&amp;quot;: db.query datasette-local 679µs, db.query.execute datasette-local 278µs, db.query datasette-local 341µs, db.query.execute datasette-local 55µs, db.query datasette-local 357µs, db.query.execute datasette-local 197µs, db.query datasette-local 330µs, db.query.execute datasette-local 73µs, db.query datasette-local 2.26ms, db.query.execute datasette-local 2.02ms, db.query datasette-local 232µs, db.query.execute datasette-local 64µs, db.query datasette-local 207µs, db.query.execute datasette-local 71µs, db.query datasette-local 6.11ms. The child span bars start progressively later across the early part of the timeline." src="https://raw.githubusercontent.com/simonw/til/refs/heads/main/datasette/datasette-parsable.webp" /&gt;&lt;/p&gt;
    
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/datasette"&gt;datasette&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/alex-garcia"&gt;alex-garcia&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/opentelemetry"&gt;opentelemetry&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="datasette"/><category term="observability"/><category term="alex-garcia"/><category term="opentelemetry"/></entry><entry><title>Don't sleep on wrapture</title><link href="https://simonwillison.net/2026/Sep/11/wrapture/" rel="alternate"/><published>2026-09-11T13:51:32+00:00</published><updated>2026-09-11T13:51:32+00:00</updated><id>https://simonwillison.net/2026/Sep/11/wrapture/</id><summary type="html">
    &lt;p&gt;Graham Dumpleton's new monkey patching package &lt;a href="https://wrapture.readthedocs.io/"&gt;wrapture&lt;/a&gt; is shaping up to be an indispensable tool for Python developers. I'm not sure why I've seen so little buzz about it!&lt;/p&gt;
&lt;p&gt;Graham has been posting new tutorials for it almost daily since &lt;a href="https://simonwillison.net/2026/Aug/31/introducing-wrapture/"&gt;the initial release&lt;/a&gt; on August 31st. Here's everything he's published so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/08/introducing-wrapture/"&gt;Introducing wrapture&lt;/a&gt; - a new monkey patching library that serves both testing and observability (think New Relic style tracing) at the same time.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/unit-testing-with-wrapture/"&gt;Unit testing with wrapture&lt;/a&gt; - how to use it for the same kinds of thing as &lt;code&gt;unittest.mock&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/recording-calls-with-wrapture/"&gt;Recording calls with wrapture&lt;/a&gt;  - recording method calls as timelines and processing and displaying them as trees.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/phased-behaviour-in-wrapture/"&gt;Phased behaviour in wrapture&lt;/a&gt;  - arranging patched methods to change behavior across multiple calls.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/beyond-callables-in-wrapture/"&gt;Beyond callables in wrapture&lt;/a&gt; - monkey patching attributes, dictionaries, generators.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/live-tracing-with-wrapture/"&gt;Live tracing with wrapture&lt;/a&gt;  - tracing a live application to see exactly how it works.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/zero-code-tracing-with-wrapture/"&gt;Zero-code tracing with wrapture&lt;/a&gt;  - configuring tracing in a separate TOML file without modifying Python code at all.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/tracing-flask-with-wrapture/"&gt;Tracing Flask with wrapture&lt;/a&gt;  - using the separate &lt;a href="https://github.com/GrahamDumpleton/wrapture-instrumentation"&gt;wrapture-instrumenation&lt;/a&gt; package to instrument a Flask application. That package also provides instrumentation for &lt;code&gt;aiohttp.client&lt;/code&gt;, &lt;code&gt;aiohttp.web&lt;/code&gt;, &lt;code&gt;django&lt;/code&gt;, &lt;code&gt;fastapi&lt;/code&gt;, &lt;code&gt;flask&lt;/code&gt;, &lt;code&gt;grpc&lt;/code&gt;, &lt;code&gt;http.client&lt;/code&gt;, &lt;code&gt;httpx&lt;/code&gt;, &lt;code&gt;jinja2&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;sqlalchemy&lt;/code&gt;, &lt;code&gt;sqlite3&lt;/code&gt;, &lt;code&gt;starlette&lt;/code&gt;, &lt;code&gt;urllib.request&lt;/code&gt;, &lt;code&gt;urllib3&lt;/code&gt;, &lt;code&gt;uvicorn&lt;/code&gt;, &lt;code&gt;werkzeug.serving&lt;/code&gt;, &lt;code&gt;wsgiref.simple_server&lt;/code&gt;, &lt;code&gt;xmlrpc.client&lt;/code&gt;, &lt;code&gt;xmlrpc.server&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/finding-slow-code-with-wrapture/"&gt;Finding slow code with wrapture&lt;/a&gt; - wrapture's tools for recording timing information, both individually and aggregated across multiple calls.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grahamdumpleton.me/posts/2026/09/opentelemetry-export-in-wrapture/"&gt;OpenTelemetry export in wrapture&lt;/a&gt; - exporting traces to OpenTelemetry.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Graham also has a &lt;a href="https://github.com/GrahamDumpleton/wrapture-workshops"&gt;set of interactive workshops&lt;/a&gt; for wrapture, implemented as JupyterLab notebooks.&lt;/p&gt;
&lt;p&gt;Wrapture is still alpha software but it's already very usable - especially given you can configure and try it out with a TOML file without modifying any Python code at all.&lt;/p&gt;
&lt;p&gt;This feels like one of those Swiss Army Knife packages that, once mastered, will provide value against all sorts of problems for years to come.&lt;/p&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/open-source"&gt;open-source&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/observability"&gt;observability&lt;/a&gt;&lt;/p&gt;



</summary><category term="graham-dumpleton"/><category term="monkey-patching"/><category term="open-source"/><category term="python"/><category term="testing"/><category term="observability"/></entry><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>Did you know about Instruments?</title><link href="https://simonwillison.net/2024/Jul/26/did-you-know-about-instruments/" rel="alternate"/><published>2024-07-26T13:06:38+00:00</published><updated>2024-07-26T13:06:38+00:00</updated><id>https://simonwillison.net/2024/Jul/26/did-you-know-about-instruments/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://registerspill.thorstenball.com/p/did-you-know-about-instruments"&gt;Did you know about Instruments?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Thorsten Ball shows how the macOS Instruments app (installed as part of Xcode) can be used to run a CPU profiler against &lt;em&gt;any&lt;/em&gt; application - not just code written in Swift/Objective C.&lt;/p&gt;
&lt;p&gt;I tried this against a Python process running &lt;a href="https://llm.datasette.io/"&gt;LLM&lt;/a&gt; executing a Llama 3.1 prompt with my new &lt;a href="https://github.com/simonw/llm-gguf"&gt;llm-gguf&lt;/a&gt; plugin and captured this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of a deep nested stack trace showing _PyFunction_Vectorcall from python3.10 calling PyCFuncPtr_call _ctypes.cpython-310-darwin.so which then calls ggml_ methods in libggml.dylib" src="https://static.simonwillison.net/static/2024/instruments-ggml.jpg" /&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/kr9od0/did_you_know_about_instruments"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


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



</summary><category term="profiling"/><category term="python"/><category term="observability"/></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><entry><title>Roblox Return to Service 10/28-10/31 2021</title><link href="https://simonwillison.net/2022/Jan/21/roblox/" rel="alternate"/><published>2022-01-21T16:41:00+00:00</published><updated>2022-01-21T16:41:00+00:00</updated><id>https://simonwillison.net/2022/Jan/21/roblox/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.roblox.com/2022/01/roblox-return-to-service-10-28-10-31-2021/"&gt;Roblox Return to Service 10/28-10/31 2021&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
A particularly good example of a public postmortem on an outage. Roblox was down for 72 hours last year, as a result of an extremely complex set of circumstances which took a lot of effort to uncover. It’s interesting to think through what kind of monitoring you would need to have in place to help identify the root cause of this kind of issue.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/benbjohnson/status/1484288578918047745"&gt;@benbjohnson&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


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



</summary><category term="ops"/><category term="observability"/><category term="postmortem"/></entry><entry><title>Quoting Brendan Gregg</title><link href="https://simonwillison.net/2021/Jun/8/observability/" rel="alternate"/><published>2021-06-08T19:33:16+00:00</published><updated>2021-06-08T19:33:16+00:00</updated><id>https://simonwillison.net/2021/Jun/8/observability/</id><summary type="html">
    &lt;blockquote cite="http://www.brendangregg.com/blog/2021-05-23/what-is-observability.html"&gt;&lt;p&gt;When I was a performance consultant I'd show up to random companies who wanted me to fix their computer performance issues. If they trusted me with a login to their production servers, I could help them a lot quicker. To get that trust I knew which tools looked but didn't touch: Which were observability tools and which were experimental tools. "I'll start with observability tools only" is something I'd say at the start of every engagement.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="http://www.brendangregg.com/blog/2021-05-23/what-is-observability.html"&gt;Brendan Gregg&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/performance"&gt;performance&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/brendan-gregg"&gt;brendan-gregg&lt;/a&gt;&lt;/p&gt;



</summary><category term="performance"/><category term="observability"/><category term="brendan-gregg"/></entry><entry><title>Quoting Charity Majors</title><link href="https://simonwillison.net/2020/Jul/19/charity-majors/" rel="alternate"/><published>2020-07-19T16:05:08+00:00</published><updated>2020-07-19T16:05:08+00:00</updated><id>https://simonwillison.net/2020/Jul/19/charity-majors/</id><summary type="html">
    &lt;blockquote cite="https://increment.com/testing/i-test-in-production/"&gt;&lt;p&gt;Instead of seeing instrumentation as a last-ditch effort of strings and metrics, we must think about propagating the full context of a request and emitting it at regular pulses. No pull request should ever be accepted unless the engineer can answer the question, “How will I know if this breaks?”&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://increment.com/testing/i-test-in-production/"&gt;Charity Majors&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/charity-majors"&gt;charity-majors&lt;/a&gt;&lt;/p&gt;



</summary><category term="observability"/><category term="charity-majors"/></entry><entry><title>Logs vs. metrics: a false dichotomy</title><link href="https://simonwillison.net/2019/Aug/3/logs-vs-metrics/" rel="alternate"/><published>2019-08-03T16:46:55+00:00</published><updated>2019-08-03T16:46:55+00:00</updated><id>https://simonwillison.net/2019/Aug/3/logs-vs-metrics/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://whiteink.com/2019/logs-vs-metrics-a-false-dichotomy/"&gt;Logs vs. metrics: a false dichotomy&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Nick Stenning discusses the differences between logs and metrics: most notably that metrics can be derived from logs but logs cannot be reconstituted starting with time-series metrics.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/mipsytipsy/status/1157503142134607872"&gt;Charity Majors&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


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



</summary><category term="logging"/><category term="observability"/></entry><entry><title>Targeted diagnostic logging in production</title><link href="https://simonwillison.net/2019/Jul/24/targeted-diagnostic-logging-production/" rel="alternate"/><published>2019-07-24T05:44:39+00:00</published><updated>2019-07-24T05:44:39+00:00</updated><id>https://simonwillison.net/2019/Jul/24/targeted-diagnostic-logging-production/</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://tersesystems.com/blog/2019/07/22/targeted-diagnostic-logging-in-production/"&gt;Targeted diagnostic logging in production&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Will Sargent defines diagnostic logging as “debug logging statements with an audience”, and proposes controlling this style if logging via a feature flat system to allow detailed logging to be turned on in production against a selected subset if users in order to help debug difficult problems. Lots of great background material in the topic of observability here too.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/mipsytipsy/status/1153889935536975872"&gt;Charity Majors&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


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



</summary><category term="logging"/><category term="observability"/></entry><entry><title>Quoting Clint Sharp</title><link href="https://simonwillison.net/2019/Feb/25/clint-sharp/" rel="alternate"/><published>2019-02-25T22:15:45+00:00</published><updated>2019-02-25T22:15:45+00:00</updated><id>https://simonwillison.net/2019/Feb/25/clint-sharp/</id><summary type="html">
    &lt;blockquote cite="https://twitter.com/clintsharp/status/1098848313170784256"&gt;&lt;p&gt;Metrics are lossily compressed logs. Traces are logs with parent child relationships between entries. The only reason we have three terms is because getting value from them has required different compromises to make them cost effective.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://twitter.com/clintsharp/status/1098848313170784256"&gt;Clint Sharp&lt;/a&gt;&lt;/p&gt;

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



</summary><category term="logs"/><category term="observability"/></entry></feed>