ไทย

ใช้ Next.js instrumentation เพื่อวิเคราะห์ประสิทธิภาพแอปพลิเคชัน ระบุคอขวด และปรับปรุงประสบการณ์ผู้ใช้ เรียนรู้วิธีใช้ฮุกติดตามแอปพลิเคชันอย่างมีประสิทธิภาพ

การวัดผลใน Next.js (Instrumentation): ฮุกสำหรับติดตามแอปพลิเคชันเพื่อข้อมูลเชิงลึกใน Production

การวัดผล (instrumentation) ใน Next.js เป็นกลไกอันทรงพลังที่ช่วยให้เราสามารถสังเกตและวัดประสิทธิภาพของแอปพลิเคชันในสภาพแวดล้อมการใช้งานจริง (production) ได้ โดยการใช้ฮุกสำหรับติดตามแอปพลิเคชัน (application monitoring hooks) คุณจะได้รับข้อมูลเชิงลึกเกี่ยวกับการจัดการคำขอ (request handling), การเรนเดอร์ฝั่งเซิร์ฟเวอร์ (server-side rendering), การดึงข้อมูล (data fetching) และส่วนสำคัญอื่นๆ ของแอปพลิเคชัน ซึ่งช่วยให้คุณสามารถระบุคอขวด วินิจฉัยปัญหาด้านประสิทธิภาพ และปรับปรุงแอปพลิเคชันเพื่อประสบการณ์ผู้ใช้ที่ดีขึ้น สิ่งนี้มีความสำคัญอย่างยิ่งเมื่อปรับใช้แอปพลิเคชัน Next.js ทั่วโลก ซึ่งอาจมีความท้าทายเฉพาะตัวจากความหน่วงของเครือข่ายและผู้ใช้ที่กระจายตัวอยู่ตามภูมิภาคต่างๆ

ทำความเข้าใจเกี่ยวกับการวัดผลใน Next.js

ฟีเจอร์การวัดผลใน Next.js ช่วยให้คุณสามารถลงทะเบียนฮุก (hooks) ที่จะทำงานในขั้นตอนต่างๆ ของวงจรชีวิตแอปพลิเคชันได้ ฮุกเหล่านี้สามารถใช้เพื่อรวบรวมเมตริก (metrics), เทรซ (traces) และล็อก (logs) ซึ่งสามารถส่งต่อไปยังระบบ Application Performance Monitoring (APM) หรือเครื่องมือสังเกตการณ์ (observability tools) อื่นๆ ได้ ซึ่งจะให้มุมมองที่ครอบคลุมเกี่ยวกับประสิทธิภาพของแอปพลิเคชันของคุณแบบเรียลไทม์

แตกต่างจากการติดตามฝั่งไคลเอนต์แบบดั้งเดิมซึ่งจับภาพเฉพาะประสบการณ์บนเบราว์เซอร์ การวัดผลของ Next.js ให้ความสามารถในการสังเกตการณ์ทั้งฝั่งไคลเอนต์และฝั่งเซิร์ฟเวอร์ ทำให้ได้มุมมองแบบ full-stack เกี่ยวกับประสิทธิภาพของแอปพลิเคชันของคุณ ซึ่งเป็นสิ่งสำคัญอย่างยิ่งในการทำความเข้าใจผลกระทบของการเรนเดอร์ฝั่งเซิร์ฟเวอร์, API routes และการดึงข้อมูลต่อประสบการณ์ผู้ใช้โดยรวม

ประโยชน์หลักของการวัดผล

การตั้งค่าการวัดผลใน Next.js

ในการเปิดใช้งานการวัดผลในแอปพลิเคชัน Next.js ของคุณ คุณต้องสร้างไฟล์ instrumentation.js (หรือ instrumentation.ts) ในไดเรกทอรีราก (root directory) ของโปรเจกต์ของคุณ ไฟล์นี้จะบรรจุฮุกที่คุณต้องการลงทะเบียน

นี่คือตัวอย่างพื้นฐานของไฟล์ instrumentation.ts:

// instrumentation.ts

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    const { trace } = await import('./utils/tracing');

    trace('registering-tracing');
  }
}

ในตัวอย่างนี้ เรากำลังนำเข้าฟังก์ชัน trace จากไฟล์ ./utils/tracing และเรียกใช้งานภายในฟังก์ชัน register ฟังก์ชัน register จะถูกเรียกโดยอัตโนมัติโดย Next.js เมื่อแอปพลิเคชันเริ่มต้นทำงาน

การทำงานแบบมีเงื่อนไขตาม Runtime

ตัวแปร process.env.NEXT_RUNTIME มีความสำคัญอย่างยิ่งในการกำหนดบริบทการทำงาน (execution context) ซึ่งช่วยให้คุณสามารถสั่งให้โค้ดทำงานแบบมีเงื่อนไขตามสภาพแวดล้อมที่แอปพลิเคชันกำลังทำงานอยู่ ไม่ว่าจะเป็นในสภาพแวดล้อม Node.js (สำหรับการเรนเดอร์ฝั่งเซิร์ฟเวอร์, API routes ฯลฯ) หรือในสภาพแวดล้อม Edge Runtime (สำหรับ edge functions) สิ่งนี้สำคัญเพราะไลบรารีหรือเครื่องมือติดตามบางตัวอาจเข้ากันได้กับ runtime เพียงประเภทเดียวเท่านั้น

ตัวอย่างเช่น คุณอาจต้องการใช้ APM agent เฉพาะสำหรับสภาพแวดล้อม Node.js และใช้เครื่องมืออื่นสำหรับสภาพแวดล้อม Edge Runtime การใช้ process.env.NEXT_RUNTIME ช่วยให้คุณสามารถโหลดโมดูลที่เหมาะสมได้เฉพาะเมื่อจำเป็นเท่านั้น

การนำ Application Monitoring Hooks ไปใช้งาน

ตอนนี้ เรามาดูตัวอย่างวิธีการนำฮุกติดตามแอปพลิเคชันไปใช้ใน Next.js กัน

1. การวัดระยะเวลาในการจัดการคำขอ (Request Handling Time)

หนึ่งในกรณีการใช้งานทั่วไปสำหรับการวัดผลคือการวัดเวลาที่ใช้ในการจัดการคำขอที่เข้ามา ซึ่งจะช่วยให้คุณสามารถระบุ endpoints ที่ทำงานช้าและปรับปรุงประสิทธิภาพของมันได้

นี่คือตัวอย่างวิธีการวัดเวลาในการจัดการคำขอโดยใช้ performance API:

// utils/tracing.ts

import { performance } from 'perf_hooks';

export function trace(eventName: string) {
  const start = performance.now();

  return () => {
    const end = performance.now();
    const duration = end - start;

    console.log(`[${eventName}] took ${duration}ms`);
    // In a real application, you would send this data to an APM system.
  };
}

ใน instrumentation.ts:

// instrumentation.ts

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    const { trace } = await import('./utils/tracing');

    const endTrace = trace('request-handling');

    // Simulate request handling
    await new Promise((resolve) => setTimeout(resolve, 100));

    endTrace();
  }
}

ตัวอย่างนี้จะวัดเวลาที่ใช้ในการจัดการคำขอและบันทึกระยะเวลาลงในคอนโซล ในแอปพลิเคชันจริง คุณจะส่งข้อมูลนี้ไปยังระบบ APM เพื่อการวิเคราะห์เพิ่มเติม

2. การติดตามระยะเวลาการเรนเดอร์ฝั่งเซิร์ฟเวอร์ (Server-Side Rendering Time)

การเรนเดอร์ฝั่งเซิร์ฟเวอร์ (SSR) เป็นฟีเจอร์หลักของ Next.js แต่อาจเป็นคอขวดด้านประสิทธิภาพได้เช่นกัน การติดตามเวลาที่ใช้ในการเรนเดอร์หน้าบนเซิร์ฟเวอร์จึงเป็นสิ่งสำคัญเพื่อให้แน่ใจว่าผู้ใช้จะได้รับประสบการณ์ที่รวดเร็ว

คุณสามารถใช้การวัดผลเพื่อวัดเวลาที่ใช้ในการทำงานของฟังก์ชัน getServerSideProps หรือ getStaticProps ได้ ฟังก์ชันเหล่านี้มีหน้าที่รับผิดชอบในการดึงข้อมูลและเตรียมข้อมูลสำหรับการเรนเดอร์บนเซิร์ฟเวอร์

// pages/index.tsx

import { GetServerSideProps } from 'next';
import { trace } from '../utils/tracing';

interface Props {
  data: string;
}

export const getServerSideProps: GetServerSideProps = async () => {
  const endTrace = trace('getServerSideProps');
  const data = await fetchData();
  endTrace();

  return {
    props: { data },
  };
};

async function fetchData() {
  // Simulate fetching data from an external API
  await new Promise((resolve) => setTimeout(resolve, 50));
  return 'Data from API';
}

export default function Home({ data }: Props) {
  return 

{data}

; }

ในตัวอย่างนี้ เราใช้ฟังก์ชัน trace เพื่อวัดเวลาที่ใช้ในการทำงานของฟังก์ชัน getServerSideProps ซึ่งช่วยให้เราระบุปัญหาด้านประสิทธิภาพในกระบวนการดึงข้อมูลได้

3. การติดตามประสิทธิภาพของ API Route

Next.js API routes ช่วยให้คุณสร้างฟังก์ชัน serverless ที่จัดการคำขอ API ได้ การติดตามประสิทธิภาพของ API routes เหล่านี้จึงจำเป็นอย่างยิ่งเพื่อให้แน่ใจว่า backend ของคุณตอบสนองได้ดี

คุณสามารถใช้การวัดผลเพื่อวัดเวลาที่ใช้ในการจัดการคำขอ API ใน API routes ของคุณได้

// pages/api/hello.ts

import type { NextApiRequest, NextApiResponse } from 'next'
import { trace } from '../../utils/tracing';

type Data = {
  name: string
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const endTrace = trace('api-hello');
  // Simulate some work
  await new Promise((resolve) => setTimeout(resolve, 25));
  endTrace();
  res.status(200).json({ name: 'John Doe' })
}

ตัวอย่างนี้จะวัดเวลาที่ใช้ในการจัดการคำขอ API และส่งคืนการตอบกลับแบบ JSON ซึ่งช่วยให้คุณเข้าใจประสิทธิภาพของ backend และระบุ API endpoints ที่ทำงานช้าได้

4. การติดตามประสิทธิภาพของ Edge Runtime

Next.js Edge Runtime ช่วยให้คุณสามารถปรับใช้แอปพลิเคชันของคุณไปยัง edge ซึ่งอยู่ใกล้กับผู้ใช้ของคุณมากขึ้น ซึ่งสามารถปรับปรุงประสิทธิภาพได้อย่างมาก โดยเฉพาะสำหรับแอปพลิเคชันที่ให้บริการทั่วโลก อย่างไรก็ตาม สิ่งสำคัญคือต้องติดตามประสิทธิภาพของแอปพลิเคชันของคุณใน Edge Runtime เพื่อให้แน่ใจว่ามันทำงานได้อย่างมีประสิทธิภาพ

การวัดผลสามารถใช้เพื่อติดตามประสิทธิภาพของแอปพลิเคชันของคุณใน Edge Runtime ได้ ซึ่งช่วยให้คุณสามารถระบุปัญหาด้านประสิทธิภาพที่เฉพาะเจาะจงกับสภาพแวดล้อม Edge Runtime ได้

หมายเหตุสำคัญ: ไม่ใช่เครื่องมือติดตามทุกตัวที่รองรับ Edge Runtime คุณอาจต้องใช้เครื่องมือหรือไลบรารีพิเศษที่ออกแบบมาสำหรับสภาพแวดล้อม Edge Runtime

ตัวอย่างเช่น Vercel มีเครื่องมือวิเคราะห์ในตัวที่สามารถใช้เพื่อติดตามประสิทธิภาพของแอปพลิเคชันของคุณใน Edge Runtime ได้ นอกจากนี้คุณยังสามารถใช้เครื่องมือติดตามจากบุคคลที่สามที่รองรับ Edge Runtime เช่น Datadog หรือ New Relic

การผสานรวมกับระบบ APM

ข้อมูลที่รวบรวมโดยฮุกการวัดผลของคุณจะมีค่ามากที่สุดเมื่อส่งไปยังระบบ APM (Application Performance Monitoring) ระบบ APM มีเครื่องมือสำหรับการแสดงภาพ วิเคราะห์ และแจ้งเตือนข้อมูลประสิทธิภาพ ระบบ APM ที่เป็นที่นิยม ได้แก่:

ขั้นตอนเฉพาะสำหรับการผสานรวมกับระบบ APM จะแตกต่างกันไปขึ้นอยู่กับระบบที่คุณเลือก อย่างไรก็ตาม กระบวนการทั่วไปประกอบด้วยขั้นตอนต่อไปนี้:

  1. ติดตั้ง APM agent หรือ SDK ในแอปพลิเคชัน Next.js ของคุณ
  2. กำหนดค่า APM agent ด้วย API key หรือข้อมูลประจำตัวของระบบ APM ของคุณ
  3. ใช้ API ของ APM agent เพื่อส่งเมตริก, เทรซ และล็อก จากฮุกการวัดผลของคุณ

ตัวอย่างการใช้ OpenTelemetry กับ Datadog:

OpenTelemetry เป็นเฟรมเวิร์กการสังเกตการณ์แบบโอเพนซอร์สที่ให้วิธีการมาตรฐานในการรวบรวมและส่งออกข้อมูล telemetry สามารถใช้เพื่อผสานรวมกับระบบ APM ที่หลากหลาย รวมถึง Datadog

// utils/tracing.ts

import { trace, context } from '@opentelemetry/api';

const tracer = trace.getTracer('my-app-tracer');

export function traceFunction any>(
  operationName: string,
  fn: T
): T {
  return function tracedFunction(...args: Parameters): ReturnType {
    const span = tracer.startSpan(operationName);
    const ctx = trace.setSpan(context.active(), span);

    try {
      return context.with(ctx, () => fn(...args));
    } finally {
      span.end();
    }
  } as T;
}

การใช้งานภายใน `getServerSideProps`:

// pages/index.tsx

import { GetServerSideProps } from 'next';
import { traceFunction } from '../utils/tracing';

interface Props {
  data: string;
}

async function fetchData() {
  // Simulate fetching data from an external API
  await new Promise((resolve) => setTimeout(resolve, 50));
  return 'Data from API';
}

export const getServerSideProps: GetServerSideProps = async () => {
  const tracedFetchData = traceFunction('fetchData', fetchData);
  const data = await tracedFetchData();

  return {
    props: { data },
  };
};

export default function Home({ data }: Props) {
  return 

{data}

; }

ตัวอย่าง OpenTelemetry แบบง่ายนี้แสดงให้เห็นถึงวิธีการครอบฟังก์ชันด้วย tracing span การตั้งค่าและการกำหนดค่าจริงของ OpenTelemetry SDK และ Datadog agent นั้นซับซ้อนกว่าและต้องมีขั้นตอนเพิ่มเติม รวมถึงการตั้งค่าตัวแปรสภาพแวดล้อม การกำหนดค่า exporter และการเริ่มต้น SDK ในไฟล์ instrumentation.ts ของคุณ โปรดอ้างอิงเอกสารประกอบของ OpenTelemetry และ Datadog สำหรับคำแนะนำฉบับสมบูรณ์

แนวทางปฏิบัติที่ดีที่สุดสำหรับการวัดผลใน Next.js

ข้อผิดพลาดที่พบบ่อยและแนวทางแก้ไข

สรุป

การวัดผลใน Next.js เป็นกลไกอันทรงพลังที่ช่วยให้เราสามารถสังเกตและวัดประสิทธิภาพของแอปพลิเคชันในสภาพแวดล้อมการใช้งานจริงได้ โดยการนำฮุกติดตามแอปพลิเคชันไปใช้งาน คุณจะได้รับข้อมูลเชิงลึกเกี่ยวกับการจัดการคำขอ การเรนเดอร์ฝั่งเซิร์ฟเวอร์ การดึงข้อมูล และส่วนสำคัญอื่นๆ ของแอปพลิเคชัน ซึ่งช่วยให้คุณสามารถระบุคอขวด วินิจฉัยปัญหาด้านประสิทธิภาพ และปรับปรุงแอปพลิเคชันเพื่อประสบการณ์ผู้ใช้ที่ดีขึ้น

โดยการปฏิบัติตามแนวทางที่ดีที่สุดที่ระบุไว้ในคู่มือนี้ คุณสามารถใช้ประโยชน์จากการวัดผลของ Next.js เพื่อปรับปรุงประสิทธิภาพและความน่าเชื่อถือของแอปพลิเคชันของคุณได้อย่างมีประสิทธิภาพ ไม่ว่าผู้ใช้ของคุณจะอยู่ที่ใดก็ตาม อย่าลืมเลือกระบบ APM ที่เหมาะสมกับความต้องการของคุณ และติดตามประสิทธิภาพของแอปพลิคชันของคุณอย่างต่อเนื่องเพื่อระบุและแก้ไขปัญหาในเชิงรุก

การวัดผลใน Next.js (Instrumentation): ฮุกสำหรับติดตามแอปพลิเคชันเพื่อข้อมูลเชิงลึกใน Production | MLOG