Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
13 posts found
Debugging Is a Method: Observation, Hypothesis, Experiment and the 9 Rules
Developer Tools PART 01

Debugging Is a Method: Observation, Hypothesis, Experiment and the 9 Rules

Debugging is done with a method, not with guesses: a loop of observation, testable hypothesis, prediction, experiment and conclusion. Starting from a 1 kuruş order total mismatch, we cover Agans' 9 rules, the cost of shotgun debugging and the debugging journal with real outputs.

8 Nov 2026 11 min 4
Reproducing the Bug: Minimal Repro, Environment Differences and a Failing Test First
Developer Tools PART 02

Reproducing the Bug: Minimal Repro, Environment Differences and a Failing Test First

You can't fix a bug you can't reproduce: get the right information from the reporter, check culture, time zone, configuration and version differences, reduce the bug to a minimal repro and write a failing xUnit test before the fix. With real outputs: 12,45 parsed as 1245 in a container and an order total bug reduced to two lines.

8 Nov 2026 11 min 3
Narrowing It Down: Binary Search, git bisect run and Delta Debugging
Developer Tools PART 03

Narrowing It Down: Binary Search, git bisect run and Delta Debugging

The fastest way to find a bug is to halve the range at every step: in code, across layers, over commits and in the input. git bisect run skips a broken commit with exit code 125 and finds the faulty refactoring among 31 commits in 7 tests; the ddmin algorithm shrinks a 5,000-line import file to 3 lines.

8 Nov 2026 14 min 3
Reading Error Messages and Stack Traces: .NET Exceptions, Async Stacks and Angular NG Errors
Developer Tools PART 04

Reading Error Messages and Stack Traces: .NET Exceptions, Async Stacks and Angular NG Errors

A stack trace is read layer by layer, not top to bottom: the real cause usually sits in the inner exception starting with --->, and the root of 50 identical errors in a log is usually the first error in time order. With real output from .NET 10 we read InnerException chains, AggregateException, the stack lost to throw ex, ExceptionDispatchInfo, going from a ProblemDetails traceId to the log, source maps, and Angular 22's NG0100, NG0200 and NG0201 errors.

8 Nov 2026 13 min 3
Advanced .NET Debugging: Conditional Breakpoints, Tracepoints, Data Breakpoints and Exception Settings
Developer Tools PART 05

Advanced .NET Debugging: Conditional Breakpoints, Tracepoints, Data Breakpoints and Exception Settings

The shortest way to find who changes a value is a data breakpoint: in Visual Studio, for .NET Core 3+ projects, the debugger stops on the line that writes the property. With real output we cover conditional, hit count and dependent breakpoints, tracepoints, Exception Settings for swallowed exceptions, Set Next Statement, Hot Reload, DebuggerDisplay and Source Link, testing Copilot suggestions as hypotheses, and the Rider and Visual Studio Code equivalents.

8 Nov 2026 13 min 5
Async and Multi-Threaded Debugging: Parallel Stacks, the Tasks Window, Deadlocks and Race Conditions
Developer Tools PART 06

Async and Multi-Threaded Debugging: Parallel Stacks, the Tasks Window, Deadlocks and Race Conditions

In an async hang, the waiting code isn't on any thread's stack; you need the Tasks view of Parallel Stacks or the async chain in a dump. We read a lock-order deadlock and a .Result sync-over-async deadlock through dotnet-stack output, measure thread pool starvation, show Dictionary, counter and check-then-act race conditions with real runs, and explain forcing a race with freeze/thaw.

8 Nov 2026 11 min 5
Bug Hunting in an Angular App: Signals, Change Detection, RxJS and the HTTP Layer
Developer Tools PART 07

Bug Hunting in an Angular App: Signals, Change Detection, RxJS and the HTTP Layer

In Angular you narrow a bug by splitting the UI, state, HTTP and API chain down the middle. With real Vitest output: a computed that never updates because an array was mutated in place, a signal read after await that is not tracked, a stale screen and a hidden NG0100 under Angular 22's default OnPush, a search stream killed by catchError, switchMap cancellations and interceptor order.

8 Nov 2026 11 min 6
Finding the Cause in Logs: Correlation IDs, Trace IDs and Building a Timeline
Developer Tools PART 08

Finding the Cause in Logs: Correlation IDs, Trace IDs and Building a Timeline

To find the cause of an error in logs we first find the first signal, then follow a single request across services by its trace ID, and finally build a shared timeline with deploys and configuration changes. Plus W3C traceparent, the traceId in ProblemDetails, raising the log level at runtime, jq queries and masking personal data in logs.

8 Nov 2026 11 min 5
Analyzing Crash and Memory Dumps: dotnet-dump, SOS Commands and Taking Dumps in Containers
Developer Tools PART 09

Analyzing Crash and Memory Dumps: dotnet-dump, SOS Commands and Taking Dumps in Containers

We take crash dumps automatically with DOTNET_DbgEnableMiniDump and use pe -lines, clrthreads, dumpheap -stat, gcroot, syncblk and dumpasync in dotnet-dump analyze to find the crashing thread, a growing static cache and a lock deadlock. Plus PID 1 versus --init in containers, getting the tool into an SDK-less image, the OOM risk of Heap/Full dumps and personal data inside dumps.

8 Nov 2026 13 min 7
Diagnosing Hangs and Slowness: dotnet-stack, dotnet-trace and Thread Pool Starvation
Developer Tools PART 10

Diagnosing Hangs and Slowness: dotnet-stack, dotnet-trace and Thread Pool Starvation

We diagnose an unresponsive service with dotnet-counters, dotnet-stack and a time-boxed dotnet-trace, in that order: an endpoint using .Result pushes p50 to 47 seconds under 200 concurrent requests, and await brings it down to 204 ms. Plus WaitHandleWait events, the prerequisites of collect-linux in .NET 10 and keeping traces safely bounded in production.

8 Nov 2026 12 min 6
Root Cause Analysis: 5 Whys, Fishbone and Blameless Postmortems
Developer Tools PART 11

Root Cause Analysis: 5 Whys, Fishbone and Blameless Postmortems

A root cause is not a person but the conditions that let a bug reach production. In the order total case we separate symptom, proximate cause and root cause, find the factors with 5 Whys and a fishbone, measure the impact, make the class of bug impossible with a Money value object and BannedApiAnalyzers, and write the blameless postmortem.

8 Nov 2026 14 min 6
Real-World Bug Hunts 1: Backend — Culture, Time Zones, Sockets and Mutable Keys
Developer Tools PART 12

Real-World Bug Hunts 1: Backend — Culture, Time Zones, Sockets and Mutable Keys

In backend bugs the first hypothesis usually blames another system; a cheap observation refutes it. Six real cases: a role check broken under tr-TR, a report shifted 3 hours by UTC, TIME_WAIT sockets piling up from new HttpClient(), a key mutated inside a Dictionary, an async void crashing the process (and lingering half-dead as PID 1 in a container), and N+1 in EF Core; each with a fix, a regression test and an analyzer.

8 Nov 2026 15 min 4
Blog Map