← Back to list

I Had No Idea What Observability Meant. Then I Added It to My Own Cybersecurity Project.

I’m a B.Tech Computer Science student specializing in Cybersecurity and Forensics, and until a few weeks ago, “observability” was one of…

Yogita Vohra · 2026-07-12 13:10 · 10 claps · 9.8 min read
#cybersecurity-awareness #observability #opentelemetry #signoz #python
Open on Medium ↗
Wiki topics: EDU · Education & Learning 💻 · Programming 🔒 · Cybersecurity 🔬 · Science · General

I Had No Idea What Observability Meant. Then I Added It to My Own Cybersecurity Project.

I’m a B.Tech Computer Science student specializing in Cybersecurity and Forensics, and until a few weeks ago, “observability” was one of those words I nodded along to without actually understanding. I’d seen it in job descriptions, in conference talk titles, in the occasional LinkedIn post. Traces, metrics, logs — I knew the words existed. I couldn’t have told you what any of them actually looked like on a screen, or why an engineer would care about them at 2 AM.

So when I saw SigNoz’s pre-event blog challenge, my first instinct was to scroll past it. I’m not an observability person. I build cybersecurity tools, mess around with encryption, and occasionally break my own Python scripts in creative ways. But then I thought about it a little more, and honestly, that felt like exactly the wrong reason to skip it. I wanted to walk into the actual hackathon with at least some idea of what I was doing, instead of learning everything under time pressure. So I decided to just start.

Why I Didn’t Build a Fake Demo App

A lot of tutorials on observability use some toy microservice — a shopping cart, a to-do list, something built purely to show off tracing. I get why. It’s clean and controlled. But I didn’t want to do that. I already had a working project sitting in my GitHub: an Image Steganography Tool I’d built earlier for a cybersecurity assignment. It hides secret messages inside images and can decode them back out, built with Python, Tkinter for the GUI, and PIL for the image handling.

I decided to instrument that instead of building something new, and I think this ended up being the right call. Real applications don’t behave like tutorial apps. They have GUI event loops, file I/O, existing error handling, and code you didn’t write with observability in mind. Adding tracing to something that already works, without touching its actual logic, felt a lot closer to what I’d actually be doing in a job someday than building a fresh demo just to instrument it. If anything, keeping the app’s behavior completely unchanged was the whole point — I wanted to add a lens to look through, not rebuild the thing I was looking at.

Getting Docker to Cooperate (This Took Longer Than It Should Have)

I’m going to be honest about this part because I think it’s the most relatable bit for anyone starting from scratch.

I run Windows 11 on a laptop with an Intel i5–12450HX, an RTX 2050, and 12 GB of RAM — nothing exotic, just a fairly standard machine. I had never installed Docker Desktop before this. Somehow, in three years of writing code, I’d avoided containers entirely.

So step one was installing Docker Desktop, which immediately asked me to set up WSL. Fine, I thought, how bad could that be. I installed Ubuntu through WSL, created my Linux username, and sat there for a few minutes while Ubuntu configured itself for the first time. That part went smoothly enough.

Then Docker just… didn’t work. I could run docker commands fine in Windows PowerShell, but the moment I opened my Ubuntu terminal and tried the same thing, I got hit with docker: command not found. I remember staring at that error longer than I'd like to admit, convinced I'd typed something wrong.

I hadn’t. The actual problem was WSL integrationDocker Desktop has a setting where you explicitly enable integration with your specific WSL distro, and I’d missed it. I went digging through Docker Desktop’s settings, found the WSL integration toggle, enabled it for my Ubuntu distro, restarted Docker, restarted my terminal, and still got the same error. Turned out there was also a PATH issue on top of that — Ubuntu wasn’t picking up the Docker binary path correctly even after integration was on.

I won’t pretend I fixed this in five minutes. It took a genuine stretch of trial and error, closing and reopening terminals, restarting Docker Desktop more times than felt reasonable, before docker --version finally printed something inside Ubuntu instead of an error. When it did work, it was a small, quiet kind of satisfying — not dramatic, just relief that I could finally move on to the part I actually cared about.

Installing SigNoz Through Foundry

With Docker working, I moved on to installing Foundry, which is what SigNoz uses to set up the self-hosted stack. I installed foundryctl next, and — I'll admit I saw this coming at this point — got foundryctl: command not found. Same story as before: PATH problem. I fixed it, and this time it was quicker since I already had a mental model of what to check.

Once foundryctl was recognized, running the actual Foundry setup felt genuinely exciting. Docker started pulling down container after container — I watched the terminal scroll through image after image downloading, and there was a specific moment where it hit me that I wasn't just installing an app, I was standing up an entire observability platform on my own laptop. Collectors, storage, the query service, the frontend — all of it spinning up in containers I could see running.

A few minutes later, localhost:8080 opened in my browser, and I created my SigNoz workspace. That was the first time the whole thing felt real instead of theoretical.

Staring at the Interface and Having No Idea What I Was Looking At

I want to be honest about this part too, because I think it’s the part most beginner-friendly tutorials skip over. I opened SigNoz and had absolutely no idea where to start. There were tabs for traces, metrics, logs, dashboards, alerts. Nothing had any data in it yet, obviously, since I hadn’t instrumented anything. But even conceptually, I kept asking myself: what actually is observability, and why does it need three different things — traces, metrics, and logs — instead of just one?

It took me a while to realize the analogy that finally made it click for me. Think of your application like a delivery truck driving across a city. A log is like the driver radioing in short updates: “left the warehouse,” “hit traffic on Main Street,” “delivered package.” Useful, but disconnected — just individual moments. A metric is more like a dashboard showing you average delivery time across all trucks over the last hour — a trend, a number that goes up or down, without telling you about any single trip. A trace is the full GPS route of one specific truck, one specific delivery, from the second it left the warehouse to the second it dropped off the package, with timestamps at every turn.

I hadn’t set up metrics or logs at that point — I was purely focused on tracing — but understanding how the three relate to each other made the rest of the setup make a lot more sense.

Actually Instrumenting My Code

This is where things got genuinely interesting. I connected OpenTelemetry to my project and created a telemetry.py file to hold the tracing setup separately from my application logic. I specifically didn't want to scatter observability code through my existing files — I wanted it to sit alongside my project, not rewrite it.

I added tracing around two functions: encode_image(), which hides the secret message inside the image, and decode_image(), which pulls it back out. That's it. I didn't touch the actual steganography logic, the PIL operations, or the Tkinter GUI code. I wrapped the two functions I actually cared about observing, and left everything else exactly as it was.

This mattered more than I expected going in. If I’d started modifying my application’s real logic while also trying to learn OpenTelemetry, I wouldn’t have been able to tell whether a bug was from my instrumentation or from something I broke in the app itself. Keeping the two completely separate meant I could trust that if something looked wrong in SigNoz, it was a tracing problem, not an application problem — and if my app misbehaved, tracing had nothing to do with it.

The Moment It Actually Clicked

I ran my application, encoded a message into an image, decoded it back out, and switched over to SigNoz to refresh the page.

I’ll admit I refreshed it more times than I’d like to admit, half-expecting an empty screen again. But this time, there it was: a service named image-steganography-tool, with two operations listed underneath it — encode_image and decode_image. I could see execution times for each call. I could click into an individual trace and see exactly when the function started, how long it took, and when it finished.

Before this, my entire understanding of “running a program” was: I click run, something happens, the program finishes. That was the whole picture. What happened in between was a black box I never really thought to question — if the output looked right, I moved on. Seeing SigNoz break open that black box, showing me the actual shape of what my code was doing while it ran, was the first time observability stopped being an abstract industry term and started being something I could point at on my screen.

What I Actually Learned

The biggest shift in my thinking was realizing observability isn’t the same thing as debugging, even though I’d been mentally lumping them together. Debugging is what you do when something is already broken — you’re hunting for the specific line that failed. Observability is what lets you understand a system’s behavior even when nothing is broken, so that when something eventually does go wrong, you already have the context to figure out why.

It’s also different from just sprinkling print() statements everywhere, which is honestly the only "monitoring" technique I'd used before this. Print statements give you a flat wall of text with no structure, no timing, no relationships between events. A trace, by comparison, tells a story — it has a beginning, a sequence, a duration, and it shows you how one operation relates to another. Logs are closer to print statements in spirit, but structured and searchable. Metrics don't tell you about a single run at all — they show you patterns across many runs, the kind of thing you'd only notice by looking at trends over time.

I only worked with traces in this project. I didn’t touch metrics or logs beyond understanding what they’re for conceptually, and I don’t want to pretend otherwise — that’s genuinely the next thing I want to explore.

My Favorite Feature: Trace Explorer

If I had to pick one part of SigNoz that made everything worthwhile, it’s Trace Explorer. Not because I read that it was useful in some documentation page, but because I actually sat there using it — clicking into individual encode and decode operations, checking execution times, looking at how spans lined up against each other.

It let me understand my own program’s flow without adding a single print statement. I could see exactly how long encode_image() took compared to decode_image(), and I could inspect an individual trace to see the full lifecycle of one function call. It felt like getting a window into my code that I never had before, and it made me actually curious to instrument other parts of my project later, just to see what else I'd find.

The Honest Parts: What Didn’t Go Smoothly

I don’t want this to read like everything fell into place easily, because it didn’t. The Docker and WSL setup alone ate a genuine chunk of my time, mostly from PATH issues and integration settings I didn’t know existed until I went looking for them. foundryctl gave me the same kind of PATH headache right after I'd just solved it once. Learning OpenTelemetry's concepts — spans, tracers, exporters — took some rereading before it stopped feeling like new vocabulary and started feeling like something I understood. And the SigNoz interface itself, on first open, was a lot to take in with zero prior context.

None of it was insurmountable. But it wasn’t instant either, and I think pretending otherwise would do a disservice to anyone reading this who’s about to try the same thing and hits the exact same wall I did.

Where I Landed

By the end of this, I’d self-hosted SigNoz entirely on my own machine, instrumented an existing cybersecurity project without changing its core logic, and successfully generated and inspected traces for both the encode and decode operations of my steganography tool. I went from not understanding what a trace even was to being able to open one and read it like a timeline.

I didn’t get to metrics or logs in this round — traces were the full scope of what I configured, and I’m deliberately not claiming otherwise. That’s the natural next step for me, probably in the actual hackathon itself, where I’d like to see request-level metrics and structured logs sitting alongside the traces I already have.

What I’m taking away from this isn’t really about SigNoz as a product, even though it worked well once I got past my own setup mistakes. It’s that observability stopped being an abstract word somewhere around the point I watched my own function names show up in a dashboard with real execution times next to them. That’s a small thing, maybe, but it’s the thing that made the rest of it make sense.

I’m documenting my journey of learning cybersecurity, building projects, and exploring technologies beyond my comfort zone. This was my first step into observability — and definitely not my last.


메타데이터
post_id
3aa76d604366
slug
i-had-no-idea-what-observability-meant-then-i-added-it-to-my-own-cybersecurity-project-3aa76d604366
url
https://medium.com/@krystalthoughts/i-had-no-idea-what-observability-meant-then-i-added-it-to-my-own-cybersecurity-project-3aa76d604366
canonical_url
https://medium.com/@krystalthoughts/i-had-no-idea-what-observability-meant-then-i-added-it-to-my-own-cybersecurity-project-3aa76d604366
author_url
https://medium.com/@krystalthoughts
status
ok
fetched_at
2026-07-14 04:02:57