Membuat trace dan metrik dengan Node.js

Dokumen ini menjelaskan cara mengubah aplikasi JavaScript Node.js untuk mengumpulkan data pelacakan dan metrik menggunakan framework OpenTelemetry open source, dan cara menulis log JSON terstruktur ke standard out. Dokumen ini juga memberikan informasi tentang contoh aplikasi Node.js yang dapat Anda instal dan jalankan. Aplikasi ini menggunakan framework web Fastify dan dikonfigurasi untuk membuat metrik, trace, dan log.

Sebelum memulai

Aktifkan API Cloud Logging API, Cloud Monitoring API, and Cloud Trace API.

Mengaktifkan API

Melengkapi aplikasi untuk mengumpulkan trace, metrik, dan log

Untuk melengkapi aplikasi Anda guna mengumpulkan data pelacakan dan metrik, serta untuk menulis JSON terstruktur ke standard out, lakukan langkah-langkah berikut seperti yang dijelaskan di bagian selanjutnya dari dokumen ini:

  1. Mengonfigurasi OpenTelemetry
  2. Mengonfigurasi aplikasi untuk melakukan pramuat konfigurasi OpenTelemetry
  3. Mengonfigurasi logging terstruktur
  4. Menulis log terstruktur

Konfigurasi OpenTelemetry

Konfigurasi default untuk OpenTelemetry Node.js SDK mengekspor rekaman aktivitas menggunakan protokol OTLP. API ini juga mengonfigurasi OpenTelemetry untuk menggunakan format Trace Context W3C untuk menyebarkan konteks rekaman aktivitas. Konfigurasi ini memastikan bahwa span memiliki hubungan induk-turunan yang benar di dalam rekaman aktivitas.

Contoh kode berikut mengilustrasikan modul JavaScript untuk menyiapkan OpenTelemetry:


diag.setLogger(
  new DiagConsoleLogger(),
  opentelemetry.core.getEnv().OTEL_LOG_LEVEL
);

const sdk = new opentelemetry.NodeSDK({
  instrumentations: getNodeAutoInstrumentations({
    // Disable noisy instrumentations
    '@opentelemetry/instrumentation-fs': {enabled: false},
  }),
  resourceDetectors: getResourceDetectorsFromEnv(),
  metricReader: getMetricReader(),
});

try {
  sdk.start();
  diag.info('OpenTelemetry automatic instrumentation started successfully');
} catch (error) {
  diag.error(
    'Error initializing OpenTelemetry SDK. Your application is not instrumented and will not produce telemetry',
    error
  );
}

// Gracefully shut down the SDK to flush telemetry when the program exits
process.on('SIGTERM', () => {
  sdk
    .shutdown()
    .then(() => diag.debug('OpenTelemetry SDK terminated'))
    .catch(error => diag.error('Error terminating OpenTelemetry SDK', error));
});

Contoh kode sebelumnya mengonfigurasi OpenTelemetry untuk mengekspor metrik menggunakan protokol OTLP, dan menggunakan paket @opentelemetry/auto-instrumentations-node untuk mengonfigurasi semua instrumentasi Node.js yang tersedia.

Untuk memastikan semua telemetri yang tertunda dihapus dan koneksi ditutup dengan baik sebelum aplikasi dihentikan, pengendali SIGTERM akan memanggil shutdown.

Untuk informasi lebih lanjut dan opsi konfigurasi, lihat Instrumentasi otomatis OpenTelemetry Node.js.

Mengonfigurasi aplikasi Anda untuk melakukan pramuat konfigurasi OpenTelemetry

Untuk mengonfigurasi aplikasi agar dapat menulis log terstruktur serta mengumpulkan metrik dan rekaman aktivitas menggunakan OpenTelemetry, perbarui pemanggilan aplikasi Anda untuk melakukan pramuat modul instrumentasi dengan flag --require Node.js. Menggunakan flag --require akan memastikan bahwa OpenTelemetry diinisialisasi sebelum aplikasi dimulai. Untuk informasi selengkapnya, lihat Memulai OpenTelemetry Node.js.

Contoh kode berikut mengilustrasikan Dockerfile yang meneruskan flag --require:

CMD node --require ./build/src/instrumentation.js build/src/index.js 2>&1 | tee /var/log/app.log

Mengonfigurasi logging terstruktur

Untuk menyertakan informasi rekaman aktivitas sebagai bagian dari log berformat JSON yang ditulis ke output standar, konfigurasikan aplikasi Anda untuk menghasilkan log terstruktur dalam format JSON. Fastify menggunakan framework log Pino dan menyediakan logger di setiap pengendali permintaan. Contoh kode berikut mengilustrasikan objek LoggerOptions Pino yang mengonfigurasi aplikasi untuk menghasilkan log terstruktur JSON:


// Expected attributes that OpenTelemetry adds to correlate logs with spans
interface LogRecord {
  trace_id?: string;
  span_id?: string;
  trace_flags?: string;
  [key: string]: unknown;
}

// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity
const PinoLevelToSeverityLookup: Record<string, string | undefined> = {
  trace: 'DEBUG',
  debug: 'DEBUG',
  info: 'INFO',
  warn: 'WARNING',
  error: 'ERROR',
  fatal: 'CRITICAL',
};

export const loggerConfig = {
  messageKey: 'message',
  // Same as pino.stdTimeFunctions.isoTime but uses "timestamp" key instead of "time"
  timestamp(): string {
    return `,"timestamp":"${new Date(Date.now()).toISOString()}"`;
  },
  formatters: {
    log(object: LogRecord): Record<string, unknown> {
      // Add trace context attributes following Cloud Logging structured log format described
      // in https://cloud.google.com/logging/docs/structured-logging#special-payload-fields
      const {trace_id, span_id, trace_flags, ...rest} = object;

      return {
        'logging.googleapis.com/trace': trace_id,
        'logging.googleapis.com/spanId': span_id,
        'logging.googleapis.com/trace_sampled': trace_flags
          ? trace_flags === '01'
          : undefined,
        ...rest,
      };
    },
    // See
    // https://getpino.io/#/docs/help?id=mapping-pino-log-levels-to-google-cloud-logging-stackdriver-severity-levels
    level(label: string) {
      return {
        severity:
          PinoLevelToSeverityLookup[label] ?? PinoLevelToSeverityLookup['info'],
      };
    },
  },
} satisfies LoggerOptions;

Konfigurasi sebelumnya mengekstrak informasi tentang span aktif dari pesan log, lalu menambahkan informasi tersebut sebagai atribut ke log terstruktur JSON. Atribut ini kemudian dapat digunakan untuk mengkorelasikan log dengan trace:

  • logging.googleapis.com/trace: Nama resource trace yang terkait dengan entri log.
  • logging.googleapis.com/spanId: ID span dengan pelacakan yang dikaitkan dengan entri log.
  • logging.googleapis.com/trace_sampled: Nilai kolom ini harus true atau false.

Untuk mengetahui informasi selengkapnya tentang kolom ini, lihat struktur LogEntry.

Untuk menggunakan konfigurasi Pino dengan Fastify, teruskan objek konfigurasi logger saat membuat aplikasi Fastify:

// Create the Fastify app providing the Pino logger config
const fastify = Fastify({
  logger: loggerConfig,
});

Menulis log terstruktur

Untuk menulis log terstruktur yang tertaut ke suatu rekaman aktivitas, gunakan Fastify provided Pino logger. Misalnya, pernyataan berikut menunjukkan cara memanggil metode Logger.info():

request.log.info({subRequests}, 'handle /multi request');

OpenTelemetry secara otomatis mengisi entri log Pino dengan konteks span dari span aktif saat ini dalam OpenTelemetry Context. Konteks span ini kemudian disertakan dalam log JSON seperti yang dijelaskan dalam Mengonfigurasi logging terstruktur.

Menjalankan aplikasi contoh yang dikonfigurasi untuk mengumpulkan telemetri

Aplikasi contoh menggunakan format yang tidak terikat dengan vendor, termasuk JSON untuk log dan OTLP untuk metrik dan trace, serta framework Fastify. Untuk merutekan telemetri ke Google Cloud, contoh ini menggunakan Collector OpenTelemetry yang dikonfigurasi dengan pengekspor Google. Aplikasi ini memiliki dua endpoint:

  • Endpoint /multi ditangani oleh fungsi handleMulti. Generator beban di aplikasi mengeluarkan permintaan ke endpoint /multi. Saat menerima permintaan, endpoint ini akan mengirimkan antara tiga hingga tujuh permintaan ke endpoint /single di server lokal.

    /**
     * handleMulti handles an http request by making 3-7 http requests to the /single endpoint.
     *
     * OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the handler body.
     */
    fastify.get('/multi', async request => {
      const subRequests = randInt(3, 8);
      request.log.info({subRequests}, 'handle /multi request');
    
      for (let i = 0; i < subRequests; i++) {
        await axios.get(`http://localhost:${port}/single`);
      }
      return 'ok';
    });
  • Endpoint /single ditangani oleh fungsi handleSingle. Saat menerima permintaan, endpoint ini akan tidur dalam waktu singkat, lalu merespons dengan string.

    /**
     * handleSingle handles an http request by sleeping for 100-200 ms. It writes the number of
     * milliseconds slept as its response.
     */
    fastify.get('/single', async request => {
      // Sleep between 100-200 milliseconds
      const sleepMillis = randInt(100, 200);
      request.log.info({sleepMillis}, 'Going to sleep');
      await sleep(sleepMillis);
      return `slept ${sleepMillis}\n`;
    });

Mendownload dan men-deploy aplikasi

Untuk menjalankan contoh, lakukan hal berikut:

  1. Di konsol Google Cloud, aktifkan Cloud Shell.

    Aktifkan Cloud Shell

    Di bagian bawah Google Cloud Console, Cloud Shell sesi akan terbuka dan menampilkan perintah command line. Cloud Shell adalah lingkungan shell dengan Google Cloud CLI yang sudah terinstal, dan dengan nilai yang sudah ditetapkan untuk project Anda saat ini. Diperlukan waktu beberapa detik untuk melakukan inisialisasi sesi.

  2. Meng-cloning repository

    git clone https://github.com/GoogleCloudPlatform/opentelemetry-operations-js
    
  3. Buka direktori contoh:

    cd opentelemetry-operations-js/samples/instrumentation-quickstart
    
  4. Buat dan jalankan contoh:

    docker compose up --abort-on-container-exit
    

    Jika Anda tidak menjalankan Cloud Shell, jalankan aplikasi dengan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS yang mengarah ke file kredensial. Kredensial Default Aplikasi menyediakan file kredensial di $HOME/.config/gcloud/application_default_credentials.json.

    # Set environment variables
    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json"
    export USERID="$(id -u)"
    
    # Run
    docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
    

Melihat metrik Anda

Instrumentasi OpenTelemetry di aplikasi contoh menghasilkan metrik Prometheus yang dapat Anda tampilkan menggunakan Metrics Explorer:

  • Prometheus/http_server_duration_milliseconds/histogram mencatat durasi permintaan server dan menyimpan hasilnya dalam histogram.

  • Prometheus/http_client_duration_milliseconds/histogram mencatat durasi permintaan klien dan menyimpan hasilnya dalam histogram.

Untuk melihat metrik yang dihasilkan oleh aplikasi contoh, lakukan hal berikut:
  1. Di panel navigasi Konsol Google Cloud, pilih Monitoring, lalu pilih  Metrics Explorer:

    Buka Metrics Explorer

  2. Pada elemen Metrik, luaskan menu Pilih metrik, masukkan http_server di panel filter, lalu gunakan submenu untuk memilih jenis dan metrik resource tertentu:
    1. Di menu Active resources, pilih Prometheus Target.
    2. Di menu Active metric criteria, pilih Http.
    3. Di menu Metrik aktif, pilih metrik.
    4. Klik Terapkan.
  3. Konfigurasi cara data ditampilkan.

    Jika pengukuran untuk metrik bersifat kumulatif, Metrics Explorer otomatis menormalisasi data yang diukur berdasarkan periode penyelarasan, sehingga diagram akan menampilkan rasio. Untuk mengetahui informasi selengkapnya, lihat Jenis, jenis, dan konversi.

    Saat nilai bilangan bulat atau ganda diukur, seperti dengan dua metrik counter, Metrics Explorer otomatis menjumlahkan semua deret waktu. Untuk melihat data rute HTTP /multi dan /single, tetapkan menu pertama entri Aggregation ke None.

    Untuk informasi selengkapnya tentang cara mengonfigurasi diagram, lihat Memilih metrik saat menggunakan Metrics Explorer.

Melihat trace Anda

Untuk melihat data trace, lakukan langkah berikut:

  1. Di panel navigasi konsol Google Cloud, pilih Trace, lalu pilih Trace explorer:

    Buka Trace explorer

  2. Di diagram sebar, pilih rekaman aktivitas dengan URI /multi.
  3. Pada diagram Gantt di panel Trace details, pilih span yang berlabel /multi.

    Sebuah panel yang menampilkan informasi tentang permintaan HTTP akan terbuka. Detail ini mencakup metode, kode status, jumlah byte, dan agen pengguna pemanggil.

  4. Untuk melihat log yang terkait dengan rekaman aktivitas ini, pilih tab Logs & Events.

    Tab ini menunjukkan log individual. Untuk melihat detail entri log, luaskan entri log. Anda juga dapat mengklik View Logs dan melihat log menggunakan Logs Explorer.

Untuk mengetahui informasi selengkapnya tentang cara menggunakan penjelajah Cloud Trace, lihat Menemukan dan menjelajahi trace.

Melihat log

Dari Logs Explorer, Anda dapat memeriksa log, dan Anda juga dapat melihat rekaman aktivitas terkait, jika ada.

  1. Di panel navigasi konsol Google Cloud, pilih Logging, lalu pilih Logs Explorer:

    Buka Logs Explorer

  2. Temukan log dengan deskripsi handle /multi request.

    Untuk melihat detail log, luaskan entri log.

  3. Klik Traces pada entri log dengan pesan "handle /multi request", lalu pilih View trace details.

    Panel Trace details akan terbuka dan menampilkan trace yang dipilih.

Untuk mengetahui informasi selengkapnya tentang penggunaan Logs Explorer, baca Melihat log menggunakan Logs Explorer.

Langkah selanjutnya