La forma recomendada de monitorear una aplicación Next.js es depender de los spans nativos de OpenTelemetry emitidos por Next.js junto con la característica de agente híbrido del agente Node.js, en lugar de la instrumentación Next.js integrada del agente. Esta página explica cómo habilitar el agente híbrido, señala aplicaciones de ejemplo y cubre preguntas comunes sobre cómo inyectar el agente del browser y desplegar en proveedores de cloud.
Importante
El soporte nativo de Next.js OpenTelemetry requiere la versión 14.1.0 del agente Node.js o posterior. El agente híbrido solo instrumenta el runtime de Node.js; el edge runtime de Next.js no es compatible, por lo que el ejemplo de register() a continuación sale temprano a menos que NEXT_RUNTIME sea nodejs.
El agente Node.js ha tenido instrumentación Next.js desde 2022 a través de @newrelic/next, y esa instrumentación se integró en el agente en 12.0.0. Sin embargo, era limitada y no funcionaba al desplegar en proveedores cloud como Vercel, AWS Amplify, Netlify o Azure Static Web Apps. Con la introducción del agente híbrido, el agente Node.js puede interceptar spans OpenTelemetry y sintetizar la telemetría que impulsa la experiencia de New Relic. La instrumentación nativa Next.js OpenTelemetry se agregó en 14.1.0.
Habilite el agente híbrido
Para habilitar el agente híbrido y deshabilitar la instrumentación del agente que entra en conflicto con Next.js, establezca la siguiente configuración en newrelic.js:
'use strict'
exports.config = { app_name: ['Your application name'], license_key: 'your-license-key', opentelemetry: { enabled: true }, instrumentation: { http: { enabled: false }, next: { enabled: false }, undici: { enabled: false } }}Sugerencia
Si realiza llamadas nativas de fetch, debe deshabilitar la instrumentación de undici como se muestra arriba. Next.js envuelve a fetch y crea sus propios spans de cliente, por lo que dejar undici habilitado produce spans de cliente duplicados en sus trazas.
Si prefiere usar variables de entorno:
NEW_RELIC_LICENSE_KEY=<your-license-key>NEW_RELIC_APP_NAME=<your-application-name>NEW_RELIC_OPENTELEMETRY_ENABLED=trueNEW_RELIC_INSTRUMENTATION_NEXT_ENABLED=falseNEW_RELIC_INSTRUMENTATION_HTTP_ENABLED=falseNEW_RELIC_INSTRUMENTATION_UNDICI_ENABLED=falseTambién debe agregar un archivo instrumentation.js (o instrumentation.ts para TypeScript) para cargar el agente antes del resto de su aplicación:
async function loadNewRelicAgent() { const { default: newrelic } = await import('newrelic') const agent = newrelic?.agent if (!agent || agent.collector?.isConnected?.()) { return }
await new Promise((resolve) => { const done = () => { clearTimeout(timer) agent.removeListener('started', done) agent.removeListener('errored', done) resolve() } const timer = setTimeout(done, 8000) agent.once('started', done) agent.once('errored', done) })}
export async function register() { // The agent only instruments the Node.js runtime, not the edge runtime. if (process.env.NEXT_RUNTIME !== 'nodejs') { return }
await loadNewRelicAgent()}Consulte la aplicación de ejemplo de Next.js App Router para obtener un ejemplo más completo de esta configuración.
Next.js instrumentación en Vercel
Desplegar en Vercel divide las páginas estáticas y dinámicas en diferentes entornos. En lugar de depender de .env y newrelic.js para cargar la configuración del agente, defina las siguientes variables de entorno en la consola de Vercel en Environment Variables:
NEW_RELIC_LICENSE_KEY=<your-license-key>NEW_RELIC_APP_NAME=<your-application-name>NEW_RELIC_OPENTELEMETRY_ENABLED=trueNEW_RELIC_INSTRUMENTATION_NEXT_ENABLED=falseNEW_RELIC_INSTRUMENTATION_HTTP_ENABLED=falseNEW_RELIC_INSTRUMENTATION_UNDICI_ENABLED=falseAún necesita el archivo instrumentation.js descrito anteriormente; solo cambia la fuente de la configuración en Vercel.
Consulte la aplicación de ejemplo de Next.js App Router para obtener un ejemplo más completo de esta configuración.
Inyectar el agente del browser
Dado que Next.js es un framework full-stack, la mayoría de los clientes desean observabilidad tanto en el cliente como en el servidor. El siguiente ejemplo muestra cómo inyectar el agente del browser de New Relic en cada página.
Edite el archivo de diseño raíz dentro de app/ y agregue lo siguiente:
import Script from 'next/script';
async function loadNewRelicAgent() { const { default: newrelic } = await import('newrelic') const agent = newrelic?.agent if (!agent || agent.collector?.isConnected?.()) { return newrelic }
await new Promise((resolve) => { const done = () => { clearTimeout(timer) agent.removeListener('started', done) agent.removeListener('errored', done) resolve() } const timer = setTimeout(done, 8000) agent.once('started', done) agent.once('errored', done) })
return newrelic}
export default async function RootLayout({ children,}){ // Wait for the agent to connect before requesting the browser timing header. const newrelic = await loadNewRelicAgent() const browserTimingHeader = newrelic.getBrowserTimingHeader({ hasToRemoveScriptWrapper: true, allowTransactionlessInjection: true, })
return ( <html lang="en"> <body className="min-h-full flex flex-col">{children}</body> <Script // Inline scripts require an id. // See https://nextjs.org/docs/app/building-your-application/optimizing/scripts#inline-scripts id='nr-browser-agent' // "beforeInteractive" loads the script before the page becomes interactive. strategy='beforeInteractive' // The script body is the browser timing header generated above. Because // `hasToRemoveScriptWrapper` is true, the header is raw JavaScript with no // surrounding <script> tag, so we inject it with `dangerouslySetInnerHTML`. dangerouslySetInnerHTML={{ __html: browserTimingHeader }} /> </html> );}Consulte la aplicación de ejemplo de Next.js App Router para obtener un ejemplo más completo de esta configuración.