Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Job Dashboards, Monitoring and Alerting: Hangfire Dashboard, Quartz 4 Dashboard and OpenTelemetry
The Hangfire Dashboard is open only to local requests by default, but a request coming through a proxy on the same machine counts as local too: a request through Docker got a 200. In production, put the dashboard behind an authorization policy and read-only mode; the Quartz 4 dashboard won't start at all without authorization. A "last successful run older than 26 hours" health check, Quartz 4's OpenTelemetry spans and metrics, and structured logs carrying the JobId complete the picture.
Observability in Messaging: OpenTelemetry Trace Context, Queue Depth and Consumer Lag
Listen to RabbitMQ.Client 7's built-in ActivitySource and write the traceparent into Kafka headers yourself with a propagator; an order's journey through the API, RabbitMQ, Billing, Kafka and Notification then shows up as five spans in one trace. MessageId and CorrelationId in the log scope, the messaging.process.duration histogram, cardinality, queue depth and Kafka consumer lag, with real output.
What's New in Caching with .NET 11: MemoryCache Metrics, HybridCache Factory Context and IOutputCachePolicyProvider
.NET 11 brings three caching changes: with TrackStatistics on, MemoryCache publishes dotnet.cache.requests, evictions, entries and estimated_size metrics on its own; the HybridCache factory can choose the duration from the value; and IOutputCachePolicyProvider resolves output cache policies at runtime. The catch we measured: with today's package the new HybridCache overload isn't atomic (40 factory runs instead of 20 for 20 cold keys), and a custom provider silently drops AddPolicy definitions.
Measuring and Testing Caches: Hit Ratio, Metrics, Memory Usage and Consistency Tests
A cache proves its worth through p95 and database load, not hit ratio: the report cache cut p95 from 245 ms to 1.3 ms and 3,001 queries to 1; the book cache at 87% hit ratio didn't change p95 but cut queries by 87%; the one at 16% should go. In .NET 10 you measure with TrackStatistics, a Meter and HybridCache's EventSource; FakeTimeProvider and Testcontainers tests caught tag invalidation not reaching another server.
Reading Structured Logs with Seq: Docker Setup, Queries, Signals and Alerts
We run Seq in Docker with a password and a separate ingestion port, and send logs through Serilog and OTLP with an Ingest-only API key. Filters, group by and percentile queries, logs and spans on the same TraceId, signals, alerts and signal-based retention, all with real results, including why 8 failures became 16 events and the ERROR level trap with OTLP.
Serilog Sinks: Console, File, Seq and OpenTelemetry — Async, Batching and Lost Logs
In a container, logs go to stdout as compact JSON; if you need files, set rolling and retention explicitly. Serilog 4's core batching and the async wrapper either drop events or hold the app when a sink is slow: 101 of 2,000 events arrived, or the loop took 2.4 seconds. SelfLog, going out to OTLP and per-sink levels.