Pertanyaan umum dan solusi untuk melakukan kueri serta menganalisis log berformat JSON di Simple Log Service, termasuk konfigurasi indeks, fungsi JSON, dan penanganan array JSON.
Contoh log
Contoh dalam topik ini menggunakan log JSON dari sistem pemrosesan pesanan.
{
"request":{
"clientIp":"20xxx30",
"http.path":"/order/buy",
"param":{
"userId": "186453",
"orders":[
{
"commodity":["bread","milk","meat"],
"payment":132
},
{
"commodity":["milk","beer"],
"payment":49
}
]
}
},
"response":"{\"errcode\":400,\"msg\":\"insufficient\"}"
}
Bidang request berisi informasi permintaan pesanan dalam format JSON. Satu permintaan dapat mencakup beberapa pesanan untuk satu pengguna, masing-masing dengan daftar produk yang dibeli dan total pembayaran.
-
Bidang response berisi hasil pemrosesan pesanan.
Jika berhasil, nilai bidang response adalah
SUCCESS.Jika gagal, nilai bidang response adalah objek JSON yang berisi
errcodedanmsg.
Gunakan Logtail untuk Mengumpulkan log dalam mode JSON ke Simple Log Service untuk kueri dan analisis.
Cara mengonfigurasi indeks
Konfigurasikan indeks sebelum melakukan kueri atau analisis data log. Perhatikan poin-poin berikut saat mengonfigurasi indeks untuk log JSON.
Cara memilih jenis indeks
Simple Log Service mendukung indeks teks penuh (full-text index) dan indeks bidang (field index). Pilih berdasarkan kasus penggunaan Anda. Buat indeks.
Untuk melakukan kueri pada semua bidang, buat indeks teks penuh. Untuk kueri hanya pada bidang tertentu, buat indeks bidang untuk bidang tersebut guna mengurangi biaya.
Untuk menjalankan analisis SQL pada suatu bidang, buat indeks bidang untuknya dan aktifkan statistik.
Jika indeks teks penuh dan indeks bidang dikonfigurasi secara bersamaan, indeks bidang akan memiliki prioritas lebih tinggi untuk bidang-bidang yang telah diberi indeks bidang.
Sebagai contoh, untuk menganalisis bidang request dan response, buat indeks bidang untuk keduanya dan aktifkan statistik.
Cara memilih tipe data untuk suatu bidang dalam konfigurasi indeks
Saat mengonfigurasi indeks, atur tipe data suatu bidang menjadi text, long, double, atau JSON. Tipe data.
Perhatikan hal-hal berikut saat menetapkan tipe data untuk bidang JSON.
-
Jika nilai bidang tidak dalam format JSON standar tetapi berisi konten JSON, atur tipe datanya menjadi text. Jika nilainya dalam format JSON standar, atur menjadi JSON.
CatatanUntuk log JSON yang tidak sepenuhnya valid, Simple Log Service dapat mengurai bagian-bagian yang valid.
Setelah mengatur tipe data menjadi JSON, buat indeks untuk node daun (leaf node) di dalam objek JSON agar kueri lebih cepat. Hal ini menimbulkan biaya indeks tambahan.
Simple Log Service mendukung indeks untuk node daun dalam objek JSON, tetapi tidak untuk node anak yang berisi node daun.
Simple Log Service tidak mendukung indeks untuk bidang yang nilainya berupa array JSON, atau untuk bidang di dalam array JSON. Untuk bidang semacam ini, gunakan fungsi JSON untuk analisis real-time.
Berdasarkan contoh log, buat indeks berikut.
-
Bidang request
request: Nilainya dalam format JSON. Atur tipe data menjadi JSON dan aktifkan statistik.
request.clientIp: Sering dianalisis. Buat indeks terpisah, atur tipe data menjadi text, dan aktifkan statistik.
request.http.path: Jarang dianalisis. Lewati pembuatan indeks terpisah — urai sesuai kebutuhan menggunakan fungsi JSON.
request.param: Node anak yang berisi node daun. Indeks tidak didukung.
request.param.userId: Sering dianalisis. Buat indeks terpisah, atur tipe data menjadi text, dan aktifkan statistik.
request.param.orders: Nilainya berupa array JSON. Indeks tidak didukung.
-
tanggapan bidang
Nilai bidang response tidak selalu dalam format JSON. Atur tipe datanya menjadi text dan aktifkan statistik.
Setelah membuat indeks, log yang baru dikumpulkan akan ditampilkan sesuai konfigurasi indeks tersebut.
Cara mengatur alias
Untuk jalur node daun JSON yang panjang, atur alias. Alias kolom.
Dalam konfigurasi indeks, Anda dapat mengatur alias untuk node daun bidang bertipe JSON. Sebagai contoh, atur alias request.clientIp menjadi ip, dan atur alias request.param.userId menjadi id.
Nama bidang dan alias harus unik di seluruh bidang dalam konfigurasi indeks.
Untuk bidang bertipe JSON, keunikan ditentukan berdasarkan jalur lengkap (full path) node daun. Misalnya, mengatur alias bidang response menjadi clientIp tidak bentrok dengan nama bidang request.clientIp.
Cara melakukan kueri dan analisis pada bidang JSON yang telah diindeks
Pernyataan kueri dan analisis mengikuti format query statement|analytic statement. Dalam pernyataan analitik, sertakan nama bidang dalam tanda kutip ganda ("") dan string dalam tanda kutip tunggal (''). Tentukan jalur lengkap untuk bidang bersarang — misalnya, Key1.Key2.Key3, request.clientIp, atau request.param.userId. Kueri dan analisis log JSON.
Sebagai contoh, untuk menemukan alamat IP client untuk pengguna 186499:
*
and request.param.userId: 186499 |
SELECT
distinct("request.clientIp")
Kapan menggunakan fungsi JSON
Untuk set data besar dengan struktur JSON kompleks namun tetap, di mana performa kueri penting, buat indeks bidang untuk node daun JSON. Untuk set data kecil atau analisis ad-hoc, gunakan fungsi JSON tanpa indeks bidang untuk menghemat biaya. Fungsi JSON memungkinkan pemrosesan dan analisis dinamis terhadap konten JSON. Dalam beberapa kasus, ini merupakan satu-satunya opsi.
-
Nilai bidang tidak selalu dalam format JSON atau memerlukan pra-pemrosesan.
Sebagai contoh, bidang response hanya berisi JSON dengan bidang errcode ketika permintaan gagal. Untuk menganalisis distribusi errcode, filter permintaan yang gagal dan ekstrak errcode menggunakan fungsi JSON.
* not response :SUCCESS | SELECT json_extract_scalar(response, '$.errcode') AS errcode
Bidang tidak dapat diindeks. Untuk node JSON yang tidak mendukung pengindeksan — seperti request.param dan request.param.orders — fungsi JSON merupakan satu-satunya cara untuk menjalankan analisis real-time.
Cara memilih antara json_extract dan json_extract_scalar
Kedua fungsi json_extract dan json_extract_scalar mengekstrak konten dari objek atau array JSON. Perbedaan utamanya terletak pada tipe kembalian.
-
json_extractmengembalikan tipe JSON;json_extract_scalarmengembalikan tipe varchar.CatatanIni merujuk pada tipe data SQL (varchar, bigint, boolean, JSON, array, date), yang berbeda dari tipe data indeks SLS. Gunakan fungsi
typeofuntuk memeriksa tipe data objek SQL. Fungsi typeof. json_extractdapat mengurai sub-struktur apa pun dari objek JSON.json_extract_scalarhanya mengurai node daun skalar (string, Boolean, atau angka) dan mengembalikan string yang sesuai.
Kedua fungsi dapat mengekstrak bidang clientIp dari bidang request.
-
Menggunakan
json_extract:* | SELECT json_extract(request, '$.clientIp')Dalam hasil kueri dan analisis, karena tidak ada alias yang diatur, nama kolom menampilkan nilai default
_col0, yang berisi nilaiclientIpyang diekstrak olehjson_extract. -
Menggunakan
json_extract_scalar:* | SELECT json_extract_scalar(request, '$.clientIp')Setelah menjalankan pernyataan kueri di atas, hasil kueri menampilkan nilai bidang yang diekstrak dalam satu kolom
_col0.
Untuk mengekstrak oktet pertama dari nilai clientIp, gunakan json_extract_scalar untuk mengekstrak clientIp, lalu gunakan split_part untuk mengekstrak angka pertama. json_extract tidak dapat digunakan di sini karena split_part memerlukan input varchar.
* |
SELECT
split_part(
json_extract_scalar(request, '$.clientIp'),
'.',
1
) AS segment

Dalam sebagian besar kasus, gunakan json_extract_scalar — tipe kembaliannya yang berupa varchar dapat digabungkan secara alami dengan fungsi SQL lainnya. Gunakan json_extract saat Anda perlu bekerja dengan struktur JSON itu sendiri. Contohnya, untuk menghitung jumlah orders dalam suatu request (panjang array request.param.orders):
* |
SELECT
json_array_length((json_extract(request, '$.param.orders')))
Dalam hasil kueri dan analisis, kolom _col0 mengembalikan panjang array JSON (yaitu jumlah pesanan) dalam setiap permintaan, dengan nilai contoh 2.
json_extract_scalar mengembalikan tipe varchar. Sebagai contoh, angka 2 dalam hasil sebelumnya bertipe varchar. Untuk melakukan perhitungan seperti penjumlahan, ubah dulu ke tipe bigint menggunakan cast. Fungsi konversi tipe.
Cara mengatur jalur JSON
Saat menggunakan fungsi seperti json_extract, tentukan jalur JSON untuk menargetkan bagian objek JSON yang akan diekstrak. Formatnya adalah $.a.b, di mana $ adalah node akar dan tanda titik (.) merujuk ke node anak.
Untuk nama bidang JSON yang mengandung karakter khusus — seperti http.path, http path, atau http-path — gunakan tanda kurung siku [] alih-alih tanda titik dan sertakan nama bidang dalam tanda kutip ganda. Contoh: * |SELECT json_extract_scalar(request, '$["http.path"]').
Saat melakukan kueri melalui SDK, lakukan escape pada tanda kutip ganda. Contoh: * | select json_extract_scalar(request, '$[\"http.path\"]').
Untuk mengekstrak elemen dari array JSON, gunakan tanda kurung siku [] dengan indeks berbasis nol.
-
Lihat pembayaran untuk pesanan pertama pengguna:
* | SELECT json_extract_scalar(request, '$.param.orders[0].payment')Tabel hasil kueri menunjukkan dua baris di kolom
_col0, keduanya dengan nilai132. -
Lihat produk kedua yang dibeli dalam pesanan pertama pengguna:
* | SELECT json_extract_scalar(request, '$.param.orders[0].commodity[1]')Kolom
_col0mengembalikan dua catatan, keduanya dengan nilaimilk.
Cara menganalisis array JSON
Untuk menganalisis array JSON, gabungkan cast dengan klausa UNNEST untuk memperluas array, lalu agregasikan hasilnya.
Contoh 1
Untuk menghitung total pembayaran dari semua pesanan yang berhasil:
-
Filter permintaan yang berhasil dan ekstrak bidang orders menggunakan
json_extract.* and response: SUCCESS | SELECT json_extract(request, '$.param.orders')_col0 [{"commodity":["bread","milk","meat"],"payment":132},{"commodity":["milk","beer","rice"],"payment":49}] [{"commodity":["bread","milk","meat"],"payment":132},{"commodity":["milk","beer","rice"],"payment":49}] -
Konversi array JSON ke tipe array.
* and response: SUCCESS | SELECT cast( json_extract(request, '$.param.orders') AS array(json) )_col0 ["{"commodity":["bread","milk","meat"],"payment":132}","{"commodity":["milk","beer","rice"],"payment":49}"] ["{"commodity":["bread","milk","meat"],"payment":132}","{"commodity":["milk","beer","rice"],"payment":49}"] -
Gunakan
UNNESTuntuk memperluas array menjadi baris-baris individual.* and response: SUCCESS | SELECT orderinfo FROM log, unnest( cast( json_extract(request, '$.param.orders') AS array(json) ) ) AS t(orderinfo)Hasil kueri dan analisis:
orderinfo {"commodity":["milk","beer","rice"],"payment":49} {"commodity":["milk","beer","rice"],"payment":49} -
Ekstrak nilai payment menggunakan
json_extract_scalar, ubah ke bigint, lalu jumlahkan.* and response: SUCCESS | SELECT sum( cast( json_extract_scalar(orderinfo, '$.payment') AS bigint ) ) FROM log, unnest( cast( json_extract(request, '$.param.orders') AS array(json) ) ) AS t(orderinfo)Hasil yang dikembalikan adalah
10860.
Contoh 2
Untuk menghitung jumlah setiap produk di semua permintaan yang berhasil: ekstrak bidang orders, cast ke array(json), dan perluas dengan UNNEST — setiap baris adalah sebuah pesanan. Ekstrak bidang commodity, cast dan perluas lagi — setiap baris adalah sebuah produk. Kelompokkan dan hitung.
*
and response: SUCCESS |
SELECT
item,
count(1) AS cnt
FROM (
SELECT
orderinfo
FROM log,
unnest(
cast(
json_extract(request, '$.param.orders') AS array(json)
)
) AS t(orderinfo)
),
unnest(
cast(
json_extract(orderinfo, '$.commodity') AS array(json)
)
) AS t(item)
GROUP BY
item
ORDER BY
cnt DESC
Hasil kueri berisi dua kolom: item dan cnt. Statistik jumlah pembelian tiap komoditas adalah:
"milk": 120
"bread": 60
"rice": 60
"beer": 60
"meat": 60