Processing Complex JSON Data
This section describes how to use LTS's data processing feature to handle complex JSON data.
Processing Complex JSON Data with Multiple Sub-keys as Arrays
Logs generated by applications are written in a statistical JSON format. Generally, these logs contain basic information and multiple sub-keys structured as arrays. For example, a server writes a log every minute, including its current information status and the statistics of its related servers and client nodes.
- Example log
{ "content":{ "service": "search_service", "overall_status": "yellow", "servers": [ { "host": "192.0.2.1", "status": "green" }, { "host": "192.0.2.2", "status": "green" } ], "clients": [ { "host": "192.0.2.3", "status": "green" }, { "host": "192.0.2.4", "status": "red" } ] } } - Processing requirements
- Split the raw log into three topics: overall_type, client_status, and server_status.
- Retain different information for each topic:
- overall_type: retains the count of servers and clients, overall_status color, and service information.
- client_status: retains the host address, status, and service information.
- server_status: retains the host address, status, and service information.
- Solution: The following describes how to use the processing syntax. The syntax in 1 to 7 must be used together.
- Split the log into three distinct entries by assigning them different topic values. Following the split, you will have three logs containing identical information, differentiated only by their respective topic fields.
e_set("topic", "server_status,client_status,overall_type") e_split("topic")The log format after processing:
topic: server_status // The other two logs are marked as client_status and overall_type respectively; other parameters remain identical. content: { ...Same as above... } - Expand the JSON content. The content field is expanded at the first layer, and the original content field is deleted.
e_json('content',depth=1) e_drop_fields("content")Log format after processing:
topic: overall_type // The other two logs are marked as client_status and server_status respectively; other parameters remain identical. clients: [{"host": "192.0.2.3", "status": "green"}, {"host": "192.0.2.4", "status": "red"}] overall_status: yellow servers: [{"host": "192.0.2.1", "status": "green"}, {"host": "192.0.2.2", "status": "green"}] service: search_service - For the log whose topic is overall_type, collect statistics for client_count and server_count.
e_if(e_search("topic==overall_type"), e_compose( e_set("client_count", json_select(v("clients"), "length([*])", default=0)), e_set("server_count", json_select(v("servers"), "length([*])", default=0)) ))Log after processing:
topic: overall_type server_count: 2 client_count: 2
- Discard fields:
e_if(e_search("topic==overall_type"), e_drop_fields("clients", "servers")) - Further split the log whose topic is server_status.
e_if(e_search("topic==server_status"), e_split("servers")) e_if(e_search("topic==server_status"), e_json("servers", depth=1))Split log 1 after further splitting:
topic: server_status servers: {"host": "192.0.2.1", "status": "green"} host: 192.0.2.1 status: greenSplit log 2 after further splitting:
topic: server_status servers: {"host": "192.0.2.2", "status": "green"} host: 192.0.2.2 status: green - Retain relevant fields:
e_if(e_search("topic==server_status"), e_compose(e_drop_fields("servers"),e_drop_fields("clients"))) - Further split the log whose topic is client_status and delete unnecessary fields.
e_if(e_search("topic==client_status"), e_split("clients")) e_if(e_search("topic==client_status"), e_json("clients", depth=1))Split log 1 after further splitting:
topic: client_status host: 192.0.2.3 status: green
Split log 2 after further splitting:
topic: clients host: 192.0.2.4 status: red
- The preceding syntax is combined as follows:
# Overall splitting e_set("topic", "server_status,client_status,overall_type") e_split("topic") e_json('content',depth=1) e_drop_fields("content") # Process the overall_type log. e_if(e_search("topic==overall_type"), e_compose( e_set("client_count", json_select(v("clients"), "length([*])", default=0)), e_set("server_count", json_select(v("servers"), "length([*])", default=0)) )) e_if(e_search("topic==overall_type"), e_drop_fields("clients", "servers")) # Process the server_status log. e_if(e_search("topic==server_status"), e_split("servers")) e_if(e_search("topic==server_status"), e_json("servers", depth=1)) e_if(e_search("topic==server_status"), e_compose(e_drop_fields("servers"),e_drop_fields("clients"))) # Process the client_status log. e_if(e_search("topic==client_status"), e_split("clients")) e_if(e_search("topic==client_status"), e_json("clients", depth=1)) e_if(e_search("topic==client_status"), e_compose(e_drop_fields("servers"),e_drop_fields("clients")))Processing result:
{ "content":{ "service": "search_service", "overall_status": "yellow", "servers": [ { "host": "192.0.2.1", "status": "green" }, { "host": "192.0.2.2", "status": "green" } ], "clients": [ { "host": "192.0.2.3", "status": "green" }, { "host": "192.0.2.4", "status": "red" } ] } }
- Split the log into three distinct entries by assigning them different topic values. Following the split, you will have three logs containing identical information, differentiated only by their respective topic fields.
Processing Complex JSON Data with Multi-Layer Array Object Nesting
Take a complex JSON object with multi-layer nested arrays as an example. Split each individual login record in login_histories of each object under users into a separate login event.
- Raw log
{ "content":{ "users": [ { "name": "user1", "login_histories": [ { "date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6" }, { "date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6" }, { ...More login information... } ] }, { "name": "user2", "login_histories": [ { "date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7" }, { "date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9" }, { ...More login information... } ] }, { ...More users... } ] } } - Expected split logs
name: user1 date: 2019-10-11 1:0:0 login_ip: 192.0.2.6 name: user1 date: 2019-10-11 0:0:0 login_ip: 192.0.2.6 name: user2 date: 2019-10-11 0:0:0 login_ip: 192.0.2.7 name: user2 date: 2019-10-11 1:0:0 login_ip: 192.0.2.9 ...More logs...
- Solution
- Split and expand the users array in the content field.
e_split("content", jmes='users[*]', output='item') e_json("item",depth=1)Logs returned after processing:content:{...Same as above...} item: {"name": "user1", "login_histories": [{"date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6"}, {"date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6"}]} login_histories: [{"date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6"}, {"date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6"}] name: user1 content:{...Same as above...} item: {"name": "user2", "login_histories": [{"date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7"}, {"date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9"}]} login_histories: [{"date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7"}, {"date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9"}] name: user2 - Split and expand login_histories.
e_split("login_histories") e_json("login_histories", depth=1)Logs returned after processing:
content: {...Same as above...} date: 2019-10-11 0:0:0 item: {"name": "user2", "login_histories": [{"date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7"}, {"date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9"}]} login_histories: {"date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7"} login_ip: 192.0.2.7 name: user2 content: {...Same as above...} date: 2019-10-11 1:0:0 item: {"name": "user2", "login_histories": [{"date": "2019-10-11 0:0:0", "login_ip": "192.0.2.7"}, {"date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9"}]} login_histories: {"date": "2019-10-11 1:0:0", "login_ip": "192.0.2.9"} login_ip: 192.0.2.9 name: user2 content: {...Same as above...} date: 2019-10-10 1:0:0 item: {"name": "user1", "login_histories": [{"date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6"}, {"date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6"}]} login_histories: {"date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6"} login_ip: 192.0.2.6 name: user1 content: {...Same as above...} date: 2019-10-10 0:0:0 item: {"name": "user1", "login_histories": [{"date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6"}, {"date": "2019-10-10 1:0:0", "login_ip": "192.0.2.6"}]} login_histories: {"date": "2019-10-10 0:0:0", "login_ip": "192.0.2.6"} login_ip: 192.0.2.6 name: user1 - Delete irrelevant fields.
e_drop_fields("content", "item", "login_histories")Logs returned after processing:
{ "date": "2019-10-10 0:0:0", "name": "user1", "login_ip": "192.0.2.6" } { "date": "2019-10-10 1:0:0", "name": "user1", "login_ip": "192.0.2.6" } { "date": "2019-10-11 0:0:0", "name": "user2", "login_ip": "192.0.2.7" } { "date": "2019-10-11 1:0:0", "name": "user2", "login_ip": "192.0.2.9" } - The preceding DSL rules are combined as follows:
e_split("content", jmes='users[*]', output='item') e_json("item",depth=1) e_split("login_histories") e_json("login_histories", depth=1) e_drop_fields("content", "item", "login_histories")Summary: To meet the preceding requirements, the rules sequentially perform the splitting and expanding operations, and delete irrelevant information.
- Split and expand the users array in the content field.
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot