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 Hybrid Agent del agente Node.js, en lugar de la instrumentación Next.js incorporada del agente. Esta página explica cómo habilitar el Hybrid Agent, señala aplicaciones de ejemplo y cubre preguntas comunes sobre la inyección del agente del browser y cómo desplegar en proveedores de cloud.
Importante
El soporte nativo de Next.js OpenTelemetry requiere la versión del agente Node.js 14.1.0 o posterior. El Hybrid Agent solo instrumenta el tiempo de ejecución de Node.js; el tiempo de ejecución perimetral de Next.js no es compatible, por lo que el ejemplo de register() a continuación finaliza anticipadamente a menos que NEXT_RUNTIME sea nodejs.
Además, actualmente solo admitimos el enfoque de agente híbrido para las versiones 16 y superiores de Next.js.
El agente Node.js ha tenido instrumentación Next.js desde 2022 a través de @newrelic/next, y esa instrumentación se incluyó en el agente en 12.0.0. Sin embargo, era limitada y no funcionaba al desplegar en proveedores de cloud como Vercel, AWS Amplify, Netlify o Azure Static Web Apps. Con la introducción del Hybrid Agent, el agente Node.js puede interceptar los spans de OpenTelemetry y sintetizar la telemetría que impulsa la experiencia de New Relic. La instrumentación nativa de Next.js OpenTelemetry se agregó en 14.1.0.
Habilitar 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.