Topik ini menjelaskan cara menggunakan Structured Process Language (SPL) dalam berbagai skenario.
Pengoptimalan pernyataan SPL
Anda sering dapat menulis pernyataan SPL dengan beberapa cara untuk mencapai hasil pemrosesan data yang sama. Pernyataan SPL yang ringkas dan efisien menyederhanakan pemeliharaan serta meningkatkan performa. Tabel berikut memberikan beberapa saran.
|
Saran |
Sebelum pengoptimalan |
Setelah pengoptimalan |
|
Gabungkan klausa where yang berurutan menjadi satu. |
|
|
|
Gabungkan klausa extend yang berurutan menjadi satu. |
|
|
|
Ganti extend + project-away dengan project-rename. |
|
|
|
Ubah nilai field secara langsung alih-alih menggunakan extend untuk membuat field baru, kecuali jika diperlukan. |
|
|
Menangani field khusus
Bidang waktu
Selama eksekusi SPL, tipe data field waktu pada log Simple Log Service selalu berupa INTEGER atau BIGINT. Field-field ini mencakup field waktu data __time__ dan bagian nanodetik dari field waktu data __time_ns_part__.
Untuk memperbarui waktu data, gunakan instruksi extend dan pastikan nilai barunya berupa INTEGER atau BIGINT. Instruksi lain tidak dapat mengoperasikan field waktu. Perilaku mereka adalah sebagai berikut:
-
project, project-away, dan project-rename: Instruksi-instruksi ini secara default mempertahankan field waktu. Anda tidak dapat mengganti nama atau menimpanya.
-
parse-regexp dan parse-json: Jika hasil ekstraksi mencakup field waktu, field tersebut diabaikan.
Contoh
Ekstrak nilai field waktu dari string waktu yang sudah 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 input
time: '2023-11-11 01:23:45.678' -
Hasil output
__time__: 1699637025 __time_ns_part__: 678000000 time: '2023-11-11 01:23:45.678'
Nama field yang mengandung karakter khusus
Jika nama field mengandung spasi atau karakter khusus lainnya, sertakan dalam tanda kutip ganda (") saat Anda mereferensikannya. Misalnya, jika sebuah field bernama A B, yang mengandung spasi, Anda dapat mereferensikannya sebagai "A B" dalam pernyataan SPL. Contoh berikut menunjukkan cara melakukannya:
* | where "A B" like '%error%'
Nama field yang tidak peka huruf besar/kecil
Dalam kueri scan SLS, nama field yang direferensikan dalam instruksi SPL bersifat tidak peka huruf besar/kecil. Misalnya, jika sebuah log berisi field bernama Method, Anda dapat mereferensikannya sebagai method atau METHOD dalam instruksi SPL.
Ini berlaku untuk fitur kueri scan Simple Log Service. Untuk informasi lebih lanjut, lihat Kueri scan.
Contoh
Gunakan nama field yang tidak peka huruf besar/kecil dalam klausa where.
-
Pernyataan SPL
* | where METHOD like 'Post%' -
Data input
Method: 'PostLogstoreLogs' -
Hasil output
Method: 'PostLogstoreLogs'
Menangani konflik nama field
Selama pengunggahan log atau eksekusi SPL, pemrosesan yang peka huruf besar/kecil dapat menyebabkan konflik nama field. Misalnya, log mentah mungkin berisi field Method dan method sekaligus. SPL menyelesaikan konflik ini secara berbeda tergantung skenarionya.
Untuk menghindari situasi ini, Anda dapat menstandarkan nama field dalam log mentah Anda.
Konflik dalam data input
Jika log mentah berisi field dengan nama yang sama ketika diabaikan perbedaan huruf besar/kecilnya, seperti Status dan status, SPL secara acak memilih satu field sebagai input dan membuang yang lainnya. Misalnya:
-
Pernyataan SPL
* | extend status_cast = cast(status as bigint) -
Data input
Status: '200' status: '404' -
Hasil pemrosesan
-
Kemungkinan 1: Nilai field Status dipertahankan.
Status: '200' -- Kolom pertama dipertahankan, kolom kedua dibuang. status_cast: '200' -
Kemungkinan 2: Nilai field status dipertahankan.
status: '404' -- Kolom kedua dipertahankan, kolom pertama dibuang. Status_cast: '404'
-
Konflik dalam hasil output
Skenario 1: Konflik field data mentah
Selama eksekusi SPL, field dengan nama yang sama ketika diabaikan perbedaan huruf besar/kecilnya mungkin dihasilkan. Dalam kasus ini, SPL secara acak memilih salah satunya untuk output. Misalnya, jika sebuah field log berisi string JSON, penggunaan instruksi parse-json mungkin membuat field dengan nama yang bertentangan. Contohnya:
-
Pernyataan SPL
* | parse-json content -
Data input
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' -
Hasil output
-
Kemungkinan 1: Field Method dipertahankan.
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' Method: 'PostLogs' -- Field Method dipertahankan. status: '200' -
Kemungkinan 2: Field method dipertahankan.
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' method: 'GetLogs' -- Field method dipertahankan. status: '200'
-
Skenario 2: Konflik dengan field data yang baru dihasilkan
Untuk menghindari ambiguitas, SPL mempertahankan huruf besar/kecil dari nama field baru yang dihasilkan secara eksplisit oleh instruksi. Ini berlaku untuk nama field yang dihasilkan oleh instruksi extend dan nama field yang secara eksplisit ditentukan menggunakan as dalam instruksi parse-regexp dan parse-csv.
Misalnya, jika Anda menggunakan extend untuk membuat field baru Method, nama field yang dihasilkan tetap Method.
-
Pernyataan SPL
* | extend Method = 'Post' -
Data input
Status: '200' -
Hasil output
Status: '200' Method: 'Post'
Menangani konflik field tercadang SLS
Ini berlaku untuk fitur konsumsi real-time dan kueri scan Simple Log Service.
Untuk daftar lengkap field tercadang, lihat Field tercadang. SPL membaca data dari struktur LogGroup sebagai input. Untuk informasi lebih lanjut tentang definisi LogGroup, lihat Encoding data. Jika data mentah yang ditulis ke Simple Log Service tidak di-encode dalam format LogGroup standar, beberapa field tercadang mungkin berada di LogContent alih-alih lokasi standarnya. SPL menangani field tercadang ini sebagai berikut:
-
Untuk field
__source__,__topic__,__time__, dan__time_ns_part__, SPL membaca nilainya dari struktur LogGroup standar dan mengabaikan field apa pun dengan nama yang sama di LogContent. -
Untuk field tag dengan awalan
__tag__:, SPL pertama-tama mencoba membaca nilainya dari struktur LogGroup standar. Jika nilai tidak ditemukan, SPL membacanya dari LogContent. Misalnya, untuk field__tag__:ip, SPL pertama-tama mencoba membaca field dengan kunciipdari daftar LogTag. Jika field tersebut tidak ada, SPL kemudian membaca field log dengan kunci__tag__:ipdari field log kustom di LogContent.
Field __line__ untuk pencarian teks penuh
Ini berlaku untuk fitur kueri scan SLS.
Untuk memfilter log mentah di Konsol atau saat menggunakan operasi API GetLogstoreLogs, Anda dapat menggunakan field __line__.
Contoh
-
Cari kata kunci error dalam log.
* | where __line__ like '%error%' -
Jika sebuah log berisi field bernama
`__line__`, sertakan nama field dalam backtick untuk mereferensikannya.* | where `__line__` ='20'
Kebijakan retensi dan penimpaan nilai
Saat instruksi SPL dieksekusi, jika field output memiliki nama yang sama dengan field yang sudah ada dalam data input, kebijakan untuk menentukan nilai field tersebut adalah sebagai berikut:
Kebijakan retensi dan penimpaan nilai tidak berlaku untuk instruksi extend. Untuk instruksi extend, jika terjadi konflik nama field, nilai baru selalu digunakan.
Tipe data lama dan baru tidak konsisten
Nilai asli field input dipertahankan.
Contoh
-
Contoh 1: Field yang diganti nama dari instruksi project memiliki nama yang bertentangan.
-
Pernyataan SPL
* | extend status=cast(status as BIGINT) -- Ubah tipe field status menjadi BIGINT. | project code=status -- Tipe nilai baru (BIGINT) berbeda dari tipe nilai lama (VARCHAR), sehingga nilai lama dipertahankan. -
Data input
status: '200' code: 'Success' -
Hasil output
code: 'Success'
-
-
Contoh 2: Field yang diekstrak dari instruksi parse-json memiliki nama yang bertentangan.
-
Pernyataan SPL
* | extend status=cast(status as BIGINT) -- Ubah tipe field status menjadi BIGINT. | parse-json content -- Tipe lama status adalah BIGINT dan tipe baru adalah VARCHAR. Nilai lama dipertahankan. -
Data input
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Hasil output
content: '{"status": "Success", "body": "this is test"}' status: 200 body: 'this is test'
-
Tipe data lama dan baru konsisten
Jika nilai input adalah null, nilai baru digunakan. Jika tidak, perilaku ditentukan oleh parameter mode dalam instruksi, sebagaimana didefinisikan dalam tabel berikut.
Jika parameter mode tidak ditentukan dalam instruksi, nilai default-nya adalah overwrite.
|
Mode |
Deskripsi |
|
overwrite |
Menimpa nilai lama dengan nilai baru. |
|
preserve |
Mempertahankan nilai lama dan membuang nilai baru. |
Contoh
-
Contoh 1: Field yang diganti nama 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 sama-sama VARCHAR. Nilai baru digunakan berdasarkan mode overwrite.-
Data input
status: '200' code: 'Success' -
Hasil output
code: '200'
-
-
Contoh 2: Field yang diekstrak 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 sama-sama VARCHAR. Nilai baru digunakan berdasarkan mode overwrite. -
Data input
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Hasil output
content: '{"status": "Success", "body": "this is test"}' status: 'Success' body: 'this is test'
-
-
Contoh 3: Field yang diekstrak 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 sama-sama VARCHAR. Nilai lama dipertahankan berdasarkan mode preserve. -
Data input
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Hasil output
content: '{"status": "Success", "body": "this is test"}' status: '200' body: 'this is test'
-
Konversi tipe data
Tipe awal
Saat SPL memproses data, tipe data awal semua field input adalah VARCHAR, kecuali field waktu log. Jika logika pemrosesan selanjutnya melibatkan tipe data yang berbeda, Anda harus melakukan konversi tipe data.
Contoh
Untuk memfilter log akses dengan kode status 5xx, Anda harus mengonversi field status ke tipe BIGINT sebelum perbandingan.
* -- Tipe awal field status adalah VARCHAR.
| where cast(status as BIGINT) >= 500 -- Ubah tipe field status menjadi BIGINT, lalu lakukan perbandingan.
Retensi tipe
Selama pemrosesan data SPL, setelah Anda menggunakan instruksi extend untuk mengonversi tipe data suatu field, logika pemrosesan selanjutnya menggunakan tipe data yang telah dikonversi tersebut.
Contoh
* -- Logstore digunakan sebagai data input. Kecuali field waktu, semua field awalnya bertipe VARCHAR.
| where __source__='127.0.0.1' -- Filter berdasarkan field __source__.
| extend status=cast(status as BIGINT) -- Ubah tipe field status menjadi BIGINT.
| project status, content
| where status>=500 -- Tipe field 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:
-
Jika field yang digunakan dalam ekspresi SPL tidak ada dalam data input, nilainya dianggap null selama perhitungan.
-
Jika terjadi exception selama perhitungan ekspresi SPL, hasilnya adalah null. Misalnya, konversi tipe cast gagal atau indeks array di luar batas.
Contoh
-
Jika field tidak ada, nilainya dianggap null dalam perhitungan.
-
Pernyataan SPL
* | extend withoutStatus=(status is null) -
Data input
# Entri 1 status: '200' code: 'Success' # Entri 2 code: 'Success' -
Hasil output
# Entri 1 status: '200' code: 'Success' withoutStatus: false # Entri 2 code: 'Success' withoutStatus: true
-
-
Jika terjadi exception selama perhitungan, hasilnya adalah null.
-
Pernyataan SPL
* | extend code=cast(code as BIGINT) -- Gagal mengonversi field code ke BIGINT. | extend values=json_parse(values) | extend values=cast(values as ARRAY(BIGINT)) | extend last=arr[10] -- Indeks array di luar batas. -
Data input
status: '200' code: 'Success' values: '[1,2,3]' -
Hasil output
status: '200' code: null values: [1, 2, 3] last: null
-
Menghilangkan nilai null
Untuk menghilangkan nilai null selama perhitungan, Anda dapat menggunakan ekspresi COALESCE. Ekspresi ini mengembalikan nilai pertama yang bukan null dari daftar ekspresi. Anda juga dapat menetapkan nilai default yang digunakan jika semua ekspresi bernilai null.
Contoh
Baca elemen terakhir dari array. Jika array kosong, nilai default-nya 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 input
# Entri 1 values: '[1, 2, 3]' # Entri 2 values: '[]' -
Hasil output
# Entri 1 values: [1, 2, 3] last: 3 # Entri 2 values: [] last: 0
Escape karakter
Tanda kutip tunggal
Tanda kutip tunggal digunakan untuk mengapit literal string. Jika literal string mengandung tanda kutip tunggal, Anda harus menggunakan tanda kutip tunggal tambahan untuk meng-escape-nya.
Contoh
-
Pernyataan SPL
* | extend user = 'Alice' | extend phone = 'Alice''s Phone' -
Hasil output
user: Alice phone: Alice's Phone
Tanda kutip ganda
Tanda kutip ganda digunakan untuk mengapit nama field. Jika nama field mengandung tanda kutip ganda, Anda harus menggunakan tanda kutip ganda tambahan untuk meng-escape-nya.
Contoh
-
Pernyataan SPL
* | extend user_name = 'Alice' | extend "user name" = 'Alice' | extend "user""name" = 'Alice' -
Hasil output
user_name: Alice user name: Alice user"name: Alice
Karakter khusus lainnya
Contoh 1
Dalam SPL, backslash (\) bukan karakter escape dan karena itu dipertahankan apa adanya.
-
Pernyataan SPL
* | extend a = 'foo\tbar' | extend b = 'foo\nbar' -
Hasil output
a: foo\tbar b: foo\nbar
Contoh 2
Jika string harus menyertakan 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 output
a: foo bar b: foo bar
Penanganan error
Error sintaksis
Error sintaksis terjadi ketika pernyataan SPL tidak valid, seperti nama instruksi salah, kesalahan referensi kata kunci, atau kesalahan spesifikasi tipe. Saat terjadi error sintaksis, SPL tidak memproses data apa pun. Anda harus memperbaiki pernyataan berdasarkan pesan error.
Error data
Error data terjadi ketika fungsi atau konversi gagal selama eksekusi SPL. SPL mengatur field hasil menjadi null. Karena error data dapat terjadi pada baris mana pun, SPL secara acak mengambil sampel dan hanya mengembalikan sebagian pesan error. Anda dapat mengabaikan error ini atau memodifikasi pernyataan SPL berdasarkan konten data.
Error data tidak menghentikan seluruh proses eksekusi. Pernyataan SPL tetap mengembalikan hasil, tetapi nilai field tempat error terjadi adalah null. Anda dapat mengabaikan error ini sesuai kebutuhan.
Timeout eksekusi
Pernyataan SPL berisi berbagai instruksi, dan waktu eksekusinya bervariasi tergantung skenario data. Jika total waktu eksekusi pernyataan SPL melebihi periode timeout default, eksekusi dihentikan dan error timeout dikembalikan. Dalam kasus ini, hasil eksekusi kosong. Periode timeout default dapat berbeda untuk kueri scan, konsumsi real-time, dan pengumpulan Logtail.
Jika Anda mengalami error ini, Anda dapat menyesuaikan pernyataan SPL untuk mengurangi kompleksitasnya, misalnya dengan menyederhanakan ekspresi reguler yang kompleks atau mengurangi jumlah pipeline.
Batas memori terlampaui
Pernyataan SPL berisi berbagai instruksi, dan konsumsi memorinya bervariasi tergantung skenario data. Eksekusi SPL dibatasi oleh kuota memori tertentu. Jika kuota ini terlampaui, eksekusi gagal dan error batas memori terlampaui dikembalikan. Dalam kasus ini, hasil eksekusi kosong. Kuota memori default dapat berbeda untuk kueri scan, konsumsi real-time, dan pengumpulan Logtail.
Jika Anda mengalami error ini, Anda dapat menyesuaikan pernyataan SPL untuk mengurangi kompleksitasnya, mengurangi jumlah pipeline, atau memeriksa apakah ukuran data mentah terlalu besar.