Scraper Observability 2026: OpenTelemetry, Sentry, Custom Metrics Setup

Scrapers fail in ways normal backend services do not, and that is exactly why scraper observability deserves its own discipline in 2026. A healthy run can still return poisoned data, get partially blocked, slow down only in one ASN, or silently degrade on one selector while every infrastructure graph stays green. If you operate pricing crawlers, lead-gen bots, marketplace monitors, or SERP collectors, the stack that works now is not “logs plus uptime checks.” The practical baseline is traces for request chains, error grouping for DOM and anti-bot failures, and custom metrics for data quality. Anything less leaves you blind when a run goes from 98.7% usable rows to 81% overnight.

What scraper observability actually needs

The biggest mistake teams make is copying API observability patterns without accounting for scraper behavior. Scrapers are distributed, bursty, proxy-heavy, and often judged by data freshness rather than raw uptime. You need to observe four things at once:

  • Fetch health, including DNS, connect, TLS, TTFB, and total response time
  • Extraction health, including selector misses, parse errors, schema drift, and empty-field rates
  • Block health, including CAPTCHA hits, 403s, soft blocks, fingerprint failures, and retry inflation
  • Business output, including fresh rows, duplicate ratios, cost per successful page, and time-to-ingest

For most production teams, the first useful SLO is not “99.9% requests succeed.” It is “95% of scheduled jobs deliver at least 97% usable records within 20 minutes.” That reframes instrumentation around outcomes, which is also how good Scraper SLO Patterns: Error Budgets and Alerting at 2026 Scale setups avoid alert fatigue.

A concrete target many teams use now looks like this: p95 page fetch under 4.5 seconds for commodity targets, block rate under 3%, extraction success above 98%, and freshness lag under 15 minutes for hourly pipelines. Those numbers vary by niche, but the point is to define thresholds that reflect scraper reality, not generic service health.

OpenTelemetry setup that works for scrapers

OpenTelemetry is now the default instrumentation layer because it lets you unify workers, job schedulers, browser automation, proxy gateways, and downstream storage. The pattern that holds up in production is simple: instrument scraper workers with OTEL SDKs, send OTLP to an OpenTelemetry Collector, fan out traces to Tempo or Datadog, metrics to Prometheus-compatible storage, and logs only where you truly need retention.

The minimum useful span model

One scraper job should produce a root span like scrape.job, with child spans for:

  1. queue.dequeue
  2. browser.launch or http.request
  3. page.navigate
  4. anti_bot.challenge
  5. extract.parse
  6. storage.write

This structure makes slowdowns obvious. If page.navigate p95 jumps from 2.1 seconds to 7.8 seconds only on one target, you know you have target-side friction. If extract.parse error rate doubles while network spans are normal, you have a DOM drift problem, not an infra problem.

Keep span attributes strict. Good dimensions are target_domain, job_type, proxy_pool, country, runtime (http, playwright, selenium), and result (success, block, parse_error). Bad dimensions are raw URL, session ID, product ID, and arbitrary query strings. In practice, most teams should cap high-cardinality attributes before they hit the backend, or they will pay for it fast.

Here is a compact Node example for a Playwright-based worker:

import { trace, SpanStatusCode } from "@opentelemetry/api";

const tracer = trace.getTracer("scraper-worker");

export async function scrapeProduct(url: string, page: any) {
  return tracer.startActiveSpan("scrape.job", async (span) => {
    span.setAttribute("target_domain", new URL(url).hostname);
    span.setAttribute("runtime", "playwright");

    try {
      const navStart = Date.now();
      await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
      span.addEvent("page.loaded", { nav_ms: Date.now() - navStart });

      const title = await page.locator("h1").textContent();
      span.setAttribute("extract.title_present", Boolean(title));

      span.setStatus({ code: SpanStatusCode.OK });
      return { title };
    } catch (err: any) {
      span.recordException(err);
      span.setAttribute("result", "parse_or_fetch_error");
      span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
      throw err;
    } finally {
      span.end();
    }
  });
}

The OpenTelemetry Collector matters more than most teams think. Put sampling, attribute cleanup, and tail-based routing there, not in every worker. A common 2026 pattern is 100% retention for error traces, 10% to 20% for success traces, and full-fidelity spans only for newly launched targets during the first two weeks.

Sentry for scraper-specific failures

Sentry is still one of the fastest ways to get value because scraper failures are often exception-rich. Selector breakages, timeout storms, fingerprint mismatches, schema validation failures, and browser crashes all benefit from grouped issues, stack traces, and release tracking. What Sentry is not great at is long-term, high-volume metrics economics. Use it for debugging and regression detection, not as your only observability backend.

The right setup is to send scraper exceptions to Sentry with domain-aware tags like target_domain, job_family, extractor_version, and proxy_vendor. Then add breadcrumbs for navigation steps, retries, block detections, and parser checkpoints. A single grouped issue titled “selector_missing: .price-card span.amount” is much more actionable than 20,000 unstructured logs.

One honest tradeoff is volume. Browser-heavy scrapers can generate huge error throughput during block waves. If 30,000 jobs hit the same anti-bot challenge in 15 minutes, default Sentry ingestion can become expensive noise. The fix is to fingerprint intelligently and drop known duplicate non-actionable events at the SDK or Collector layer. Teams doing this well often cut event volume by 60% to 80% without losing signal.

Custom metrics decide whether your scraper is healthy

Traces tell you where time went. Errors tell you what broke. Custom metrics tell you whether the scraper is delivering business value. This is where Prometheus, Mimir, Grafana Cloud, Datadog metrics, or VictoriaMetrics usually come in.

The metrics that matter most are not generic CPU and memory. They are:

  • scrape_pages_total by domain and result
  • scrape_block_rate
  • extract_success_ratio
  • records_fresh_total
  • field_null_ratio for critical fields like price, title, stock
  • cost_per_1k_successful_pages
  • retry_count_p95
  • job_duration_seconds
  • freshness_lag_seconds

If you only add one non-obvious metric, make it usable_records_ratio. A page can return HTTP 200, parse cleanly, and still be useless because core fields are blank or shifted. Teams that instrument this typically catch silent failures 30 to 90 minutes earlier than teams relying on request success alone.

Here is a practical comparison of where teams usually land:

LayerBest tool choicesStrengthWeak spot
TracesGrafana Tempo, Datadog APMRoot-cause latency and retry chainsCost climbs if span volume is unmanaged
ErrorsSentryFast debugging, release correlation, issue groupingWeak for long-horizon metric analysis
MetricsPrometheus, Mimir, Grafana Cloud, DatadogBest for SLOs, alerts, and cost dashboardsCardinality mistakes hurt quickly
LogsLoki, Datadog Logs, Cloud loggingUseful for rare forensic casesEasy to overspend, low signal at scale

Cost discipline matters here. In 2026, a scraper fleet doing 50 million page attempts per month can easily emit 200 million to 400 million spans if you trace every retry and sub-step. Depending on vendor and retention, that can push trace cost into the low thousands per month. Many teams are finding better economics with Tempo plus cheap object storage for traces, while paying for premium metrics and Sentry issues where query speed matters more. If you are deciding between managed stacks, Datadog vs Grafana Cloud for Scraper Monitoring in 2026 covers the tradeoff most teams are actually weighing.

Alerting, dashboards, and cardinality control

Most scraper alerting is still too noisy because it pages on raw errors instead of degradation patterns. A better dashboard layout has five rows: schedule throughput, request health, block health, extraction quality, and business freshness. If any of those rows need more than four charts, you are probably compensating for missing derived metrics.

Alerts should focus on rate changes and burn rate, not single thresholds. Good alerts include:

  • extract_success_ratio < 97% for 15m on high-priority jobs
  • block_rate > 5% and rising for 10m by domain or proxy pool
  • freshness_lag_seconds exceeding SLA for two consecutive runs
  • usable_records_ratio dropping more than 8 percentage points day-over-day
  • retry_count_p95 doubling without a matching traffic spike

Cardinality is the place scraper teams usually get punished. Product-level labels, URL labels, and session fingerprints explode metric storage and slow queries. As a rule, keep metrics aggregated at domain, job family, region, proxy vendor, and result class. Push page-level detail into traces or sampled logs. A Prometheus or Mimir setup that feels cheap at 5 million series will feel broken at 40 million.

If you operate headless browsers, also split metrics by runtime mode. HTTP scrapers and browser scrapers behave differently enough that shared dashboards hide failures. Browser fleets need extra metrics like cold start time, page memory high-water mark, crash rate per thousand sessions, and CAPTCHA solve time where applicable.

Bottom line

The reliable 2026 stack for scraper observability is OpenTelemetry for traces, Sentry for actionable exceptions, and custom metrics for data quality and SLOs. Start with outcome-oriented metrics like usable records and freshness lag, then add traces and error grouping where they reduce mean time to diagnose. dataresearchtools.com has more detailed coverage on stack choice and SLO design, but the short version is simple: if you cannot see block rate, parse drift, and business output in one place, your scraper is not observable yet.

Related guides on dataresearchtools.com

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top
message me on telegram

Resources

Proxy Signals Podcast
Operator-level insights on mobile proxies and access infrastructure.

Multi-Account Proxies: Setup, Types, Tools & Mistakes (2026)