全部产品
Search
文档中心

Simple Log Service:Referensi Umum

更新时间:Aug 22, 2025

Topik ini menjelaskan cara menggunakan Bahasa Proses Terstruktur (SPL) dalam berbagai skenario.

Optimasi Pernyataan SPL

Pernyataan SPL dapat ditulis dengan beberapa cara untuk mencapai hasil pemrosesan data tertentu. Menulis pernyataan SPL yang ringkas dan efisien menyederhanakan pemeliharaan serta meningkatkan kinerja. Tabel berikut memberikan beberapa saran.

Saran

Sebelum optimasi

Setelah optimasi

Gabungkan klausa `where` berturut-turut menjadi satu.

*
| where request_method = 'POST'
| where cast(status as integer) >= 500
*
| where request_method = 'POST' and cast(status as integer) >= 500

Gabungkan klausa `extend` berturut-turut menjadi satu.

*
| extend k1 = 'v1'
| extend k2 = 'v2'
| extend k3 = 'v3'
*
| extend k1 = 'v1', k2 = 'v2', k3 = 'v3'

Ganti `extend` dan `project-away` dengan `project-rename`.

*
| extend method = request_method
| project-away request_method
*
| project-rename method = request_method

Ubah nilai bidang di tempatnya alih-alih menggunakan `extend` untuk membuat bidang baru, kecuali diperlukan.

*
| extend newContent = json_extract(content, 'abc \d+')
| project-away content
*
| extend content = json_extract(content, 'abc \d+')

Menangani bidang khusus

Bidang waktu

Selama eksekusi SPL, tipe data dari bidang waktu log SLS selalu INTEGER atau BIGINT. Bidang log SLS mencakup bidang waktu data __time__ dan bagian nanodetik dari bidang waktu data __time_ns_part__.

Untuk memperbarui waktu data, gunakan instruksi `extend` dan pastikan nilai baru adalah INTEGER atau BIGINT. Instruksi lain tidak dapat beroperasi pada bidang waktu. Perilaku mereka adalah sebagai berikut:

  • `project`, `project-away`, dan `project-rename`: Instruksi ini secara default mempertahankan bidang waktu. Anda tidak dapat mengganti nama atau menimpanya.

  • `parse-regexp` dan `parse-json`: Jika hasil ekstraksi mencakup bidang waktu, mereka akan diabaikan.

Contoh

Ekstrak nilai bidang waktu dari string waktu yang ada.

  • Pernyataan SPL

    * 
    | parse-regexp time, '([\d\-\s:]+)\.(\d+)' as ts, ms
    | extend ts=date_parse(ts, '%Y-%m-%d %H:%i:%S')
    | extend __time__=cast(to_unixtime(ts) as INTEGER)
    | extend __time_ns_part__=cast(ms as INTEGER) * 1000000
    | project-away ts, ms
  • Data Masukan

    time: '2023-11-11 01:23:45.678'
  • Hasil Keluaran

    __time__: 1699637025
    __time_ns_part__: 678000000
    time: '2023-11-11 01:23:45.678'

Nama bidang dengan karakter khusus

Jika nama bidang berisi spasi atau karakter khusus lainnya, apit dengan tanda kutip ganda (") saat merujuknya. Sebagai contoh, jika sebuah bidang bernama A B, yang berisi spasi, Anda dapat merujuknya sebagai "A B" dalam pernyataan SPL. Contoh berikut menunjukkan cara melakukannya:

* | where "A B" like '%error%'

Nama bidang tanpa membedakan huruf besar/kecil

Dalam kueri pemindaian SLS, nama bidang yang dirujuk dalam instruksi SPL bersifat case-insensitive. Sebagai contoh, jika log berisi bidang bernama Method, Anda dapat merujuknya sebagai method atau METHOD dalam instruksi SPL.

Penting

Ini berlaku untuk fitur kueri pemindaian dari Simple Log Service. Untuk informasi selengkapnya, lihat Kueri Pemindaian.

Contoh

Gunakan nama bidang tanpa membedakan huruf besar/kecil dalam klausa `where`.

  • Pernyataan SPL

    * | where METHOD like 'Post%'
  • Data Masukan

    Method: 'PostLogstoreLogs'
  • Hasil Keluaran

    Method: 'PostLogstoreLogs'

Tangani konflik nama bidang

Selama pengunggahan log atau eksekusi SPL, penanganan nama bidang tanpa membedakan huruf besar/kecil dapat menyebabkan konflik. Sebagai contoh, konflik terjadi jika log mentah berisi bidang `Method` dan `method`. SPL menyelesaikan konflik ini secara berbeda tergantung pada skenario.

Untuk menghindari situasi ini, standarisasikan nama bidang dalam log mentah Anda.

Konflik dalam data masukan

Jika log mentah berisi bidang dengan konflik nama tanpa membedakan huruf besar/kecil, seperti Status dan status, SPL secara acak memilih salah satu bidang untuk masukan dan membuang yang lain. Sebagai contoh:

  • Pernyataan SPL

    * | extend status_cast = cast(status as bigint)
  • Data Masukan

    Status: '200'
    status: '404'
  • Hasil Pemrosesan

    • Kemungkinan 1: Nilai bidang Status dipertahankan.

      Status: '200' -- Kolom pertama dipertahankan, kolom kedua dibuang.
      status_cast: '200'
    • Kemungkinan 2: Nilai bidang status dipertahankan.

      status: '404' -- Kolom kedua dipertahankan, kolom pertama dibuang.
      Status_cast: '404'

Konflik dalam hasil keluaran

Skenario 1: Konflik Bidang Data Mentah

Selama eksekusi SPL, bidang dengan konflik nama tanpa membedakan huruf besar/kecil mungkin dihasilkan. Dalam hal ini, SPL secara acak memilih salah satu dari mereka untuk keluaran. Sebagai contoh, jika bidang log berisi string JSON, menggunakan instruksi parse-json mungkin membuat bidang dengan nama yang bertentangan. Sebagai contoh:

  • Pernyataan SPL

    * | parse-json content
  • Data Masukan

    content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}'
  • Hasil Keluaran

    • Kemungkinan 1: Bidang Method dipertahankan.

      content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}'
      Method: 'PostLogs' -- Bidang Method dipertahankan.
      status: '200'
    • Kemungkinan 2: Bidang method dipertahankan.

      content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}'
      method: 'GetLogs' -- Bidang method dipertahankan.
      status: '200'

Skenario 2: Konflik dengan Bidang Data Baru yang Dihasilkan

Untuk menghindari ambiguitas, SPL mempertahankan huruf besar/kecil dari nama bidang baru yang dihasilkan secara eksplisit oleh instruksi. Instruksi ini mencakup extend dan instruksi yang menggunakan as untuk menentukan nama bidang, seperti parse-regexp dan parse-csv.

Sebagai contoh, jika Anda menggunakan extend untuk membuat bidang baru bernama Method, nama bidang yang dihasilkan tetap Method.

  • Pernyataan SPL

    * | extend Method = 'Post'
  • Data Masukan

    Status: '200'
  • Hasil Keluaran

    Status: '200'
    Method: 'Post'

Menangani konflik bidang cadangan SLS

Penting

Ini berlaku untuk fitur konsumsi real-time dan kueri pemindaian Layanan Log Sederhana.

Untuk daftar lengkap bidang yang dicadangkan, lihat Bidang yang Dicadangkan. SPL membaca data dari struktur LogGroup (lihat Pengodean Data untuk definisi LogGroup). Jika data mentah tidak sesuai dengan pengodean LogGroup standar, beberapa bidang yang dicadangkan mungkin berada di LogContent alih-alih di lokasi standarnya. SPL menangani konflik ini sebagai berikut:

  • Untuk bidang __source__, __topic__, __time__, dan __time_ns_part__, SPL membaca nilai dari pengkodean LogGroup standar dan mengabaikan bidang LogContent apa pun dengan nama yang sama.

  • Untuk bidang tag dengan awalan __tag__: , SPL pertama-tama mencoba membaca nilai dari pengkodean LogGroup standar. Jika nilai tidak ditemukan, SPL membacanya dari LogContent. Sebagai contoh, untuk bidang __tag__:ip, SPL pertama-tama mencoba membaca bidang dengan kunci ip dari daftar LogTag. Jika bidang tersebut tidak ada, SPL kemudian membaca bidang log dengan kunci __tag__:ip dari bidang log kustom di LogContent.

Bidang __line__ untuk pencarian teks penuh

Penting

Ini berlaku untuk fitur kueri pemindaian SLS.

Untuk memfilter log mentah di Konsol atau saat menggunakan operasi API GetLogstoreLogs, Anda dapat menggunakan bidang `__line__`.

Contoh

  • Cari kata kunci `error` dalam log.

    * | where __line__ like '%error%'
  • Jika log memiliki bidang bernama `__line__`, apit nama tersebut dengan backticks (`` ` ``) untuk merujuknya, seperti `__line__`.

    * | where `__line__` ='20'

Kebijakan Penyimpanan dan Penimpaan Nilai

Saat instruksi SPL dieksekusi, jika bidang keluaran memiliki nama yang sama dengan bidang yang ada di data masukan, kebijakan untuk menentukan nilai bidang tersebut adalah sebagai berikut:

Penting

Kebijakan untuk mempertahankan dan menimpa nilai bidang tidak berlaku untuk instruksi `extend`. Untuk instruksi `extend`, jika terjadi konflik nama bidang, nilai baru selalu digunakan.

Tipe data tidak konsisten antara nilai lama dan baru

Nilai asli dari bidang masukan dipertahankan.

Contoh

  • Contoh 1: Bidang yang diubah namanya dari instruksi `project` memiliki nama yang bertentangan.

    • Pernyataan SPL

      * 
      | extend status=cast(status as BIGINT) -- Ubah tipe bidang status menjadi BIGINT.
      | project code=status -- Tipe nilai baru (BIGINT) berbeda dari tipe nilai lama (VARCHAR), jadi nilai lama dipertahankan.
    • Data Masukan

      status: '200'
      code: 'Success'
    • Hasil Keluaran

      code: 'Success'
  • Contoh 2: Bidang yang diekstraksi dari instruksi `parse-json` memiliki nama yang bertentangan.

    • Pernyataan SPL

      * 
      | extend status=cast(status as BIGINT) -- Ubah tipe bidang status menjadi BIGINT.
      | parse-json content -- Tipe lama status adalah BIGINT dan tipe baru adalah VARCHAR. Nilai lama dipertahankan.
    • Data Masukan

      status: '200'
      content: '{"status": "Success", "body": "this is test"}'
    • Hasil Keluaran

      content: '{"status": "Success", "body": "this is test"}'
      status: 200
      body: 'this is test'

Tipe data konsisten antara nilai lama dan baru

Jika nilai masukan adalah null, nilai baru akan digunakan. Jika tidak, perilaku ditentukan oleh parameter mode dalam instruksi, sebagaimana didefinisikan dalam tabel berikut.

Penting

Jika parameter mode tidak didefinisikan dalam instruksi, nilai defaultnya adalah overwrite.

Mode

Deskripsi

overwrite

Menimpa nilai lama dengan nilai baru.

preserve

Mempertahankan nilai lama dan membuang nilai baru.

Contoh

  • Contoh 1: Bidang yang diubah namanya dari instruksi `project` memiliki nama yang bertentangan dan tipe yang sama. Mode default adalah `overwrite`.

    • Pernyataan SPL

    * | project code=status -- Tipe lama dan baru dari code keduanya adalah VARCHAR. Nilai baru digunakan berdasarkan mode overwrite.
    • Data Masukan

      status: '200'
      code: 'Success'
    • Hasil Keluaran

      code: '200'
  • Contoh 2: Bidang yang diekstraksi dari instruksi `parse-json` memiliki nama yang bertentangan dan tipe yang sama. Mode default adalah `overwrite`.

    • Pernyataan SPL

      * | parse-json content -- Tipe lama dan baru dari status keduanya adalah VARCHAR. Nilai baru digunakan berdasarkan mode overwrite.
    • Data Masukan

      status: '200'
      content: '{"status": "Success", "body": "this is test"}'
    • Hasil Keluaran

      content: '{"status": "Success", "body": "this is test"}'
      status: 'Success'
      body: 'this is test'
  • Contoh 3: Bidang yang diekstraksi dari instruksi `parse-json` memiliki nama yang bertentangan dan tipe yang sama. Mode diatur ke `preserve`.

    • Pernyataan SPL

      * | parse-json -mode='preserve' content -- Tipe lama dan baru dari status keduanya adalah VARCHAR. Nilai lama dipertahankan berdasarkan mode preserve.
    • Data Masukan

      status: '200'
      content: '{"status": "Success", "body": "this is test"}'
    • Hasil Keluaran

      content: '{"status": "Success", "body": "this is test"}'
      status: '200'
      body: 'this is test'

Konversi Tipe Data

Tipe awal

Untuk pemrosesan data dengan SPL, tipe data awal dari semua bidang masukan adalah VARCHAR, kecuali untuk bidang waktu log. Jika logika pemrosesan selanjutnya melibatkan tipe data yang berbeda, Anda harus melakukan konversi tipe data.

Contoh

Untuk menyaring log akses dengan kode status 5xx, Anda harus mengonversi bidang `status` ke tipe BIGINT sebelum perbandingan.

* -- Tipe awal dari bidang status adalah VARCHAR.
| where cast(status as BIGINT) >= 500 -- Konversikan tipe bidang status menjadi BIGINT, lalu lakukan perbandingan.

Penyimpanan tipe

Selama pemrosesan data SPL, setelah Anda menggunakan instruksi `extend` untuk mengonversi tipe data suatu bidang, logika pemrosesan selanjutnya menggunakan tipe data yang dikonversi.

Contoh

* -- Logstore digunakan sebagai data masukan. Kecuali untuk bidang waktu, semua bidang awalnya bertipe VARCHAR.
| where __source__='127.0.0.1' -- Filter pada bidang __source__.
| extend status=cast(status as BIGINT) -- Konversikan tipe bidang status menjadi BIGINT.
| project status, content
| where status>=500 -- Tipe bidang status tetap BIGINT, sehingga dapat langsung dibandingkan dengan angka 500.

Menangani Nilai Null dalam Ekspresi SPL

Menghasilkan Nilai Null

Selama pemrosesan data SPL, nilai null dihasilkan dalam dua skenario berikut:

  1. Jika bidang yang digunakan dalam ekspresi SPL tidak ada dalam data masukan, nilainya dianggap null selama perhitungan.

  2. Jika terjadi pengecualian selama perhitungan ekspresi SPL, hasilnya adalah null. Sebagai contoh, konversi tipe `cast` gagal atau indeks array di luar batas.

Contoh

  1. Jika sebuah bidang tidak ada, nilainya dianggap null dalam perhitungan.

    • Pernyataan SPL

      * | extend withoutStatus=(status is null)
    • Data Masukan

      # Entri 1
      status: '200'
      code: 'Success'
      
      # Entri 2
      code: 'Success'
    • Hasil Keluaran

      # Entri 1
      status: '200'
      code: 'Success'
      withoutStatus: false
      
      # Entri 2
      code: 'Success'
      withoutStatus: true
  2. Jika terjadi pengecualian selama perhitungan, hasilnya adalah null.

    • Pernyataan SPL

      *
      | extend code=cast(code as BIGINT) -- Gagal mengonversi bidang code menjadi BIGINT.
      | extend values=json_parse(values)
      | extend values=cast(values as ARRAY(BIGINT))
      | extend last=arr[10] -- Indeks array di luar batas.
    • Data Masukan

      status: '200'
      code: 'Success'
      values: '[1,2,3]'
    • Hasil Keluaran

      status: '200'
      code: null
      values: [1, 2, 3]
      last: null

Menghilangkan Nilai Null

Untuk menghilangkan nilai null selama perhitungan, Anda dapat menggunakan ekspresi `COALESCE` untuk menggabungkan beberapa nilai berdasarkan prioritas dan mengambil nilai non-null pertama sebagai hasil akhir. Anda juga dapat menetapkan nilai default untuk digunakan jika semua hasil ekspresi adalah null.

Contoh

Baca elemen terakhir dari array. Jika array kosong, nilai defaultnya adalah 0.

  • Pernyataan SPL

    *
    | extend values=json_parse(values)
    | extend values=cast(values as ARRAY(BIGINT))
    | extend last=COALESCE(values[3], values[2], values[1], 0)
  • Data Masukan

    # Entri 1
    values: '[1, 2, 3]'
    
    # Entri 2
    values: '[]'
  • Hasil Keluaran

    # Entri 1
    values: [1, 2, 3]
    last: 3
    
    # Entri 2
    values: []
    last: 0

Pelarian Karakter

Tanda Kutip Tunggal

Tanda kutip tunggal digunakan untuk mengapit nilai bidang. Jika nilai bidang berisi tanda kutip tunggal, Anda harus menggunakan tanda kutip tunggal tambahan untuk melarikannya.

Contoh

  • Pernyataan SPL

    *
    | extend user = 'Alice'
    | extend phone = 'Alice''s Phone'
  • Hasil Keluaran

    user: Alice
    phone: Alice's Phone

Tanda Kutip Ganda

Tanda kutip ganda digunakan untuk mengapit nama bidang. Jika nama bidang berisi tanda kutip ganda, Anda harus menggunakan tanda kutip ganda tambahan untuk melarikannya.

Contoh

  • Pernyataan SPL

    *
    | extend user_name = 'Alice'
    | extend "user name" = 'Alice'
    | extend "user""name" = 'Alice'
  • Hasil Keluaran

    user_name: Alice
    user name: Alice
    user"name: Alice

Karakter Khusus Lainnya

Contoh 1

Dalam SPL, backslash (\) bukanlah karakter pelarian dan oleh karena itu disimpan apa adanya.

  • Pernyataan SPL

    *
    | extend a = 'foo\tbar'
    | extend b = 'foo\nbar'
  • Hasil Keluaran

    a: foo\tbar
    b: foo\nbar

Contoh 2

Jika string harus mencakup karakter khusus, seperti karakter tab atau line feed, Anda dapat menggunakan fungsi chr untuk menggabungkan string.

  • Pernyataan SPL

    *
    | extend a = concat('foo', chr(9), 'bar')
    | extend b = concat('foo', chr(10), 'bar')
  • Hasil Keluaran

    a: foo	bar
    b: foo
    bar

Penanganan Kesalahan

Kesalahan sintaksis

Kesalahan sintaksis terjadi ketika pernyataan SPL salah bentuk, seperti nama instruksi yang salah, kesalahan referensi kata kunci, atau kesalahan pengaturan tipe. Saat terjadi kesalahan sintaksis, SPL tidak memproses data apa pun. Anda harus memodifikasi pernyataan berdasarkan pesan kesalahan.

Kesalahan data

Kesalahan data terjadi ketika fungsi atau konversi gagal selama eksekusi SPL. SPL menetapkan bidang hasil menjadi null. Karena kesalahan data dapat terjadi pada baris mana saja, SPL secara acak mengambil sampel dan hanya mengembalikan beberapa pesan kesalahan. Anda dapat mengabaikan kesalahan ini atau memodifikasi pernyataan SPL berdasarkan isi data.

Kesalahan data tidak menghentikan seluruh proses eksekusi. Pernyataan SPL tetap mengembalikan hasil, tetapi nilai bidang tempat kesalahan terjadi adalah null. Anda dapat mengabaikan kesalahan ini sesuai kebutuhan.

Waktu Eksekusi Habis

Pernyataan SPL mencakup berbagai instruksi, dan waktu eksekusi mereka bervariasi tergantung pada skenario data. Jika total waktu eksekusi pernyataan SPL melebihi periode timeout default, eksekusi berhenti dan kesalahan timeout dikembalikan. Dalam hal ini, hasil eksekusi kosong. Periode timeout default mungkin berbeda untuk kueri pemindaian, konsumsi real-time, dan pengumpulan Logtail.

Jika Anda mengalami kesalahan ini, Anda dapat menyesuaikan pernyataan SPL untuk mengurangi kompleksitasnya, misalnya, dengan menyederhanakan ekspresi reguler yang kompleks atau mengurangi jumlah alur kerja.

Batas Memori Terlampaui

Pernyataan SPL mencakup berbagai instruksi, dan konsumsi memori mereka bervariasi tergantung pada skenario data. Eksekusi SPL dibatasi pada kuota memori tertentu. Jika kuota ini terlampaui, eksekusi gagal dan kesalahan batas memori terlampaui dikembalikan. Dalam hal ini, hasil eksekusi kosong. Kuota memori default mungkin berbeda untuk kueri pemindaian, konsumsi real-time, dan pengumpulan Logtail.

Jika Anda mengalami kesalahan ini, Anda dapat menyesuaikan pernyataan SPL untuk mengurangi kompleksitasnya, mengurangi jumlah alur kerja, atau memeriksa apakah ukuran data mentah terlalu besar.