Logging terstruktur

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

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

  • Panggil metode entries.write API dan berikan LogEntry yang diformat sepenuhnya.
  • Menggunakan library klien Cloud Logging yang menulis log terstruktur.
  • Gunakan perintah gcloud logging write.
  • 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 Cloud Functions.

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

Untuk mengetahui 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 langsung Cloud Logging API. Library klien dapat menyederhanakan pengisian kolom JSON khusus dengan mengambil beberapa informasi secara otomatis dan menyediakan antarmuka untuk mengisi kolom secara tepat. Namun, untuk kontrol penuh atas struktur payload Anda, panggil langsung Cloud Logging API 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 mendukung log tidak terstruktur dan log terstruktur. Jika Anda ingin menulis log terstruktur, berikan perintah objek JSON serial.

Untuk panduan memulai, lihat Menulis dan mengkueri 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 memiliki format JSON dan disusun sesuai dengan sistem sumber. Untuk mengetahui 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 Agen Operasional atau agen Cloud Logging lama. Kedua agen dapat mengumpulkan metrik dari aplikasi pihak ketiga, dan keduanya memberikan dukungan untuk logging terstruktur:

  • Agen Operasional 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 throughput tinggi.

    Untuk informasi tentang cara mengonfigurasi Agen Operasional untuk mendukung logging terstruktur atau menyesuaikan bentuk log terstruktur, lihat Mengonfigurasi Agen Operasional.

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

Bagian selanjutnya khusus membahas 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 ditentukan oleh pengguna
  • httpRequest

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

Untuk membuat entri log terstruktur bagi aplikasi Anda menggunakan format yang disederhanakan, 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 ini adalah satu-satunya kolom yang tersisa setelah agen Logging memindahkan kolom dengan tujuan khusus lainnya dan detect_json tidak diaktifkan; jika tidak, message akan tetap berada di jsonPayload. detect_json tidak berlaku untuk lingkungan logging terkelola seperti Google Kubernetes Engine. Jika entri log Anda berisi stack trace pengecualian, stack trace pengecualian harus ditetapkan dalam kolom log JSON message ini agar stack trace pengecualian dapat diuraikan dan disimpan ke Error Reporting.
log (khusus Google Kubernetes Engine lama) textPayload Hanya berlaku untuk Google Kubernetes Engine lama: jika, setelah memindahkan kolom tujuan khusus, hanya tersisa satu kolom log, maka kolom tersebut disimpan sebagai textPayload.
httpRequest httpRequest Data terstruktur dalam format kolom HttpRequest LogEntry. "httpRequest":{"requestMethod":"GET"}
bidang yang terkait dengan waktu, timestamp Untuk mengetahui 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 catatan 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 yang 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 rekaman aktivitas 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 trace. 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 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 dari entri tersebut 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 pemaketan khusus Cloud Logging dari pengumpul data log Fluentd. Agen Logging dilengkapi dengan konfigurasi Fluentd default dan menggunakan plugin input Fluentd untuk mengambil log peristiwa dari sumber eksternal seperti file pada 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 menggunakan format [PARSER_NAME], Anda dapat mem-build di parser bawaan yang disediakan oleh Fluentd. Untuk informasi tentang cara mengonfigurasi agen Logging lama, lihat Mengonfigurasi agen Logging.

Contoh kode berikut menunjukkan konfigurasi Fluentd, 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>
    
  • Catatan 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 mengetahui 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 mendapatkan petunjuk tentang 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. Mengaktifkan logging terstruktur akan menggantikan file konfigurasi yang tercantum sebelumnya, tetapi tidak mengubah operasi agen itu sendiri.

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

Untuk mendapatkan petunjuk tentang 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 seharusnya 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 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 Anda:

<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 mengenai cara mengonfigurasi entri log Anda, 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 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 Anda:

<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 mengenai cara mengonfigurasi entri log Anda, 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 setiap bagian.

Contoh kode berikut menunjukkan baris log dalam catatan 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