<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tarek E</title>
    <description>The latest articles on DEV Community by Tarek E (@telilabs).</description>
    <link>https://dev.to/telilabs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3862197%2F332fc355-ceb6-4bc4-8435-41e703960f75.jpeg</url>
      <title>DEV Community: Tarek E</title>
      <link>https://dev.to/telilabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/telilabs"/>
    <language>en</language>
    <item>
      <title>Observability - A Counter in RAM, an ID in a Header, and a Batch Export</title>
      <dc:creator>Tarek E</dc:creator>
      <pubDate>Fri, 14 Aug 2026 21:49:37 +0000</pubDate>
      <link>https://dev.to/telilabs/observability-a-counter-in-ram-an-id-in-a-header-and-a-batch-export-h41</link>
      <guid>https://dev.to/telilabs/observability-a-counter-in-ram-an-id-in-a-header-and-a-batch-export-h41</guid>
      <description>&lt;p&gt;For a long time, my mental model of observability was this: you import an SDK, sprinkle some calls through your code, each call fires off data to a server somewhere, and a dashboard reads it back. A logging system with extra steps.&lt;/p&gt;

&lt;p&gt;That model is wrong in a specific, interesting way. And I couldn't see &lt;em&gt;how&lt;/em&gt; it was wrong until I stopped looking at the dashboards and started looking at what actually gets emitted, and how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The seductive wrong model
&lt;/h2&gt;

&lt;p&gt;The wrong model is seductive because the plumbing really does look identical. Logging: emit, store, search. Observability: emit, store, query. Same loop, right?&lt;/p&gt;

&lt;p&gt;So my working theory became: observability is logging plus some fancy logic to analyze the logs.&lt;/p&gt;

&lt;p&gt;Close. But no. The difference isn't in the analysis. It's in the &lt;strong&gt;emission&lt;/strong&gt; — and it splits into three mechanisms that have almost nothing in common with each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descent one: metrics aren't events at all
&lt;/h2&gt;

&lt;p&gt;A metric is not a record you write. It's a &lt;strong&gt;number sitting in your app's memory&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;requests_total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;// 1, 2, 3...&lt;/span&gt;
&lt;span class="nx"&gt;request_duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.23&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// adds to a histogram&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing is sent when this line runs. The number just changes in RAM. Periodically — every 15 seconds, say — either a backend scrapes an endpoint your app exposes, or a collector ships the current values out.&lt;/p&gt;

&lt;p&gt;That's why metrics are absurdly cheap: a million requests is one counter reading "1,000,000", not a million records. You could never reconstruct a clean p99 latency graph by parsing log text. The histogram was built for it at write time.&lt;/p&gt;

&lt;p&gt;And the stateless-container objection answers itself: the in-memory counter is disposable. Each instance flushes to the backend on a schedule (on serverless, a sidecar collector even does a final flush at shutdown), and the backend sums across instances. The durable truth never lived in your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descent two: logs are the familiar part
&lt;/h2&gt;

&lt;p&gt;Logs work exactly the way I always assumed everything worked: an event, written out, shipped, searched.&lt;/p&gt;

&lt;p&gt;The only upgrade observability adds is one field, injected automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payment failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;trace_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;trace_id&lt;/code&gt; looks trivial. It's the glue for everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descent three: the trace, or the part that felt like magic
&lt;/h2&gt;

&lt;p&gt;Distributed tracing was the piece I couldn't demystify. A request hops across five services and somehow the platform shows me the whole path as one tree. Surely something sophisticated is happening.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;When service A calls service B, the SDK stuffs the trace ID into the outgoing request. For HTTP, it's literally a header — &lt;code&gt;traceparent&lt;/code&gt;, a W3C standard. For gRPC, the same ID rides in the metadata (which &lt;em&gt;is&lt;/em&gt; HTTP/2 headers underneath). For a message queue, it goes in the message headers.&lt;/p&gt;

&lt;p&gt;Service B reads the header and says: I'm part of trace &lt;code&gt;abc&lt;/code&gt;, my parent is span 1. Each service exports its spans independently. The backend reassembles the tree later, matching parent and child IDs like a linked list.&lt;/p&gt;

&lt;p&gt;That's the entire trick. No agent watching the network. No distributed coordination. &lt;strong&gt;An ID, copied into a header, over and over.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The click
&lt;/h2&gt;

&lt;p&gt;Here's where it snapped into place.&lt;/p&gt;

&lt;p&gt;Observability is not one system. It's three mechanically different emitters that happen to share a pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;number in RAM&lt;/strong&gt;, sampled on a timer&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;event&lt;/strong&gt;, enriched with an ID and shipped&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;ID in a header&lt;/strong&gt;, propagated hop by hop and reassembled later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the reason no amount of after-the-fact log analysis can replace it: if the trace ID was never propagated at request time, no analysis can invent it. The structure has to exist &lt;em&gt;when the data is born&lt;/em&gt;. The dashboard is downstream of a decision made in a header, milliseconds earlier, inside your request path.&lt;/p&gt;

&lt;p&gt;Oh. It's just a counter, a log line with an ID, and a header. That's it.&lt;/p&gt;

&lt;p&gt;The fancy part was never the analysis. It was agreeing — across languages, frameworks, and vendors — on what to emit and what to call it. That's what OpenTelemetry actually is: not a tool, a treaty.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt; is the ability to understand a system's internal state purely from what it emits — so you can answer questions you never thought to ask in advance. It works because the emitted signals carry their relationships with them: metrics as live numbers, logs as events, traces as an ID passed hand-to-hand through every request. The linking happens at emission time; everything after is just reading.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>observability</category>
      <category>opentelemetry</category>
      <category>backend</category>
    </item>
    <item>
      <title>OSI Model - The Internet Is Just Envelopes Thrown Away at Every Router</title>
      <dc:creator>Tarek E</dc:creator>
      <pubDate>Fri, 14 Aug 2026 21:48:02 +0000</pubDate>
      <link>https://dev.to/telilabs/osi-model-the-internet-is-just-envelopes-thrown-away-at-every-router-3l82</link>
      <guid>https://dev.to/telilabs/osi-model-the-internet-is-just-envelopes-thrown-away-at-every-router-3l82</guid>
      <description>&lt;h2&gt;
  
  
  The wrong mental model
&lt;/h2&gt;

&lt;p&gt;For a long time I pictured a packet as a thing. A little sealed capsule that leaves my laptop, hops from router to router, and arrives at a server on the other side of the planet — the same object the whole way, like a parcel with my address on it.&lt;/p&gt;

&lt;p&gt;That picture is wrong. Not slightly wrong. Structurally wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start at the top
&lt;/h2&gt;

&lt;p&gt;When my browser sends an HTTP request, that request is just data. The layers below it exist to move that data, and each one wraps it in its own header.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transport (TCP) wraps it in a &lt;strong&gt;segment&lt;/strong&gt;: source port, destination port, sequence numbers.&lt;/li&gt;
&lt;li&gt;Network (IP) wraps that in a &lt;strong&gt;packet&lt;/strong&gt;: source IP, destination IP, TTL.&lt;/li&gt;
&lt;li&gt;Data link (Ethernet, Wi-Fi) wraps that in a &lt;strong&gt;frame&lt;/strong&gt;: destination MAC first, then source MAC, then a checksum trailer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nesting dolls. Fine. That part I had right.&lt;/p&gt;

&lt;p&gt;What I had wrong was what happens to those dolls in transit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descend: what actually changes per hop
&lt;/h2&gt;

&lt;p&gt;Here's the thing I had to sit with. The destination IP on my packet is the server's IP from the very first instant. Not my router's. The packet is addressed to the far end &lt;em&gt;before it leaves my machine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But the frame around it? That's addressed to my router's MAC. The frame only knows about the next device on the wire. It's local. It has a range of exactly one hop.&lt;/p&gt;

&lt;p&gt;So my router receives the frame, strips it off, and throws it away.&lt;/p&gt;

&lt;p&gt;Then it reads the packet inside, decides where to send it next, decrements the TTL, recomputes the header checksum — yes, the IP header is modified at every single router, even when the addresses aren't — and builds a &lt;em&gt;brand new frame&lt;/em&gt; addressed to the next hop's MAC.&lt;/p&gt;

&lt;p&gt;That happens at every router. Dozens of times. Frame born, frame dead. Every wire gets its own envelope.&lt;/p&gt;

&lt;h2&gt;
  
  
  One detour the packet can't avoid
&lt;/h2&gt;

&lt;p&gt;The IP addresses do stay constant end-to-end — with one exception, and it happens once, right at my front door.&lt;/p&gt;

&lt;p&gt;My home router does NAT: it swaps my private source IP (&lt;code&gt;192.168.x.x&lt;/code&gt;) for the public one my ISP assigned, usually rewrites the source port too, and recomputes the TCP checksum because that checksum covers the IPs. After that single rewrite, the addressing is fixed for the rest of the journey.&lt;/p&gt;

&lt;p&gt;So the packet isn't immutable either. It's a letter that gets its return address corrected once, and its postmark stamped at every sorting facility.&lt;/p&gt;

&lt;h2&gt;
  
  
  The click
&lt;/h2&gt;

&lt;p&gt;And then it landed: &lt;strong&gt;the packet never travels.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing travels except signals on a wire. What crosses the internet is a &lt;em&gt;pattern&lt;/em&gt; — a description of a packet, re-serialized into a fresh frame at every hop, carried one link at a time by envelopes that are shredded on arrival.&lt;/p&gt;

&lt;p&gt;My HTTP request doesn't ride across the ocean. It gets rebuilt, hop by hop, thirty times, and the only reason the far end receives "the same" request is that every router faithfully copies the layers above the frame into the next envelope.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>osi</category>
      <category>tcp</category>
      <category>ip</category>
    </item>
  </channel>
</rss>
