Skip to main content
Technology & EngineeringMonitoring Services266 lines

New Relic

"New Relic: APM, distributed tracing, browser monitoring, custom events, NRQL queries, alert policies, Node.js and browser agents"

Quick Summary16 lines
You are an expert in integrating New Relic for application monitoring.

## Key Points

- **Use distributed tracing over cross-application tracing** — distributed tracing is the modern replacement and works across all language agents and third-party services.
- **Send custom events for business metrics** — NRQL can query custom events just like built-in data, giving you dashboards that track revenue, signups, or feature usage alongside technical metrics.
- **Exclude sensitive headers and attributes** — configure the `attributes.exclude` list to strip cookies, auth tokens, and PII from trace data before it leaves your infrastructure.

## Quick Example

```html
<!-- Paste the browser agent snippet from New Relic UI into <head>,
     or use the npm package for SPA frameworks -->
```
skilldb get monitoring-services-skills/New RelicFull skill: 266 lines
Paste into your CLAUDE.md or agent config

New Relic — Application Monitoring

You are an expert in integrating New Relic for application monitoring.

Core Philosophy

Overview

New Relic is a full-stack observability platform that provides APM, infrastructure monitoring, browser monitoring, log management, and custom dashboards. Its query language NRQL (New Relic Query Language) is central to building dashboards, alerts, and ad-hoc investigations. The Node.js agent auto-instruments popular frameworks and the browser agent captures real user performance data.

Setup & Configuration

Node.js APM Agent

// newrelic.ts — must be at the project root or specified via NEW_RELIC_HOME
// The agent is loaded via require('newrelic') as the FIRST import in your entry point.

// newrelic.js (CommonJS config file required by the agent)
"use strict";

exports.config = {
  app_name: [process.env.NEW_RELIC_APP_NAME ?? "my-api-service"],
  license_key: process.env.NEW_RELIC_LICENSE_KEY,
  distributed_tracing: {
    enabled: true,
  },
  logging: {
    level: "info",
    filepath: "stdout",
  },
  allow_all_headers: true,
  application_logging: {
    forwarding: {
      enabled: true,
      max_samples_stored: 10000,
    },
  },
  attributes: {
    exclude: [
      "request.headers.cookie",
      "request.headers.authorization",
      "request.headers.proxyAuthorization",
      "request.headers.setCookie*",
      "request.headers.x*",
      "response.headers.cookie",
      "response.headers.authorization",
      "response.headers.proxyAuthorization",
      "response.headers.setCookie*",
    ],
  },
};
// app.ts — entry point: require newrelic FIRST
import "newrelic";
import express from "express";
import { router } from "./routes";

const app = express();
app.use(router);
app.listen(3000);

Browser Monitoring (SPA Agent)

<!-- Paste the browser agent snippet from New Relic UI into <head>,
     or use the npm package for SPA frameworks -->
// lib/newrelic-browser.ts — for React/Next.js apps
import { BrowserAgent } from "@newrelic/browser-agent/loaders/browser-agent";

const agent = new BrowserAgent({
  init: {
    distributed_tracing: { enabled: true },
    privacy: { cookies_enabled: true },
    ajax: { deny_list: ["bam.nr-data.net"] },
  },
  info: {
    beacon: "bam.nr-data.net",
    errorBeacon: "bam.nr-data.net",
    licenseKey: process.env.NEXT_PUBLIC_NEW_RELIC_BROWSER_KEY!,
    applicationID: process.env.NEXT_PUBLIC_NEW_RELIC_APP_ID!,
    sa: 1,
  },
  loader_config: {
    accountID: process.env.NEXT_PUBLIC_NEW_RELIC_ACCOUNT_ID!,
    trustKey: process.env.NEXT_PUBLIC_NEW_RELIC_TRUST_KEY!,
    agentID: process.env.NEXT_PUBLIC_NEW_RELIC_AGENT_ID!,
    licenseKey: process.env.NEXT_PUBLIC_NEW_RELIC_BROWSER_KEY!,
    applicationID: process.env.NEXT_PUBLIC_NEW_RELIC_APP_ID!,
  },
});

export { agent };

Core Patterns

Custom Events and Attributes

// lib/nr-events.ts
import newrelic from "newrelic";

export function recordBusinessEvent(
  eventType: string,
  attributes: Record<string, string | number | boolean>
) {
  newrelic.recordCustomEvent(eventType, {
    ...attributes,
    environment: process.env.NODE_ENV,
    service: process.env.NEW_RELIC_APP_NAME,
  });
}

// Usage: track domain-specific events queryable with NRQL
recordBusinessEvent("OrderPlaced", {
  orderId: "abc-123",
  total: 59.99,
  itemCount: 3,
  paymentMethod: "stripe",
});

// Query in New Relic:
// SELECT count(*) FROM OrderPlaced FACET paymentMethod SINCE 1 hour ago

Custom Transaction Instrumentation

// lib/nr-tracing.ts
import newrelic from "newrelic";

export function instrumentBackground<T>(
  name: string,
  group: string,
  fn: () => Promise<T>
): Promise<T> {
  return new Promise((resolve, reject) => {
    newrelic.startBackgroundTransaction(`${group}/${name}`, group, () => {
      const transaction = newrelic.getTransaction();

      fn()
        .then((result) => {
          transaction.end();
          resolve(result);
        })
        .catch((error) => {
          newrelic.noticeError(error as Error);
          transaction.end();
          reject(error);
        });
    });
  });
}

// Usage: instrument a queue worker or cron job
await instrumentBackground("processEmailQueue", "Worker", async () => {
  const messages = await queue.receive(10);
  for (const msg of messages) {
    await sendEmail(msg.body);
  }
});

Error Tracking with Context

// middleware/nr-error-handler.ts
import newrelic from "newrelic";
import type { Request, Response, NextFunction } from "express";

export function nrErrorHandler(
  err: Error,
  req: Request,
  res: Response,
  next: NextFunction
) {
  newrelic.noticeError(err, {
    userId: (req as any).user?.id,
    route: req.route?.path ?? req.path,
    method: req.method,
    statusCode: res.statusCode,
  });

  next(err);
}

// Add custom attributes to the current transaction
export function addTransactionContext(req: Request) {
  if ((req as any).user) {
    newrelic.addCustomAttributes({
      "user.id": (req as any).user.id,
      "user.plan": (req as any).user.plan,
    });
  }
}

NRQL Alert Conditions (as Code via Terraform)

resource "newrelic_nrql_alert_condition" "high_error_rate" {
  account_id                   = var.new_relic_account_id
  policy_id                    = newrelic_alert_policy.api_policy.id
  type                         = "static"
  name                         = "API Error Rate > 5%"
  enabled                      = true
  violation_time_limit_seconds = 3600

  nrql {
    query = <<-NRQL
      SELECT percentage(count(*), WHERE error IS true)
      FROM Transaction
      WHERE appName = 'my-api-service'
    NRQL
  }

  critical {
    operator              = "above"
    threshold             = 5
    threshold_duration    = 300
    threshold_occurrences = "all"
  }

  warning {
    operator              = "above"
    threshold             = 2
    threshold_duration    = 300
    threshold_occurrences = "all"
  }
}

Best Practices

  • Use distributed tracing over cross-application tracing — distributed tracing is the modern replacement and works across all language agents and third-party services.
  • Send custom events for business metrics — NRQL can query custom events just like built-in data, giving you dashboards that track revenue, signups, or feature usage alongside technical metrics.
  • Exclude sensitive headers and attributes — configure the attributes.exclude list to strip cookies, auth tokens, and PII from trace data before it leaves your infrastructure.

Common Pitfalls

  • Forgetting to require the agent first — the New Relic Node.js agent must be the very first require/import in your entry point; otherwise auto-instrumentation of Express, pg, Redis, etc. silently fails.
  • High-cardinality custom attributes on transactions — adding unique IDs (like request IDs or session tokens) as transaction attributes inflates data volume and slows NRQL queries; use custom events for high-cardinality data instead.

Anti-Patterns

Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.

Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.

Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.

Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.

Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.

Install this skill directly: skilldb add monitoring-services-skills

Get CLI access →

Related Skills

Baselime

Baselime is a serverless-native observability platform designed for AWS, unifying logs, traces, and metrics. It provides real-time insights and contextualized data to help you understand and troubleshoot your distributed serverless applications.

Monitoring Services245L

BetterStack

"BetterStack (formerly Better Uptime + Logtail): uptime monitoring, log management, status pages, incident management, alerting"

Monitoring Services348L

Checkly

"Checkly: synthetic monitoring, API checks, browser checks, Playwright-based E2E monitoring, monitoring-as-code CLI"

Monitoring Services202L

Cronitor

Cronitor is a robust monitoring service designed to ensure your background jobs (cron jobs, scheduled tasks, async workers) and APIs run reliably. It actively monitors the health and execution of automated processes, alerting you instantly to missed runs, failures, or delays. Use Cronitor to gain peace of mind and critical visibility into your application's backend operations.

Monitoring Services218L

Datadog

"Datadog: APM, log management, infrastructure monitoring, RUM, custom metrics, dashboards, Node.js tracing"

Monitoring Services328L

Grafana Cloud

Grafana Cloud is a fully managed observability platform that unifies metrics (Prometheus/Graphite), logs (Loki), and traces (Tempo) within a single Grafana interface. Use it to gain deep insights into your applications and infrastructure without the operational overhead of managing your own observability stack, allowing you to focus on building and improving your services.

Monitoring Services202L