{"id":52,"date":"2026-08-01T01:54:33","date_gmt":"2026-07-31T22:54:33","guid":{"rendered":"https:\/\/john-nessime.com\/blog\/?p=52"},"modified":"2026-08-01T01:54:35","modified_gmt":"2026-07-31T22:54:35","slug":"metrics-logs-traces","status":"publish","type":"post","link":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/","title":{"rendered":"Metrics, Logs and Traces: What Each One Answers"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Checkout is slow. Somebody says it in Slack, and within a minute three people are looking at three different screens. One is scrolling a dashboard where every panel looks normal. One is grepping logs for the word &#8220;error&#8221; and finding nothing. One is reading a trace for a request that completed in 40ms and wondering why they bothered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nobody is doing anything wrong. They are just using the wrong tool for the question at hand, and none of them has said out loud what question they are trying to answer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Metrics, logs and traces get called the three pillars of observability, which makes them sound like three views of the same thing. They are not. They answer three different questions, and knowing which question you are asking is most of the skill.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The one-line version<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Metrics<\/strong> tell you <em>that<\/em> something is wrong, and when it started.<\/li>\n\n<li><strong>Traces<\/strong> tell you <em>where<\/em> in the system it is wrong.<\/li>\n\n<li><strong>Logs<\/strong> tell you <em>why<\/em> that particular thing went wrong.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">That ordering is also the order you should use them in during an incident. Starting with logs is the most common mistake, and it is why people end up grepping for twenty minutes before discovering the problem was a downstream service that never logged anything at all.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Metrics: numbers over time, and the cost of a label<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A metric is a number sampled repeatedly. Requests per second, memory used, queue depth. They are cheap to store because each sample is a timestamp and a value, and they aggregate well \u2014 which is exactly what makes them right for dashboards and alerts, and wrong for investigating one specific user&#8217;s problem.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Error rate as a proportion of all requests, per service\nsum(rate(http_requests_total{status=~\"5..\"}[5m])) by (service)\n  \/\nsum(rate(http_requests_total[5m])) by (service)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That query is answerable in milliseconds across months of history. No log search comes close.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Averages lie, and they lie in a specific direction<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An average response time of 200ms is compatible with 95% of requests at 50ms and 5% at three seconds. The people having a terrible time are invisible in the mean, and they are the ones who complain.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># p99 latency by endpoint\nhistogram_quantile(0.99,\n  sum(rate(http_request_duration_seconds_bucket[5m])) by (le, endpoint)\n)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Alert on p95 or p99, look at p50 to understand the typical case, and be aware that averaging percentiles across instances is mathematically meaningless \u2014 you have to aggregate the histogram buckets first, which is what the query above does.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Cardinality is the thing that breaks Prometheus<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every unique combination of label values creates a separate time series. Add a label with unbounded values and you multiply your storage and memory by the number of distinct values.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Fine. A handful of endpoints, a handful of statuses.\nhttp_requests_total{endpoint=\"\/checkout\", status=\"200\"}\n\n# Catastrophic. One time series per user, forever.\nhttp_requests_total{endpoint=\"\/checkout\", user_id=\"8a3f...\", request_id=\"...\"}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">User IDs, request IDs, session tokens, full URLs with parameters, email addresses \u2014 none of these belong in a metric label. They belong in logs and traces, which are built for high-cardinality data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To see whether you already have a problem:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Which metric names have the most series?\ntopk(10, count by (__name__)({__name__=~\".+\"}))<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run that on any Prometheus that has been growing unexpectedly. The answer is usually one metric somebody added a request ID to.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Logs: the detail, once you know where to look<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Logs are discrete events with arbitrary detail attached. Their strength is precision \u2014 the actual exception, the actual SQL statement, the actual value that was null. Their weakness is volume and cost, since you are storing every event rather than an aggregate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Structured or it did not happen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Compare these two lines for the same event:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Human readable, machine hostile\n2026-01-15 14:32:11 ERROR Payment failed for user 8a3f after 3 retries\n\n# Structured: queryable without regex archaeology\n{\"ts\":\"2026-01-15T14:32:11Z\",\"level\":\"error\",\"msg\":\"payment failed\",\n \"user_id\":\"8a3f\",\"retries\":3,\"provider\":\"stripe\",\"error_code\":\"card_declined\",\n \"trace_id\":\"4bf92f3577b34da6a3ce929d0e0e4736\",\"duration_ms\":1840}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With the second, &#8220;how many payments failed with card_declined on stripe in the last hour, grouped by retry count&#8221; is a query. With the first it is a regular expression that will break the next time someone rewords the message.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The field that ties everything together<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Notice <code>trace_id<\/code> in that log line. That single field is what turns three separate tools into one workflow. Find a slow trace, take its ID, and pull every log line from every service involved in that exact request.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you do one thing after reading this, make it that: get trace and span IDs into your structured logs. It is usually a few lines in a logging middleware and it changes how debugging feels.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Levels, used properly<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ERROR<\/strong> \u2014 something failed and a human may need to act. If nobody would act on it, it is not an error.<\/li>\n\n<li><strong>WARN<\/strong> \u2014 recovered, but worth knowing. A retry succeeded, a fallback was used.<\/li>\n\n<li><strong>INFO<\/strong> \u2014 meaningful state changes. Started, stopped, config loaded, job completed.<\/li>\n\n<li><strong>DEBUG<\/strong> \u2014 off in production, on when you are actively investigating.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The failure mode is logging everything at INFO. You get volume, cost, and a signal that nobody reads because it is 99% noise. If your ERROR channel fires constantly and nobody looks, you have trained your team to ignore errors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Sampling, when volume gets expensive<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Keep all errors and warnings. Sample the successful path \u2014 one in a hundred INFO lines from a healthy endpoint tells you the same thing as all hundred, at a fraction of the cost. Never sample errors. The one you drop is the one you needed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Traces: where the time actually went<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A trace follows one request across every service it touches. Each unit of work is a span, with a start time, duration, and a parent \u2014 so the trace becomes a tree showing exactly where the milliseconds went.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>POST \/checkout                                    1840ms\n\u251c\u2500 auth.verify_token                                12ms\n\u251c\u2500 cart.get_items                                   34ms\n\u2502  \u2514\u2500 SELECT * FROM cart_items WHERE ...            28ms\n\u251c\u2500 inventory.check_stock                            41ms\n\u251c\u2500 payment.charge                                 1690ms   \u2190 here\n\u2502  \u251c\u2500 HTTP POST api.stripe.com\/v1\/charges         1680ms\n\u2502  \u2514\u2500 db.insert payment_record                       8ms\n\u2514\u2500 order.create                                     52ms<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No amount of dashboard-staring gets you there that fast. The metric told you p99 checkout latency doubled; the trace tells you it is one outbound HTTP call, and now you know whether to look at your code or send an email to a vendor.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Traces are also how you find work you did not know about<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The classic find is the N+1 query \u2014 a trace showing four hundred nearly identical database spans where you expected one. That is invisible in metrics, because four hundred fast queries look healthy in aggregate, and invisible in logs unless you happen to log every query.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Context propagation is the part that breaks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tracing works because each service passes the trace context to the next one, usually in the W3C <code>traceparent<\/code> header:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\n             \u2502  \u2502                                \u2502                \u2502\n             \u2502  \u2514\u2500 trace ID                      \u2514\u2500 parent span   \u2514\u2500 flags\n             \u2514\u2500 version<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Break that chain anywhere and your trace splits in two, with the second half orphaned and useless. The usual culprits: a service that does not forward the header, a message queue where nobody propagated context into the consumer, or a thread pool that lost the context on handoff. Async boundaries are where this fails most often.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Sampling, and why tail-based is worth the trouble<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tracing everything at scale is expensive, so you sample. The distinction matters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Head-based<\/strong> \u2014 decide at the start of the request. Simple, cheap, and it throws away most of your errors, because errors are rare and the dice were rolled before anything went wrong.<\/li>\n\n<li><strong>Tail-based<\/strong> \u2014 decide after the request finishes, when you know it was slow or failed. Keep every error, keep the slow tail, sample the boring successes at 1%.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Tail-based needs a collector that buffers spans until the trace completes, which costs memory and adds a component. It is almost always worth it, because a trace store full of successful requests is a trace store you never open.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Using all three: an incident, in order<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>An alert fires on a metric.<\/strong> Checkout p99 latency crossed its threshold at 14:20. You know what and when.<\/li>\n\n<li><strong>Check the metric&#8217;s shape.<\/strong> Step change or gradual climb? Correlated with a deploy, traffic spike, or nothing? Which service, which endpoint?<\/li>\n\n<li><strong>Open a slow trace from that window.<\/strong> Not an average one \u2014 filter for the slow tail. Find the span holding the time.<\/li>\n\n<li><strong>Take the trace ID into your logs.<\/strong> Now you are reading a handful of lines from the exact request, not grepping a firehose.<\/li>\n\n<li><strong>Confirm the fix with the metric<\/strong> you started from. The graph coming back down is what closes the incident.<\/li>\n<\/ol>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Every step narrows the search. Metrics cover everything at low detail, traces cover one request at high detail, logs cover one moment at full detail. Going straight to logs means searching everything at full detail, which is why it feels like archaeology.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">What to instrument if you are starting from nothing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not try to do all three at once. In order of value per hour spent:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Request rate, error rate and duration per endpoint.<\/strong> These three metrics answer most operational questions and take an afternoon with a middleware.<\/li>\n\n<li><strong>Structured logs with a request ID.<\/strong> Even without tracing, a request ID threaded through your logs is transformative.<\/li>\n\n<li><strong>Host metrics.<\/strong> CPU, memory, disk, network. Answers &#8220;is the machine underneath healthy&#8221; before you debug the application.<\/li>\n\n<li><strong>Tracing on your slowest or most critical path.<\/strong> Not everything. Checkout, or whatever your equivalent is.<\/li>\n\n<li><strong>Trace IDs in log lines,<\/strong> once tracing exists. This is the step that connects the tools.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Instrument with OpenTelemetry rather than a vendor SDK. The API is vendor-neutral, so switching backends later is a collector config change instead of touching every service. That is the single decision most likely to save you a painful migration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common mistakes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Starting an investigation in logs rather than metrics.<\/li>\n\n<li>Putting user IDs, request IDs or full URLs into metric labels.<\/li>\n\n<li>Alerting on averages instead of percentiles.<\/li>\n\n<li>Averaging percentiles across instances, which is not a meaningful operation.<\/li>\n\n<li>Unstructured log messages that require regular expressions to query.<\/li>\n\n<li>Head-based trace sampling, which discards most of your errors by construction.<\/li>\n\n<li>Sampling error logs to save money.<\/li>\n\n<li>No trace or request ID in logs, leaving the three tools unconnected.<\/li>\n\n<li>Instrumenting with a vendor SDK and discovering the cost of that choice at renewal time.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keep metric cardinality bounded and check your top series periodically.<\/li>\n\n<li>Log structured JSON with consistent field names across services.<\/li>\n\n<li>Propagate trace context everywhere, especially across queues and async boundaries.<\/li>\n\n<li>Use tail-based sampling so errors and slow requests are always kept.<\/li>\n\n<li>Set retention by usefulness: metrics for months, traces for days, logs somewhere between.<\/li>\n\n<li>Alert on symptoms users feel \u2014 latency, errors, saturation \u2014 not on internal counters nobody can act on.<\/li>\n\n<li>Standardise on OpenTelemetry so the backend stays replaceable.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Do I need all three?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Not immediately. A single service with good metrics and structured logs is well covered. Tracing earns its cost when a request crosses several services and &#8220;which one is slow&#8221; stops being obvious.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the difference between monitoring and observability?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Monitoring watches for failure modes you predicted. Observability is being able to answer questions you did not think of in advance. Metrics and alerts are mostly monitoring; high-cardinality traces and structured logs are what make a system observable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why is my Prometheus using so much memory?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Almost always cardinality. Memory tracks the number of active time series, not the number of hosts. Find the offending metric with a top-series query \u2014 it will usually be one where somebody added an unbounded label.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I put logs into metrics or the reverse?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You can derive metrics from logs, and it is a reasonable stopgap when you cannot change the application. It is more expensive than emitting metrics directly and the resolution is worse. Going the other way \u2014 reconstructing event detail from metrics \u2014 is not possible, since aggregation discards it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How long should I keep each?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Metrics are cheap and useful for capacity planning, so months. Traces are large and mostly interesting while an incident is fresh, so days. Logs sit in between and are usually driven by compliance rather than debugging value.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is tracing worth it for a monolith?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Often yes, because spans still reveal internal structure \u2014 which query, which external call, how many times. The N+1 problem shows up just as clearly in a monolith as in a distributed system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping up<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Metrics, logs and traces are not three ways of looking at the same data. Metrics are aggregates over time and answer whether something is wrong. Traces follow one request and answer where. Logs are individual events and answer why. Reach for them in that order and each step makes the next one smaller.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your setup is incomplete, the highest-value gap is usually the connective tissue rather than another data source. Trace IDs in structured logs, consistent field names, bounded metric labels. Those three make the tools you already have work together, which is worth more than adding a fourth.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Want your observability stack to actually answer questions?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I work with teams on observability that earns its cost \u2014 metrics with sane cardinality, structured logging that is queryable, OpenTelemetry instrumentation that survives a backend change, and alerts that fire on things people can act on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your dashboards look healthy while users complain, you can hire me on Upwork.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.upwork.com\/freelancers\/~01f15a912ad84a6620\" target=\"_blank\" rel=\"noreferrer noopener\">Work with me on Upwork<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Metrics tell you that something is wrong. Traces tell you where. Logs tell you why. Use them in that order and each step narrows the search \u2014 start with logs and you are grepping a firehose. Here is what each one is actually for, and the field that connects all three.<\/p>\n","protected":false},"author":1,"featured_media":53,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,63,107],"tags":[98,3,11,21,116,13,96,115,16,118,117,4],"class_list":["post-52","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-system-administration","category-web-performance","tag-alerting","tag-devops","tag-grafana","tag-infrastructure","tag-logging","tag-monitoring","tag-observability","tag-opentelemetry","tag-prometheus","tag-sre","tag-tracing","tag-troubleshooting","entry","has-media"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Metrics, Logs and Traces: What Each Answers<\/title>\n<meta name=\"description\" content=\"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Metrics, Logs and Traces: What Each Answers\" \/>\n<meta property=\"og:description\" content=\"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/\" \/>\n<meta property=\"og:site_name\" content=\"John Nessime\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-31T22:54:33+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-31T22:54:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"John Nessime\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"John Nessime\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/\"},\"author\":{\"name\":\"John Nessime\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"headline\":\"Metrics, Logs and Traces: What Each One Answers\",\"datePublished\":\"2026-07-31T22:54:33+00:00\",\"dateModified\":\"2026-07-31T22:54:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/\"},\"wordCount\":2057,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"image\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/metrics-logs-traces-featured.png\",\"keywords\":[\"Alerting\",\"DevOps\",\"Grafana\",\"Infrastructure\",\"Logging\",\"Monitoring\",\"Observability\",\"OpenTelemetry\",\"Prometheus\",\"SRE\",\"Tracing\",\"Troubleshooting\"],\"articleSection\":[\"DevOps\",\"System Administration\",\"Web Performance\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/\",\"name\":\"Metrics, Logs and Traces: What Each Answers\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/metrics-logs-traces-featured.png\",\"datePublished\":\"2026-07-31T22:54:33+00:00\",\"dateModified\":\"2026-07-31T22:54:35+00:00\",\"description\":\"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#primaryimage\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/metrics-logs-traces-featured.png\",\"contentUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/metrics-logs-traces-featured.png\",\"width\":1200,\"height\":800,\"caption\":\"Diagram showing how metrics, traces and logs narrow an investigation: a latency chart with an alert threshold, a waterfall trace isolating a slow payment span, and a structured log line, all connected by a shared trace ID\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/devops\\\/metrics-logs-traces\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Metrics, Logs and Traces: What Each One Answers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/\",\"name\":\"John Nessime\",\"description\":\"Cloud, DevOps, Data &amp; AI \u2014 Built, Tested, Explained\",\"publisher\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/#\\\/schema\\\/person\\\/ede0b56d0c808f123f57d5d796902105\",\"name\":\"John Nessime\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"contentUrl\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\",\"width\":512,\"height\":512,\"caption\":\"John Nessime\"},\"logo\":{\"@id\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/cropped-jn.png\"},\"description\":\"AWS Certified Solutions Architect helping businesses build reliable cloud, data, reporting, and automation solutions. I help startups, agencies, and growing businesses replace manual processes and disconnected data with practical AWS architectures, clean data pipelines, useful dashboards, and maintainable automation.\",\"sameAs\":[\"https:\\\/\\\/john-nessime.com\\\/blog\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/john-m-nessime\"],\"url\":\"https:\\\/\\\/john-nessime.com\\\/blog\\\/author\\\/johnnessime\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Metrics, Logs and Traces: What Each Answers","description":"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/","og_locale":"en_US","og_type":"article","og_title":"Metrics, Logs and Traces: What Each Answers","og_description":"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.","og_url":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/","og_site_name":"John Nessime","article_published_time":"2026-07-31T22:54:33+00:00","article_modified_time":"2026-07-31T22:54:35+00:00","og_image":[{"width":1200,"height":800,"url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png","type":"image\/png"}],"author":"John Nessime","twitter_card":"summary_large_image","twitter_misc":{"Written by":"John Nessime","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#article","isPartOf":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/"},"author":{"name":"John Nessime","@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"headline":"Metrics, Logs and Traces: What Each One Answers","datePublished":"2026-07-31T22:54:33+00:00","dateModified":"2026-07-31T22:54:35+00:00","mainEntityOfPage":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/"},"wordCount":2057,"commentCount":0,"publisher":{"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"image":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#primaryimage"},"thumbnailUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png","keywords":["Alerting","DevOps","Grafana","Infrastructure","Logging","Monitoring","Observability","OpenTelemetry","Prometheus","SRE","Tracing","Troubleshooting"],"articleSection":["DevOps","System Administration","Web Performance"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/","url":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/","name":"Metrics, Logs and Traces: What Each Answers","isPartOf":{"@id":"https:\/\/john-nessime.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#primaryimage"},"image":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#primaryimage"},"thumbnailUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png","datePublished":"2026-07-31T22:54:33+00:00","dateModified":"2026-07-31T22:54:35+00:00","description":"Metrics, logs and traces answer different questions: what is wrong, where, and why. How to use each, avoid cardinality blowups, and connect them by trace ID.","breadcrumb":{"@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#primaryimage","url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png","contentUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/08\/metrics-logs-traces-featured.png","width":1200,"height":800,"caption":"Diagram showing how metrics, traces and logs narrow an investigation: a latency chart with an alert threshold, a waterfall trace isolating a slow payment span, and a structured log line, all connected by a shared trace ID"},{"@type":"BreadcrumbList","@id":"https:\/\/john-nessime.com\/blog\/devops\/metrics-logs-traces\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/john-nessime.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Metrics, Logs and Traces: What Each One Answers"}]},{"@type":"WebSite","@id":"https:\/\/john-nessime.com\/blog\/#website","url":"https:\/\/john-nessime.com\/blog\/","name":"John Nessime","description":"Cloud, DevOps, Data &amp; AI \u2014 Built, Tested, Explained","publisher":{"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/john-nessime.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/john-nessime.com\/blog\/#\/schema\/person\/ede0b56d0c808f123f57d5d796902105","name":"John Nessime","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","url":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","contentUrl":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png","width":512,"height":512,"caption":"John Nessime"},"logo":{"@id":"https:\/\/john-nessime.com\/blog\/wp-content\/uploads\/2026\/07\/cropped-jn.png"},"description":"AWS Certified Solutions Architect helping businesses build reliable cloud, data, reporting, and automation solutions. I help startups, agencies, and growing businesses replace manual processes and disconnected data with practical AWS architectures, clean data pipelines, useful dashboards, and maintainable automation.","sameAs":["https:\/\/john-nessime.com\/blog","https:\/\/www.linkedin.com\/in\/john-m-nessime"],"url":"https:\/\/john-nessime.com\/blog\/author\/johnnessime\/"}]}},"_links":{"self":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/52","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/comments?post=52"}],"version-history":[{"count":1,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/52\/revisions"}],"predecessor-version":[{"id":54,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/posts\/52\/revisions\/54"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/media\/53"}],"wp:attachment":[{"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/media?parent=52"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/categories?post=52"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/john-nessime.com\/blog\/wp-json\/wp\/v2\/tags?post=52"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}