Logging terstruktur

Dokumen ini membahas konsep logging terstruktur dan metode untuk menambahkan struktur ke kolom payload entri log. Saat payload log diformat sebagai objek JSON dan objek tersebut disimpan di kolom jsonPayload, entri log disebut log terstruktur. Untuk log ini, Anda dapat membuat kueri yang menelusuri jalur JSON tertentu dan mengindeks kolom tertentu dalam payload log. Sebaliknya, saat payload log diformat sebagai string dan disimpan di kolom textPayload, entri log bersifat tidak terstruktur. Anda dapat menelusuri kolom teks, tetapi tidak dapat mengindeks kontennya.

Untuk membuat entri log terstruktur, lakukan salah satu tindakan berikut:

  • Panggil metode API entries.write dan berikan LogEntry yang diformat sepenuhnya.
  • Gunakan perintah gcloud logging write.
  • Gunakan library klien Cloud Logging yang menulis log terstruktur.
  • Gunakan layanan BindPlane.
  • Gunakan agen untuk menulis log:

    • Beberapa layanan Google Cloud berisi agen logging terintegrasi yang mengirim data yang ditulis ke stdout atau stderr sebagai log ke Cloud Logging. Anda dapat menggunakan pendekatan ini untuk layanan Google Cloud seperti Google Kubernetes Engine, lingkungan fleksibel App Engine, dan fungsi Cloud Run.

    • Untuk virtual machine (VM) Compute Engine, Anda dapat menginstal dan mengonfigurasi Ops Agent atau agen Logging lama, lalu menggunakan agen yang diinstal untuk mengirim log ke Cloud Logging.

Untuk informasi selengkapnya tentang pendekatan ini, lihat bagian berikut.

Menulis log menggunakan library klien atau API

Anda dapat menulis data log menggunakan library klien Cloud Logging, yang memanggil Cloud Logging API, atau dengan memanggil Cloud Logging API secara langsung. Library klien dapat menyederhanakan pengisian kolom JSON khusus dengan mengambil sejumlah informasi secara otomatis dan menyediakan antarmuka untuk mengisi kolom dengan tepat. Namun, untuk kontrol penuh atas struktur payload, panggil Cloud Logging API secara langsung dan teruskan struktur LogEntry lengkap ke Cloud Logging API.

Untuk informasi selengkapnya, lihat referensi entries.write.

Untuk contoh kode, lihat Menulis log terstruktur.

Menulis log menggunakan gcloud CLI

Anda dapat menulis data log menggunakan gcloud CLI. Antarmuka ini mendukung log tidak terstruktur dan log terstruktur. Jika Anda ingin menulis log terstruktur, berikan objek JSON yang diserialisasi ke perintah.

Untuk panduan memulai, lihat Menulis dan membuat kueri entri log dengan Google Cloud CLI.

Untuk contoh kode, lihat referensi gcloud logging write.

Menulis log menggunakan BindPlane

Anda dapat menggunakan layanan BindPlane untuk mengirim log ke Logging. Untuk log ini, payload dalam format JSON dan terstruktur sesuai dengan sistem sumber. Untuk informasi tentang cara menemukan dan melihat log yang diserap menggunakan BindPlane, lihat Panduan Memulai BindPlane.

Menulis log menggunakan agen

Untuk mendapatkan log dari instance Compute Engine, Anda dapat menggunakan Ops Agent atau agen Cloud Logging lama. Kedua agen tersebut dapat mengumpulkan metrik dari aplikasi pihak ketiga, dan keduanya memberikan dukungan untuk logging terstruktur:

  • Ops Agent adalah agen yang direkomendasikan untuk mengumpulkan telemetri dari instance Compute Engine Anda. Agen ini menggabungkan logging dan metrik ke dalam satu agen, menyediakan konfigurasi berbasis YAML, dan menampilkan logging dengan throughput tinggi.

    Untuk mengetahui informasi tentang cara mengonfigurasi Ops Agent untuk mendukung logging terstruktur atau menyesuaikan bentuk log terstruktur, lihat Mengonfigurasi Ops Agent.

  • Agen Cloud Logging lama mengumpulkan log. Agen ini tidak mengumpulkan bentuk telemetri lainnya.

Bagian selanjutnya dalam bagian ini khusus untuk agen Logging lama.

Agen logging: kolom JSON khusus

Beberapa kolom dalam objek JSON dikenali sebagai khusus oleh agen Logging lama dan diekstrak ke dalam struktur LogEntry. Kolom JSON khusus ini dapat digunakan untuk menetapkan kolom berikut di LogEntry:

  • severity
  • spanId
  • labels yang ditentukan oleh pengguna
  • httpRequest

Karena JSON lebih presisi dan serbaguna daripada baris teks, Anda dapat menggunakan objek JSON untuk menulis pesan multibaris dan menambahkan metadata.

Untuk membuat entri log terstruktur untuk aplikasi Anda menggunakan format sederhana, lihat tabel berikut, yang mencantumkan kolom dan nilainya dalam JSON:

Kolom log JSON Kolom LogEntry Fungsi agen Cloud Logging Nilai contoh
severity severity Agen logging mencoba mencocokkan berbagai string tingkat keparahan umum, yang mencakup daftar string LogSeverity yang dikenali oleh Logging API. "severity":"ERROR"
message textPayload (atau bagian dari jsonPayload) Pesan yang muncul di baris entri log di Logs Explorer. "message":"There was an error in the application."

Catatan: message disimpan sebagai textPayload jika merupakan satu-satunya kolom yang tersisa setelah agen logging memindahkan kolom tujuan khusus lainnya dan detect_json tidak diaktifkan; jika tidak, message tetap berada di jsonPayload. detect_json tidak berlaku untuk lingkungan logging terkelola seperti Google Kubernetes Engine. Jika entri log Anda berisi pelacakan tumpukan pengecualian, pelacakan tumpukan pengecualian harus ditetapkan di kolom log JSON message ini, sehingga pelacakan tumpukan pengecualian dapat diuraikan dan disimpan ke Pelaporan Error.
log (khusus Google Kubernetes Engine lama) textPayload Hanya berlaku untuk Google Kubernetes Engine lama: jika, setelah memindahkan kolom tujuan khusus, hanya kolom log yang tersisa, maka kolom tersebut akan disimpan sebagai textPayload.
httpRequest httpRequest Kumpulan data terstruktur dalam format kolom LogEntry HttpRequest. "httpRequest":{"requestMethod":"GET"}
kolom terkait waktu timestamp Untuk informasi selengkapnya, lihat Kolom terkait waktu. "time":"2020-10-12T07:20:50.52Z"
logging.googleapis.com/insertId insertId Untuk informasi selengkapnya, lihat insertId di halaman LogEntry. "logging.googleapis.com/insertId":"42"
logging.googleapis.com/labels labels Nilai kolom ini harus berupa data terstruktur. Untuk informasi selengkapnya, lihat labels di halaman LogEntry. "logging.googleapis.com/labels": {"user_label_1":"value_1","user_label_2":"value_2"}
logging.googleapis.com/operation operation Nilai kolom ini juga digunakan oleh Logs Explorer untuk mengelompokkan entri log terkait. Untuk informasi selengkapnya, lihat operation di halaman LogEntry. "logging.googleapis.com/operation": {"id":"get_data","producer":"github.com/MyProject/MyApplication", "first":"true"}
logging.googleapis.com/sourceLocation sourceLocation Informasi lokasi kode sumber yang terkait dengan entri log, jika ada. Untuk informasi selengkapnya, lihat LogEntrySourceLocation di halaman LogEntry. "logging.googleapis.com/sourceLocation": {"file":"get_data.py","line":"142","function":"getData"}
logging.googleapis.com/spanId spanId ID span dalam trace yang terkait dengan entri log. Untuk informasi selengkapnya, lihat spanId di halaman LogEntry. "logging.googleapis.com/spanId":"000000000000004a"
logging.googleapis.com/trace trace Nama resource trace yang terkait dengan entri log jika ada. Untuk informasi selengkapnya, lihat trace di halaman LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Catatan: Jika tidak menulis ke stdout atau stderr, nilai kolom ini harus diformat sebagai projects/[PROJECT-ID]/traces/[TRACE-ID], sehingga dapat digunakan oleh Logs Explorer dan Trace Viewer untuk mengelompokkan entri log dan menampilkannya sesuai dengan rekaman aktivitas. Jika autoformat_stackdriver_trace bernilai benar dan [V] cocok dengan format ResourceTrace traceId, kolom trace LogEntry akan memiliki nilai projects/[PROJECT-ID]/traces/[V].
logging.googleapis.com/trace_sampled traceSampled Nilai kolom ini harus berupa true atau false. Untuk informasi selengkapnya, lihat traceSampled di halaman LogEntry. "logging.googleapis.com/trace_sampled": false

Untuk membuat entri log dalam format yang disederhanakan, buat representasi JSON entri menggunakan kolom. Semua kolom bersifat opsional.

Berikut adalah contoh entri log JSON yang disederhanakan:

{
  "severity":"ERROR",
  "message":"There was an error in the application.",
  "httpRequest":{
    "requestMethod":"GET"
  },
  "times":"2020-10-12T07:20:50.52Z",
  "logging.googleapis.com/insertId":"42",
  "logging.googleapis.com/labels":{
    "user_label_1":"value_1",
    "user_label_2":"value_2"
  },
  "logging.googleapis.com/operation":{
    "id":"get_data",
    "producer":"github.com/MyProject/MyApplication",
    "first":"true"
  },
  "logging.googleapis.com/sourceLocation":{
    "file":"get_data.py",
    "line":"142",
    "function":"getData"
  },
  "logging.googleapis.com/spanId":"000000000000004a",
  "logging.googleapis.com/trace":"projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824",
  "logging.googleapis.com/trace_sampled":false
}

Berikut adalah contoh entri log yang dihasilkan:

{
  "insertId": "42",
  "jsonPayload": {
    "message": "There was an error in the application",
    "times": "2020-10-12T07:20:50.52Z"
  },
  "httpRequest": {
    "requestMethod": "GET"
  },
  "resource": {
    "type": "k8s_container",
    "labels": {
      "container_name": "hello-app",
      "pod_name": "helloworld-gke-6cfd6f4599-9wff8",
      "project_id": "stackdriver-sandbox-92334288",
      "namespace_name": "default",
      "location": "us-west4",
      "cluster_name": "helloworld-gke"
    }
  },
  "timestamp": "2020-11-07T15:57:35.945508391Z",
  "severity": "ERROR",
  "labels": {
    "user_label_2": "value_2",
    "user_label_1": "value_1"
  },
  "logName": "projects/stackdriver-sandbox-92334288/logs/stdout",
  "operation": {
    "id": "get_data",
    "producer": "github.com/MyProject/MyApplication",
    "first": true
  },
  "trace": "projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824",
  "sourceLocation": {
    "file": "get_data.py",
    "line": "142",
    "function": "getData"
  },
  "receiveTimestamp": "2020-11-07T15:57:42.411414059Z",
  "spanId": "000000000000004a"
}

Agen logging: konfigurasi

Agen Logging lama, google-fluentd, adalah paket khusus Cloud Logging dari kolektor data log Fluentd. Agen Logging dilengkapi dengan konfigurasi Fluentd default dan menggunakan plugin input Fluentd untuk mengambil log peristiwa dari sumber eksternal seperti file di disk, atau untuk mengurai data log yang masuk.

Fluentd memiliki daftar parser yang didukung yang mengekstrak log dan mengonversinya menjadi payload terstruktur (JSON).

Dengan mengonfigurasi sumber log dengan format [PARSER_NAME], Anda dapat mem-build pada parser bawaan yang disediakan oleh Fluentd. Untuk informasi tentang cara mengonfigurasi agen Logging lama, lihat Mengonfigurasi agen Logging.

Contoh kode berikut menunjukkan konfigurasi Fluentd, kumpulan data log input, dan payload terstruktur output, yang merupakan bagian dari entri log Cloud Logging:

  • Konfigurasi Fluentd:

      <source>
        @type tail
    
        format syslog # This uses a predefined log format regex named
                      # `syslog`. See details at https://docs.fluentd.org/parser/syslog.
    
        path /var/log/syslog
        pos_file /var/lib/google-fluentd/pos/syslog.pos
        read_from_head true
        tag syslog
      </source>
    
  • Data log (input):

      <6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test
    
  • Payload terstruktur (output):

      jsonPayload: {
          "pri": "6",
          "host": "192.168.0.1",
          "ident": "fluentd",
          "pid": "11111",
          "message": "[error] Syslog test"
      }
    

Untuk informasi selengkapnya tentang cara kerja parser syslog, lihat dokumentasi Fluentd yang mendetail.

Agen logging: parser standar diaktifkan secara default

Tabel berikut menyertakan parser standar yang disertakan dalam agen jika Anda mengaktifkan logging terstruktur:

Nama Parser File konfigurasi
syslog /etc/google-fluentd/config.d/syslog.conf
nginx /etc/google-fluentd/config.d/nginx.conf
apache2 /etc/google-fluentd/config.d/apache.conf
apache_error /etc/google-fluentd/config.d/apache.conf

Untuk mengetahui petunjuk cara mengaktifkan logging terstruktur saat menginstal agen Logging lama, lihat bagian Penginstalan.

Agen logging: penginstalan

Untuk mengaktifkan logging terstruktur, Anda harus mengubah konfigurasi default agen Logging lama saat menginstal atau menginstal ulang agen tersebut. Mengaktifkan logging terstruktur akan menggantikan file konfigurasi yang tercantum sebelumnya, tetapi tidak mengubah operasi agen itu sendiri.

Saat Anda mengaktifkan logging terstruktur, log yang tercantum akan dikonversi menjadi entri log dengan format yang berbeda dari format sebelum Anda mengaktifkan log terstruktur. Jika log dirutekan ke tujuan di luar Logging, perubahan tersebut dapat memengaruhi aplikasi pascapemrosesan. Misalnya, jika merutekan log ke BigQuery, BigQuery akan menolak entri log baru selama sisa hari karena memiliki skema yang salah.

Untuk petunjuk cara menginstal agen Logging lama dan mengaktifkan logging terstruktur, lihat Menginstal agen Logging.

Anda dapat menemukan file konfigurasi agen Logging lama di /etc/google-fluentd/config.d/, yang kini akan menyertakan Parser standar yang diaktifkan secara default.

Agen logging: mengonfigurasi format log akses Apache

Secara default, agen Logging lama menyimpan data log akses Apache di kolom jsonPayload. Contoh:

{
  "logName": ...,
  "resource": ...,
  "httpRequest": ...,
  "jsonPayload": {
    "user"   : "some-user",
    "method" : "GET",
    "code"   : 200,
    "size"   : 777,
    "host"   : "192.168.0.1",
    "path"   : "/some-path",
    "referer": "some-referer",
    "agent"  : "Opera/12.0"
  },
  ...
}

Atau, Anda dapat mengonfigurasi agen Logging lama untuk mengekstrak kolom tertentu ke kolom httpRequest. Contoh:

{
  "logName": ...,
  "resource": ...,
  "httpRequest": {
    "requestMethod": "GET",
    "requestUrl": "/some-path",
    "requestSize": "777",
    "status": "200",
    "userAgent": "Opera/12.0",
    "serverIp": "192.168.0.1",
    "referrer":"some-referrer",
  },
  "jsonPayload": {
    "user":"some-user"
  },
  ...
}

Mengonfigurasi kolom httpRequest, seperti yang ditunjukkan pada contoh sebelumnya, akan membantu pelacakan: konsol Google Cloud menampilkan semua log untuk permintaan HTTP tertentu dalam hierarki induk-turunan.

Untuk mengonfigurasi ekstraksi ini, tambahkan kode berikut ke akhir /etc/google-fluentd/config.d/apache.conf:

<filter apache-access>
  @type record_transformer
  enable_ruby true
  <record>
    httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "serverIp" => record['host'],
    "referer" => record['referer']} }
  </record>
  remove_keys method, path, size, code, agent, host, referer
</filter>

Untuk mengetahui detail selengkapnya tentang cara mengonfigurasi entri log, lihat Mengubah data log.

Agen logging: mengonfigurasi format log akses nginx

Secara default, agen Logging lama menyimpan data log akses nginx di kolom jsonPayload. Contoh:

{
  "logName": ...,
  "resource": ...,
  "httpRequest": ...,
  "jsonPayload": {
    "remote":"127.0.0.1",
    "host":"192.168.0.1",
    "user":"some-user",
    "method":"GET",
    "path":"/some-path",
    "code":"200",
    "size":"777",
    "referrer":"some-referrer",
    "agent":"Opera/12.0",
    "http_x_forwarded_for":"192.168.3.3"
  },
  ...
}

Atau, Anda dapat mengonfigurasi agen Logging lama untuk mengekstrak kolom tertentu ke kolom httpRequest. Contoh:

{
  "logName": ...,
  "resource": ...,
  "httpRequest": {
    "requestMethod": "GET",
    "requestUrl": "/some-path",
    "requestSize": "777",
    "status": "200",
    "userAgent": "Opera/12.0",
    "remoteIp": "127.0.0.1",
    "serverIp": "192.168.0.1",
    "referrer":"some-referrer",
  },
  "jsonPayload": {
    "user":"some-user",
    "http_x_forwarded_for":"192.168.3.3"
  },
  ...
}

Mengonfigurasi kolom httpRequest, seperti yang ditunjukkan pada contoh sebelumnya, akan membantu pelacakan: konsol Google Cloud menampilkan semua log untuk permintaan HTTP tertentu dalam hierarki induk-turunan.

Untuk mengonfigurasi ekstraksi ini, tambahkan kode berikut ke akhir /etc/google-fluentd/config.d/nginx.conf:

<filter nginx-access>
  @type record_transformer
  enable_ruby true
  <record>
    httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "remoteIp" => record['remote'], "serverIp" => record['host'], "referer" => record['referer']} }
  </record>
  remove_keys method, path, size, code, agent, remote, host, referer
</filter>

Untuk mengetahui detail selengkapnya tentang cara mengonfigurasi entri log, lihat Mengubah data log.

Menulis parser Anda sendiri

Jika log tidak didukung oleh parser standar, Anda dapat menulis parser Anda sendiri. Parser terdiri dari ekspresi reguler yang digunakan untuk mencocokkan data log dan menerapkan label ke bagian-bagiannya.

Contoh kode berikut menunjukkan baris log dalam data log, konfigurasi dengan ekspresi reguler yang menunjukkan format baris log, dan entri log yang disimpan:

  • Baris log dalam data log:

    REPAIR CAR $500
    
  • Konfigurasi dengan ekspresi reguler yang menunjukkan format baris log:

    $ sudo vim /etc/google-fluentd/config.d/test-structured-log.conf
    $ cat /etc/google-fluentd/config.d/test-structured-log.conf
    <source>
      @type tail
    
      # Format indicates the log should be translated from text to
      # structured (JSON) with three fields, "action", "thing" and "cost",
      # using the following regex:
      format /(?<action>\w+) (?<thing>\w+) \$(?<cost>\d+)/
      # The path of the log file.
      path /tmp/test-structured-log.log
      # The path of the position file that records where in the log file
      # we have processed already. This is useful when the agent
      # restarts.
      pos_file /var/lib/google-fluentd/pos/test-structured-log.pos
      read_from_head true
      # The log tag for this log input.
      tag structured-log
    </source>
    
  • Entri log yang dihasilkan:

    {
    insertId:  "eps2n7g1hq99qp"
    jsonPayload: {
      "action": "REPAIR"
      "thing": "CAR"
      "cost": "500"
    }
    labels: {
      compute.googleapis.com/resource_name:  "add-structured-log-resource"
    }
    logName:  "projects/my-sample-project-12345/logs/structured-log"
    receiveTimestamp:  "2023-03-21T01:47:11.475065313Z"
    resource: {
      labels: {
        instance_id:  "3914079432219560274"
        project_id:  "my-sample-project-12345"
        zone:  "us-central1-c"
      }
      type:  "gce_instance"
    }
    timestamp:  "2023-03-21T01:47:05.051902169Z"
    }
    

Memecahkan masalah

Untuk memecahkan masalah umum yang ditemukan saat menginstal atau berinteraksi dengan agen Logging lama, lihat Memecahkan masalah agen.

Langkah selanjutnya