diff --git a/apps/landing/src/pages/guides/dynatrace-pricing.astro b/apps/landing/src/pages/guides/dynatrace-pricing.astro index ed4e2e1fe4..1f955121f4 100644 --- a/apps/landing/src/pages/guides/dynatrace-pricing.astro +++ b/apps/landing/src/pages/guides/dynatrace-pricing.astro @@ -255,16 +255,31 @@ const articleJsonLd = {
+
+

+ Dynatrace is a full-stack observability platform that monitors applications, infrastructure and user experience through an agent on each host. It is sold through the Dynatrace Platform Subscription (DPS): usage such as host-hours, gigabytes of logs and traces, and user sessions is metered against a published rate card and drawn down from an annual commitment. +

+

+ This guide covers how DPS billing works, the rate card, a worked monthly bill for a small fleet, what OpenTelemetry data costs on Dynatrace, and how Dynatrace pricing compares with New Relic. +

+
+

Key takeaways

+
    +
  • Full-Stack Monitoring is $0.01 per memory-GiB-hour with a 4 GiB minimum: $58.40 a month for an 8 GiB host.
  • +
  • Infrastructure Monitoring is $0.04 per host-hour for any size host, $29.20 a month.
  • +
  • Logs and traces cost $0.20 per GiB to ingest, plus separate charges to retain and query them.
  • +
  • No per-seat fees: every user gets the full platform.
  • +
  • Everything draws from an annual commitment whose minimum Dynatrace doesn't publish.
  • +
+
+
+

01 · The model

How Dynatrace pricing works

-
-

Dynatrace pricing is pay-as-you-use against a yearly minimum. You agree to spend at least a set amount each year, and everything you monitor is metered by the hour or by the gigabyte and taken out of that amount.

-
-

- The contract is the Dynatrace Platform Subscription (DPS). It includes every generally available capability, so there are no modules to buy, and it has no per-seat fees: every user gets the full platform. What you pay depends on three kinds of meter, and this guide colors each one the same way throughout: + The DPS contract includes every generally available capability, so there are no modules to buy, and it has no per-seat fees: every user gets the full platform. What you pay depends on three kinds of meter, and this guide colors each one the same way throughout:

@@ -571,14 +586,15 @@ const articleJsonLd = { .dt-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .dt-guide h3 { display: flex; align-items: center; gap: 0.6rem; margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .dt-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .dt-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .dt-guide .guide-answer p, .dt-guide .guide-list li { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .dt-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .dt-guide .guide-list li { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .dt-guide strong { font-weight: 600; color: var(--foreground); } .dt-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .dt-guide pre { margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .dt-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .dt-guide a:not(.guide-button):hover { color: var(--foreground); } - .dt-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .dt-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } + .dt-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .dt-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .dt-guide .guide-takeaways li::marker { color: var(--primary); } .dt-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } .dt-guide .guide-list { margin: 0 0 1.5rem; padding-left: 1.2rem; list-style: disc; } .dt-guide .guide-list li::marker { color: var(--chart-1); } diff --git a/apps/landing/src/pages/guides/incident-response.astro b/apps/landing/src/pages/guides/incident-response.astro index ccbded0261..5547775033 100644 --- a/apps/landing/src/pages/guides/incident-response.astro +++ b/apps/landing/src/pages/guides/incident-response.astro @@ -221,19 +221,31 @@ const articleJsonLd = {
+
+

+ Incident response is the process a team follows from the moment a production problem is detected until service is restored and the cause is fixed. It runs as a cycle, so what you learn from each incident makes the next one less likely or shorter. +

+

+ This guide is written for small teams with one or two engineers on call. It covers how to prepare, the response steps, a worked incident timeline with the metrics that measure it, and how to run a postmortem. +

+
+

Key takeaways

+
    +
  • Prepare in an afternoon: alerts on symptoms users feel, who gets alerted when, and runbooks for your top three failure modes.
  • +
  • Stop the user impact before you know the cause; a deploy in the last hour is the first suspect, so roll it back.
  • +
  • Declare early in one channel, such as #incidents, and post updates at a fixed interval while customers are affected.
  • +
  • Write a blameless one-page postmortem for incidents customers noticed, with an owner and a due date on every action item.
  • +
  • Once a quarter, count incidents per month, median time to detect and mitigate, and repeat causes.
  • +
+
+
+

01 · The process

How incident response works

-
-

Incident response is what a team does from the moment something breaks in production until users are fine again and the cause is fixed. It runs as a loop: what the team learns from one incident changes the alerts, runbooks and code the next incident meets.

-
- -

- An incident is an unplanned event that hurts users or puts data at risk: an outage, a slow checkout, a leaked credential. -

- This guide is written for startups and small companies. Often one or two engineers are on call, and the engineer who gets paged is the one who fixes the problem, so every step is sized for that. For the formal versions, written for larger security teams, see NIST SP 800-61 and the SANS Incident Handler's Handbook. + An incident is an unplanned event that hurts users or puts data at risk: an outage, a slow checkout, a leaked credential. For the formal process, written for larger security teams, see NIST SP 800-61 and the SANS Incident Handler's Handbook.

The process has four phases. You Prepare on a quiet day. When an alert fires, you Detect and triage, then Mitigate and resolve until users are no longer affected and the system is clean. Afterwards you Learn in a postmortem whose action items go back into preparation: a load test that would have caught the bug, an alert that fires two minutes sooner, a rollback that takes one command. @@ -569,15 +581,16 @@ const articleJsonLd = { .ir-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .ir-guide h3 { margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .ir-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .ir-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .ir-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .ir-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .ir-guide strong { font-weight: 600; color: var(--foreground); } .ir-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .ir-guide pre { margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .ir-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .ir-guide a:not(.guide-button):hover { color: var(--foreground); } .ir-guide .guide-caption { margin: 0.7rem 0 0; font-family: var(--font-mono); font-size: 10px; line-height: 1.6; color: var(--muted-foreground); } - .ir-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .ir-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } + .ir-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .ir-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .ir-guide .guide-takeaways li::marker { color: var(--primary); } .ir-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } /* One color per NIST phase: set --phase on the element. */ diff --git a/apps/landing/src/pages/guides/log-parsing.astro b/apps/landing/src/pages/guides/log-parsing.astro index d1eebbb8ba..fae13c4e82 100644 --- a/apps/landing/src/pages/guides/log-parsing.astro +++ b/apps/landing/src/pages/guides/log-parsing.astro @@ -29,13 +29,14 @@ const authorUrl = `https://github.com/${author.github}`; const toc = [ { depth: 2, slug: "definition", text: "Log parsing, defined" }, { depth: 2, slug: "formats", text: "Formats and techniques" }, + { depth: 3, slug: "tools", text: "Log parsing tools" }, { depth: 2, slug: "collector", text: "The OpenTelemetry Collector" }, { depth: 3, slug: "file-log", text: "The file log receiver" }, { depth: 3, slug: "config", text: "Pick your log format" }, { depth: 3, slug: "run", text: "Run it" }, { depth: 3, slug: "see", text: "See the parsed fields" }, { depth: 2, slug: "own-format", text: "Parse your own format" }, - { depth: 2, slug: "mistakes", text: "Common mistakes" }, + { depth: 2, slug: "mistakes", text: "Best practices and mistakes" }, { depth: 2, slug: "by-hand", text: "Parse a file by hand" }, ]; const sectionNav = toc.filter((h) => h.depth === 2); @@ -312,6 +313,16 @@ const checkOutput = `{'client_address': '203.0.113.7', 'time_local': '19/Oct/202 no match on line 6: 192.0.2.44 - - [19/Oct/2026:14:02:17 +0000] "\\x16\\x03\\x01\\x0 1 lines did not match`; +// Facts from each vendor's own page, last verified 2026-10-31. +const tools = [ + ["OpenTelemetry Collector", "https://opentelemetry.io/docs/collector/", "Vendor-agnostic pipeline that receives, processes and exports logs, metrics and traces", "Open source, Apache 2.0", "Free", "Parsing once and sending to any OTLP backend"], + ["Fluent Bit", "https://fluentbit.io/", "Lightweight processor and forwarder for logs, metrics and traces; a CNCF graduated project", "Open source, Apache 2.0", "Free", "An agent on every node or container"], + ["Logstash", "https://www.elastic.co/logstash", "Elastic's server-side pipeline; grok turns unstructured text into fields", "Apache 2.0 for the -oss build, Elastic License for the default build", "Free to self-host", "Elastic Stack users and grok patterns"], + ["Vector", "https://vector.dev/", "Observability pipeline maintained by Datadog; parses with Vector Remap Language", "Open source, MPL 2.0", "Free", "Programmable transforms in one binary"], + ["Graylog", "https://graylog.org/products/source-available/", "Log management with pipeline processing, search and alerts", "Graylog Open: SSPL; Enterprise and Security editions are paid", "Open is free; Enterprise uses value-based licensing", "Self-hosted log search with parsing built in"], + ["Splunk", "https://www.splunk.com/en_us/products/pricing.html", "Commercial data platform; the rex command extracts fields with a regex at search time", "Proprietary", "Ingest, workload, entity or activity pricing; free trials", "Teams already on Splunk"], +]; + const mistakes = [ ["A loose regex", "Anchor the pattern with ^ and $ so a partial match can't fill half the fields, and use negated classes such as [^\"]* instead of .*, which backtracks across the rest of the line."], ["Keeping query strings", "Query strings carry session tokens, emails and IDs. The path group in this guide stops at ?, so they never reach an attribute."], @@ -432,14 +443,30 @@ const articleJsonLd = {

+
+

+ Log parsing is splitting raw log lines into structured fields, such as the timestamp, the severity, the status code or the URL path. Once a line is parsed, tools can filter, count and alert on those fields instead of searching free text. +

+

+ This guide covers the common log formats and the techniques and tools used to parse them, how to parse logs in the OpenTelemetry Collector with a config for each format, how to write a parser for your own format, and how to parse a log file by hand. +

+ +
+

Key takeaways

+
    +
  • The format decides the parser: JSON, logfmt and syslog have their own, other text needs a regex with named groups.
  • +
  • Parse once in a pipeline such as the OpenTelemetry Collector, so every backend gets the same fields.
  • +
  • Convert status codes and sizes to integers: as text, "502" >= "60" is false.
  • +
  • Let lines that don't match through with their raw body; they are often the ones worth reading.
  • +
  • For code you own, log JSON from a structured logger instead of parsing text later.
  • +
+
+
+

01 · Definition

Log parsing, defined

-
-

Log parsing is splitting each line of a log into named fields, such as the time, the status code or the URL path. Tools can then filter and count by those fields instead of searching the text.

-
-

Here is one request from an nginx access log, before and after parsing. Each color is one field, and the same colors mark that field in the regex and config further down.

@@ -491,6 +518,23 @@ const articleJsonLd = {

Any text format without a dedicated parser falls back to a regular expression, where each named group, written (?P<name>...), becomes a field. Grok, popularized by Logstash, is regex with a library of ready-made named patterns: %{IP:client} matches an IP address, and %{HTTPD_COMBINEDLOG} matches a whole nginx or Apache line. The next section has a Collector config for each format in the table.

+ +

Log parsing tools

+
+ + + + + + {tools.map(([name, url, what, license, pricing, bestFor]) => ( + + ))} + +
ToolWhat it isLicensePricingBest for
{name}{what}{license}{pricing}{bestFor}
+
+

+ Maple stores logs that arrive over OTLP, so this guide parses them in the Collector before they are sent. +

@@ -629,8 +673,8 @@ const articleJsonLd = {
-

05 · Mistakes

-

Common log parsing mistakes

+

05 · Best practices

+

Log parsing best practices and common mistakes

A parser that looks right on the sample line can still lose data in these ways:

{mistakes.map(([title, body], index) => ( @@ -733,7 +777,7 @@ const articleJsonLd = { .lp-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .lp-guide h3 { margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .lp-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .lp-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .lp-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .lp-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .lp-guide strong { font-weight: 600; color: var(--foreground); } .lp-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); overflow-wrap: anywhere; } .lp-guide pre { position: relative; margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); tab-size: 4; } @@ -745,9 +789,10 @@ const articleJsonLd = { .lp-guide .guide-list li::marker { color: var(--primary); } .lp-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .lp-guide a:not(.guide-button):hover { color: var(--foreground); } - .lp-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .lp-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } .lp-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } + .lp-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .lp-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .lp-guide .guide-takeaways li::marker { color: var(--primary); } /* Syntax colors stay neutral or in the page accent, so the field colors are the only hues in code. */ .lp-guide .tok-comment { color: var(--muted-foreground); } diff --git a/apps/landing/src/pages/guides/loguru.astro b/apps/landing/src/pages/guides/loguru.astro index d90e1c4d4a..4587ce0296 100644 --- a/apps/landing/src/pages/guides/loguru.astro +++ b/apps/landing/src/pages/guides/loguru.astro @@ -419,17 +419,29 @@ const articleJsonLd = {
-
-

01 · Basics

-

Get started with Loguru

+
+

+ Loguru is a third-party logging library for Python. Instead of the handlers and formatters the standard logging module needs, it gives you one ready-made logger and a single add() call for each place your logs should go. +

+

+ This guide covers installing Loguru, setting the level, writing to files, JSON output, adding context to each line, logging exceptions, using Loguru alongside the logging module, and sending Loguru logs to OpenTelemetry. +

-
-

Loguru is a popular logging library for Python that takes almost no setup. You import one ready-made logger and call it.

+
+

Key takeaways

+
    +
  • from loguru import logger is the whole setup; logger.add() adds sinks such as files.
  • +
  • rotation and retention on a file sink keep log files from filling the disk.
  • +
  • serialize=True writes JSON lines that log search tools can filter field by field.
  • +
  • Add production sinks with diagnose=False so tracebacks don't print passwords and tokens.
  • +
  • In a package other people install, log with the standard logging module; use Loguru in your own apps.
  • +
+
-

- This guide starts with your first log line and then adds what most apps need: a log level, log files, JSON output and extra context on each line. The last section sends your Loguru logs to an observability tool, where you can search them and see which request wrote each line. -

+
+

01 · Basics

+

Get started with Loguru

Install Loguru with pip, then import logger and start logging. Loguru prints colored lines to your terminal out of the box:

{installCommand}
@@ -750,7 +762,7 @@ const articleJsonLd = { .loguru-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .loguru-guide h3 { display: flex; align-items: center; gap: 0.6rem; margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .loguru-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .loguru-guide > section > p:not(.guide-eyebrow, .guide-kicker), .loguru-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .loguru-guide > section > p:not(.guide-eyebrow, .guide-kicker) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .loguru-guide strong { font-weight: 600; color: var(--foreground); } .loguru-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); overflow-wrap: anywhere; } .loguru-guide pre { position: relative; margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } @@ -761,9 +773,10 @@ const articleJsonLd = { .loguru-guide pre + .pre-output { margin-top: -1rem; border-top-left-radius: 0; border-top-right-radius: 0; background: color-mix(in oklab, var(--background) 70%, var(--bg-deep)); } .loguru-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .loguru-guide a:not(.guide-button):hover { color: var(--foreground); } - .loguru-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .loguru-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } .loguru-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } + .loguru-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .loguru-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .loguru-guide .guide-takeaways li::marker { color: var(--primary); } /* One color per system: set --sys on the element. */ .loguru-guide .sys-badge { display: inline-flex; align-items: center; border: 1px solid color-mix(in oklab, var(--sys) 45%, transparent); border-radius: 999px; background: color-mix(in oklab, var(--sys) 14%, transparent); padding: 0.15rem 0.6rem; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; text-transform: none; color: color-mix(in oklab, var(--sys) 70%, var(--foreground)); white-space: nowrap; } diff --git a/apps/landing/src/pages/guides/new-relic-pricing.astro b/apps/landing/src/pages/guides/new-relic-pricing.astro index 1961053f9b..276a9901b3 100644 --- a/apps/landing/src/pages/guides/new-relic-pricing.astro +++ b/apps/landing/src/pages/guides/new-relic-pricing.astro @@ -152,6 +152,16 @@ const faqs = [ answer: "Users plus data. On Standard, the first full platform user is $10 a month and each additional one $99 a month, up to five. On Pro each full platform user is $349 a month with a 1-year commitment, or $418.80 a month without one. Core users are $49 a month on any paid plan, and every GB past the first 100 is $0.40. A 12-person team sending 800 GB pays about $979 a month with 4 full platform and 8 core users on Standard, or $4,468 with all 12 on Pro.", }, + { + question: "Why is New Relic expensive?", + answer: + "Mostly because of full platform users. Anyone who needs the APM, infrastructure or browser views, including whoever is on call, needs one: $99 a month on Standard and $349 on Pro with a 1-year commitment. Twelve full platform users on Pro cost $4,188 a month before any data.", + }, + { + question: "Are there hidden costs in New Relic pricing?", + answer: + "Not hidden, but some sit outside the headline rates. Data Plus raises data from $0.40 to $0.60 per GB, storing data in the EU region adds $0.05 per GB, synthetic checks past your edition's allowance cost $0.005 each, and extended retention and Advanced Compute are paid add-ons.", + }, { question: "What happens past 100 GB on the New Relic free tier?", answer: @@ -248,14 +258,29 @@ const articleJsonLd = {
+
+

+ New Relic is an observability platform for application performance monitoring, infrastructure, logs and more. Its pricing has two parts: users, billed by user type, and data ingest, where the first 100 GB each month is free and each GB after that costs $0.40. +

+

+ This guide covers the four editions, the free tier, user types and data rates, a worked monthly bill for a 12-person team, and ways to lower a New Relic bill. +

+
+

Key takeaways

+
    +
  • The free tier includes 100 GB of data a month, one full platform user and unlimited basic users, with no time limit.
  • +
  • Data past 100 GB costs $0.40 per GB ($0.60 with Data Plus); hosts, agents and containers are free.
  • +
  • Full platform users cost $10 for the first and $99 for each after on Standard (5 at most), $349 on Pro with a 1-year commitment.
  • +
  • Core users cost $49 a month and get logs and errors, but not the APM or infrastructure screens.
  • +
  • On the free tier, passing 100 GB stops ingest and platform access until the next month.
  • +
+
+
+

01 · Pricing model

The New Relic pricing model

-
-

New Relic charges for two things: the people who use it and the data you send it. The first 100 GB of data each month is free, and every GB after that costs $0.40.

-
-

People are billed by user type, and only two of the three types cost money. The plan, called an edition (Free, Standard, Pro or Enterprise), sets the price of a full platform user, how many you can add and the support level.

@@ -638,15 +663,16 @@ const articleJsonLd = { .nr-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .nr-guide h3 { margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .nr-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .nr-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .nr-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .nr-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .nr-guide strong { font-weight: 600; color: var(--foreground); } .nr-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .nr-guide pre { margin: 1rem 0 1.25rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .nr-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .nr-guide a:not(.guide-button):hover { color: var(--foreground); } .nr-guide .guide-caption { margin: 0.7rem 0 1.5rem; font-family: var(--font-mono); font-size: 10px; line-height: 1.6; color: var(--muted-foreground); } - .nr-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .nr-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } + .nr-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .nr-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .nr-guide .guide-takeaways li::marker { color: var(--primary); } .nr-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } /* Code: keywords in the accent, names in teal; neither color is a billing meter. */ diff --git a/apps/landing/src/pages/guides/pino-logger.astro b/apps/landing/src/pages/guides/pino-logger.astro index 530655c5b0..7c374f5746 100644 --- a/apps/landing/src/pages/guides/pino-logger.astro +++ b/apps/landing/src/pages/guides/pino-logger.astro @@ -398,14 +398,30 @@ const articleJsonLd = {
+
+

+ Pino is a structured logger for Node.js. It writes every log entry as one line of JSON with a level, a timestamp and any fields you pass, and it is designed to add as little overhead as possible to your application. +

+

+ This guide covers installing Pino and writing your first logs, configuring it for production, logging HTTP requests with pino-http or Fastify, adding trace IDs with OpenTelemetry, and how Pino compares with Winston. +

+ +
+

Key takeaways

+
    +
  • Pass data as an object first: logger.info({ orderId }, "order created") gives you a field to search.
  • +
  • A child logger adds a request ID or tenant to every line it writes.
  • +
  • List secret paths in redact; a token under an unlisted key still goes out in clear text.
  • +
  • Use pino-pretty in development only and keep production output as JSON.
  • +
  • With the OpenTelemetry Pino instrumentation, each line carries the trace ID of the request that wrote it.
  • +
+
+
+

01 · Definition

Pino, the JSON logger for Node.js

-
-

Pino is a logger for Node.js that writes each log entry as one line of JSON. It is built to add as little work as possible to the code that serves your requests.

-
-

JSON lines suit services that run in containers or on platforms that collect stdout: whatever reads the output can filter on fields instead of matching text. Pino is MIT-licensed, Fastify uses it as its built-in logger, and pino-http adds request logging to Express and plain http servers.

@@ -708,7 +724,10 @@ const articleJsonLd = {

- Choose Pino when logs are JSON headed for a collector and per-call cost matters; Pino publishes its own benchmarks against other loggers. Choose Winston when the process itself must write several formats to several destinations, or an existing codebase depends on its format pipeline. Moving between them is mostly mechanical: both take a metadata object and a message, and Pino puts the object first. + In Pino's own benchmark, a run of logger.info('hello world') calls averaged 114.8 ms with Pino and 270.2 ms with Winston. +

+

+ Choose Pino when logs are JSON headed for a collector and per-call cost matters. Choose Winston when the process itself must write several formats to several destinations, or an existing codebase depends on its format pipeline. Moving between them is mostly mechanical: both take a metadata object and a message, and Pino puts the object first.

@@ -745,16 +764,17 @@ const articleJsonLd = { .pino-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .pino-guide h3 { display: flex; align-items: center; gap: 0.6rem; margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .pino-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .pino-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .pino-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .pino-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .pino-guide strong { font-weight: 600; color: var(--foreground); } .pino-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .pino-guide pre { margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .pino-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .pino-guide a:not(.guide-button):hover { color: var(--foreground); } .pino-guide .guide-caption { margin: 0.7rem 0 0; font-family: var(--font-mono); font-size: 10px; line-height: 1.6; color: var(--muted-foreground); } - .pino-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .pino-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } .pino-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } + .pino-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .pino-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .pino-guide .guide-takeaways li::marker { color: var(--primary); } .pino-guide .guide-list { display: grid; gap: 0.6rem; margin: 1.25rem 0 1.5rem; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.65; color: color-mix(in oklab, var(--foreground) 80%, var(--background)); } .pino-guide .guide-list li::marker { color: var(--primary); } diff --git a/apps/landing/src/pages/guides/prometheus-metrics.astro b/apps/landing/src/pages/guides/prometheus-metrics.astro index 571da3a3bb..1bfd9f9caa 100644 --- a/apps/landing/src/pages/guides/prometheus-metrics.astro +++ b/apps/landing/src/pages/guides/prometheus-metrics.astro @@ -335,16 +335,32 @@ const articleJsonLd = {
+
+

+ Prometheus is an open-source monitoring system that collects numeric measurements, called metrics, from your applications and servers and stores them as time series. You query them with PromQL, chart them in Grafana and alert on them. +

+

+ This guide explains what a Prometheus metric looks like, the four metric types (counter, gauge, histogram and summary) and when to use each, the metrics worth watching first, and how to collect and chart them with Prometheus and Grafana. +

+ +
+

Key takeaways

+
    +
  • Counters only go up: chart them with rate() or increase(), never raw.
  • +
  • Gauges go up and down: read the value directly.
  • +
  • Use a histogram for latency. Its buckets add up across instances; summary percentiles don't.
  • +
  • Start with request rate, error ratio and p95 latency, and alert on up == 0.
  • +
  • Keep user IDs and full URLs out of labels: every label value is a new time series.
  • +
+
+
+

01 · Definition

What a Prometheus metric is

-
-

A Prometheus metric is a named number that your application keeps up to date, such as how many requests it has served. Prometheus reads it every few seconds and stores each reading, so you can chart how the number changes over time.

-
-

- Applications publish their metrics as plain text on an HTTP endpoint, usually /metrics. Every line is one number: + A Prometheus metric is a named number your application keeps up to date, such as the count of requests served. Prometheus reads it every few seconds and stores each reading. Applications publish their metrics as plain text on an HTTP endpoint, usually /metrics. Every line is one number:

+ +

Which type should I use?

+
    +
  • It counts things that happen, such as requests or errors: Counter
  • +
  • It can go down for a reason other than a restart: Gauge
  • +
  • You need percentiles, such as p95 latency: Histogram
  • +
  • One process, with percentiles you know in advance: Summary works, but a histogram still does more
  • +
@@ -686,16 +710,18 @@ const articleJsonLd = { .prom-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .prom-guide h3 { display: flex; align-items: center; gap: 0.6rem; margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .prom-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .prom-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .prom-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .prom-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .prom-guide strong { font-weight: 600; color: var(--foreground); } .prom-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .prom-guide pre { margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .prom-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .prom-guide a:not(.guide-button):hover { color: var(--foreground); } .prom-guide .guide-caption { margin: 0.7rem 0 0; font-family: var(--font-mono); font-size: 10px; line-height: 1.6; color: var(--muted-foreground); } - .prom-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .prom-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } .prom-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } + .prom-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .prom-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .prom-guide .guide-takeaways li::marker { color: var(--primary); } + .prom-guide .guide-list { display: grid; gap: 0.6rem; margin: 0 0 1.5rem; padding-left: 1.2rem; list-style: disc; font-size: 16px; line-height: 1.7; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } /* One color per metric type: set --type on the element. */ .prom-guide .type-badge { display: inline-flex; align-items: center; gap: 0.4rem; border: 1px solid color-mix(in oklab, var(--type) 45%, transparent); border-radius: 999px; background: color-mix(in oklab, var(--type) 14%, transparent); padding: 0.15rem 0.6rem; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; color: color-mix(in oklab, var(--type) 70%, var(--foreground)); white-space: nowrap; } diff --git a/apps/landing/src/pages/guides/python-logging-levels.astro b/apps/landing/src/pages/guides/python-logging-levels.astro index 36289d204c..969c61e560 100644 --- a/apps/landing/src/pages/guides/python-logging-levels.astro +++ b/apps/landing/src/pages/guides/python-logging-levels.astro @@ -311,14 +311,30 @@ const articleJsonLd = {
+
+

+ Python's built-in logging module tags every message with a log level: DEBUG, INFO, WARNING, ERROR or CRITICAL. The level you set decides which messages are written, so you can keep detailed output while developing and only the important messages in production. +

+

+ This guide explains what each level is for, how to set the level in code, from a command-line flag or from an environment variable, how logger and handler levels work together, and how levels carry over when you send Python logs to OpenTelemetry. +

+ +
+

Key takeaways

+
    +
  • Python's default level is WARNING, so info() and debug() print nothing until you set one.
  • +
  • Run production at INFO and switch to DEBUG only while you investigate.
  • +
  • Read the level from a --log-level flag or a LOG_LEVEL variable, so changing it needs no code edit.
  • +
  • basicConfig does nothing if logging is already set up: pass force=True or set the root logger's level.
  • +
  • Set library loggers such as urllib3 to WARNING to hide their DEBUG and INFO lines.
  • +
+
+
+

01 · Basics

The Python logging levels

-
-

A log level is a label on each log message that says how serious it is. You choose a level for your program, and Python drops every message below it.

-
-

The method you call sets a message's level: log.debug(), log.info(), log.warning(), log.error() or log.critical(). These are the five levels, from least to most serious:

@@ -389,7 +405,7 @@ const articleJsonLd = {

basicConfig runs once

-

If a framework or library already set up logging, basicConfig silently does nothing. Set the level directly instead:

+

If a framework or library already set up logging, basicConfig silently does nothing. Pass force=True to replace the existing setup, or set the level directly instead:

@@ -536,16 +552,17 @@ const articleJsonLd = { .pylog-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .pylog-guide h3 { margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .pylog-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .pylog-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption), .pylog-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .pylog-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-caption) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .pylog-guide strong { font-weight: 600; color: var(--foreground); } .pylog-guide code:not(pre code) { border: 1px solid var(--border); background: var(--bg-elevated); padding: 0.1rem 0.35rem; font-family: var(--font-mono); font-size: 12px; color: var(--foreground); } .pylog-guide pre { position: relative; margin: 1.25rem 0 1.5rem; overflow-x: auto; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .pylog-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .pylog-guide a:not(.guide-button):hover { color: var(--foreground); } .pylog-guide .guide-caption { margin: 0.7rem 0 0; font-family: var(--font-mono); font-size: 10px; line-height: 1.6; color: var(--muted-foreground); } - .pylog-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .pylog-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } .pylog-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } + .pylog-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .pylog-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .pylog-guide .guide-takeaways li::marker { color: var(--primary); } /* One color per level: set --lvl on the element. */ .pylog-guide .lvl { color: color-mix(in oklab, var(--lvl) 85%, var(--foreground)); } diff --git a/apps/landing/src/pages/guides/sentry-pricing.astro b/apps/landing/src/pages/guides/sentry-pricing.astro index bc0bd5fa3d..70d072a3ac 100644 --- a/apps/landing/src/pages/guides/sentry-pricing.astro +++ b/apps/landing/src/pages/guides/sentry-pricing.astro @@ -29,6 +29,7 @@ const toc = [ { depth: 2, slug: "plans", text: "Plans and prices" }, { depth: 3, slug: "business", text: "Team or Business" }, { depth: 3, slug: "seer", text: "Seer add-on" }, + { depth: 3, slug: "discounts", text: "Discounts" }, { depth: 2, slug: "free-plan", text: "The free plan" }, { depth: 3, slug: "free-limits", text: "Free plan limits" }, { depth: 3, slug: "self-hosted", text: "Self-hosted Sentry" }, @@ -281,14 +282,29 @@ const articleJsonLd = {
+
+

+ Sentry is an application monitoring platform focused on error tracking and performance monitoring. It has a free Developer plan for one user and paid Team and Business plans, and it bills errors, spans, replays and logs by volume beyond each plan's included quota. +

+

+ This guide covers each plan and its price, what the free plan includes, how usage is billed and what happens past your quota, the available discounts, and two worked monthly bills. +

+
+

Key takeaways

+
    +
  • Developer is $0 for one user, with 5,000 errors, 5M spans and 50 replays a month.
  • +
  • Team is $29 a month ($26 billed annually) and Business $89 ($80); both include 50,000 errors and 5M spans.
  • +
  • Business charges about twice the Team rate for each error and span above the included volume.
  • +
  • Reserved volume costs 20% less than pay-as-you-go for errors, spans, replays and attachments.
  • +
  • Once the pay-as-you-go budget runs out, new data is dropped until the billing cycle resets.
  • +
+
+
+

01 · Plans

Sentry plans and prices

-
-

Sentry charges a flat monthly price for the plan, then a separate price for each kind of data you send beyond what the plan includes. Errors, spans, session replays and logs each have their own allowance and their own rate.

-
-
@@ -328,6 +344,13 @@ const articleJsonLd = {

Seer, Sentry's AI debugging agent, is a separate subscription on Team and Business at $40 per active contributor per month. An active contributor is anyone who opens two or more pull requests in a month against a repository connected to Sentry with a Seer feature turned on. Seer is billed on its own line and does not draw from the pay-as-you-go budget.

+ +

Discounts

+
    +
  • Annual billing takes about 10% off: Team is $26 a month instead of $29, Business $80 instead of $89.
  • +
  • Open-source projects and nonprofits can apply for a sponsored account.
  • +
  • Sentry for Startups gives up to $5,000 in credits for 12 months to companies founded in the last 2 years, with under $5M raised and new to paying for Sentry.
  • +

Verified {verified} against sentry.io/pricing and Sentry's pricing docs, which round the per-unit prices.

@@ -649,6 +672,8 @@ const articleJsonLd = {
  • Sentry: Pricing (verified {verified})
  • Sentry docs: Pricing and billing
  • +
  • Sentry help: Do I qualify for a sponsored account? (verified 2026-10-31)
  • +
  • Sentry for Startups (verified 2026-10-31)
  • Sentry docs: Quota management
  • Sentry docs: Spike protection
  • Sentry docs: Session replay for JavaScript
  • @@ -674,7 +699,7 @@ const articleJsonLd = { .pricing-guide h2 { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 500; line-height: 1.08; letter-spacing: -0.03em; color: var(--foreground); text-wrap: balance; } .pricing-guide h3 { margin: 3rem 0 0.8rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 550; line-height: 1.3; letter-spacing: -0.015em; color: var(--foreground); } .pricing-guide h4 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; font-weight: 550; color: var(--foreground); } - .pricing-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-note, .guide-verified), .pricing-guide .guide-answer p { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } + .pricing-guide > section > p:not(.guide-eyebrow, .guide-kicker, .guide-note, .guide-verified) { margin: 0 0 1.15rem; font-size: 17px; line-height: 1.7; font-weight: 430; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .pricing-guide .guide-note, .pricing-guide .guide-verified { margin: -0.75rem 0 1.5rem; font-size: 13px; line-height: 1.65; color: var(--muted-foreground); } .pricing-guide .guide-verified { margin-top: 0; } .pricing-guide strong { font-weight: 600; color: var(--foreground); } @@ -682,8 +707,9 @@ const articleJsonLd = { .pricing-guide pre { margin: 0; overflow-x: auto; border: 1px solid var(--border); border-radius: 0 0.5rem 0.5rem 0.5rem; background: var(--bg-deep); padding: 0.9rem 1.1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; color: var(--foreground); } .pricing-guide a:not(.guide-button) { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--primary) 42%, transparent); text-underline-offset: 3px; transition: color 150ms ease; } .pricing-guide a:not(.guide-button):hover { color: var(--foreground); } - .pricing-guide .guide-answer { margin: 2rem 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } - .pricing-guide .guide-answer p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--foreground); } + .pricing-guide .guide-takeaways { margin: 2rem 0 0; border-left: 2px solid var(--primary); border-radius: 0 0.5rem 0.5rem 0; background: color-mix(in oklab, var(--primary) 8%, var(--bg-deep)); padding: 1.25rem 1.35rem; } + .pricing-guide .guide-takeaways ul { display: grid; gap: 0.5rem; margin: 0.8rem 0 0; padding-left: 1.1rem; list-style: disc; font-size: 15px; line-height: 1.6; color: var(--foreground); } + .pricing-guide .guide-takeaways li::marker { color: var(--primary); } .pricing-guide .guide-kicker { margin: 0; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); } .pricing-guide .guide-list { margin: 0 0 1.5rem; padding-left: 1.2rem; list-style: disc; font-size: 16px; line-height: 1.7; color: color-mix(in oklab, var(--foreground) 85%, var(--background)); } .pricing-guide .guide-list li + li { margin-top: 0.35rem; }