全部產品
Search
文件中心

Simple Log Service:調用函數清洗資料

更新時間:Jul 26, 2024

您可以通過Log Service資料加工函數清洗您所採集的海量日誌資料,實現資料格式標準化。本文介紹調用函數清洗資料的常見情境和相關操作。

情境1:過濾日誌(e_keep函數和e_drop函數)

您可以使用e_drop函數或e_keep函數過濾日誌,也可以使用e_if函數與DROP參數、e_if_else函數與DROP參數過濾日誌。

常用規則如下所示:

  • e_keep(e_search(...) ):滿足條件時保留,不滿足條件時丟棄。

  • e_drop(e_search(...) ):滿足條件時丟棄,不滿足條件時保留。

  • e_if_else(e_search("..."), KEEP, DROP):滿足條件時保留,不滿足條件時丟棄。

  • e_if(e_search("not ..."), DROP):滿足條件時丟棄,不滿足條件時保留。

  • e_if(e_search("..."), KEEP):無意義的加工規則。

樣本如下所示:

  • 原始日誌

    #日誌1
    __source__:  192.168.0.1
    __tag__:__client_ip__:  192.168.0.2
    __tag__:__receive_time__:  1597214851
    __topic__: app 
    class:  test_case
    id:  7992
    test_string:  <function test1 at 0x1027401e0>
    
    #日誌2
    __source__:  192.168.0.1
    class:  produce_case
    id:  7990
    test_string:  <function test1 at 0x1020401e0>
  • 加工規則

    丟棄沒有__topic__欄位和__tag__:__receive_time__欄位的日誌。

    e_if(e_not_has("__topic__"),e_drop())
    e_if(e_not_has("__tag__:__receive_time__"),e_drop())
  • 加工結果

    __source__:  192.168.0.1
    __tag__:__client_ip__:  192.168.0.2
    __tag__:__receive_time__:  1597214851
    __topic__: app 
    class:  test_case
    id:  7992
    test_string:  <function test1 at 0x1027401e0>

情境2:為日誌空缺欄位賦值(e_set函數)

您可以使用e_set函數為日誌空缺欄位賦值。

  • 子情境1:原欄位不存在或者為空白時,為欄位賦值。

    e_set("result", "......value......", mode="fill")

    mode參數取值請參見欄位提取檢查與覆蓋模式

    樣本如下所示:

    • 原始日誌

      name:
    • 加工規則

      e_set("name", "aspara2.0", mode="fill")
    • 加工結果

      name:  aspara2.0
  • 子情境2:使用GROK函數簡化Regex,提取欄位內容。

    樣本如下所示:

    • 原始日誌

      content:"ip address: 192.168.1.1"
    • 加工規則

      使用GROK函數捕獲提取content欄位中的IP地址。

      e_regex("content", grok(r"(%{IP})"),"addr")
    • 加工結果

      addr:  192.168.1.1
      content:"ip address: 192.168.1.1"
  • 子情境3:為多個欄位賦值。

    e_set("k1", "v1", "k2", "v2", "k3", "v3", ......)

    樣本如下所示:

    • 原始日誌

      __source__:  192.168.0.1
      __topic__:
      __tag__:
      __receive_time__:
      id:  7990
      test_string:  <function test1 at 0x1020401e0>
    • 加工規則

      __topic__欄位、__tag__欄位和__receive_time__欄位賦值。

      e_set("__topic__","app", "__tag__","stu","__receive_time__","1597214851")
    • 加工結果

      __source__:  192.168.0.1
      __topic__:  app
      __tag__:  stu
      __receive_time__:  1597214851
      id:  7990
      test_string:  <function test1 at 0x1020401e0>

情境3:通過判斷,刪除和重新命名欄位(e_search函數、e_rename函數和e_compose函數)

一般情況下,推薦您使用e_compose函數進行重複判斷和操作。

樣本如下所示:

  • 原始日誌

    content:123
    age:23
    name:twiss
  • 加工規則

    首先判斷content欄位值是否為123,如果是,則刪除agename欄位,再將content欄位重新命名為ctx

    e_if(e_search("content==123"),e_compose(e_drop_fields("age|name"), e_rename("content", "ctx")))
  • 加工結果

    ctx: 123

情境4:轉換日誌參數類型(v函數、cn_int函數和dt_totimestamp函數)

日誌的欄位和欄位值在加工過程中,始終都是字串形式,非字串類型的資料會被自動轉化為字串類型。因此在調用函數時,要注意各個函數能接收的參數類型。更多資訊,請參見文法簡介

  • 子情境1:調用op_add函數進行字元拼接和資料相加。

    op_add函數既可以接收字串類型,也可以接受數實值型別,因此不需要做參數類型轉換。

    樣本如下所示:

    • 原始日誌

      a : 1
      b : 2
    • 加工規則

      e_set("d",op_add(v("a"), v("b")))
      e_set("e",op_add(ct_int(v("a")), ct_int(v("b"))))
    • 加工結果

      a:1
      b:2
      d:12
      e:3
  • 子情境2:運用欄位操作函數ct_int函數進行類型轉換並調用op_mul函數進行資料相乘。

    樣本如下所示:

    • 原始日誌

      a:2
      b:5
    • 加工規則

      因為v("a")和v("b")都是字串類型,而op_mul函數的第二個參數只能接收數實值型別,所以您需要通過ct_int函數將字串轉化為整型,再傳遞給op_mul函數。

      e_set("c",op_mul(ct_int(v("a")), ct_int(v("b"))))
      e_set("d",op_mul(v("a"), ct_int(v("b"))))
    • 加工結果

      a: 2
      b: 5
      c: 10
      d: 22222
  • 子情境3:調用dt_parse函數和dt_parsetimestamp函數將字串或日期時間轉換為標準時間。

    dt_totimestamp函數接收的參數類型為日期時間對象,不是字串。因此需要調用dt_parse函數將time1的字串實值型別轉化為日期時間物件類型。您也可以直接使用dt_parsetimestamp函數,它既能接收日期時間對象,也能接收字串。更多資訊,請參見日期時間函數

    樣本如下所示:

    • 原始日誌

      time1: 2020-09-17 9:00:00
    • 加工規則

      time1表示的日期時間轉化為Unix時間戳記。

      e_set("time1", "2019-06-03 2:41:26")
      e_set("time2", dt_totimestamp(dt_parse(v("time1")))) 或 e_set("time2", dt_parsetimestamp(v("time1"))) 
    • 加工結果

      time1:  2019-06-03 2:41:26 
      time2:  1559529686 

情境5:為日誌不存在的欄位填充預設值(default傳參)

部分SLS DSL運算式函數對輸入的參數有一定要求,如果不滿足,資料加工視窗會報錯或返回預設值。當日誌中存在必要而殘缺欄位時,您可以在op_len函數中填充預設值。

重要

傳遞預設值給後續的函數時可能會進一步報錯,因而需要及時處理函數返回的異常。

  • 原始日誌

    data_len: 1024
  • 加工規則

    e_set("data_len", op_len(v("data", default="")))
  • 加工結果

    data: 0
    data_len: 0

情境6:判斷日誌並增加欄位(e_if函數與e_switch函數)

推薦使用e_if函數或e_switch函數進行日誌判斷。更多資訊,請參見流程式控制制函數

  • e_if函數

    e_if(條件1, 操作1, 條件2, 操作2, 條件3, 操作3, ....)
  • e_switch函數

    e_switch函數是條件與操作的配對組合。依次根據條件進行判斷,滿足條件的進行對應操作,然後直接返回操作結果。不滿足條件的不進行對應操作,直接進行下一個條件判斷。如果沒有滿足任一條件並且配置了default參數,則執行default配置的操作並返回。

    e_switch(條件1, 操作1, 條件2, 操作2, 條件3, 操作3, ...., default=None)

樣本如下所示:

  • 原始日誌

    status1: 200
    status2: 404
  • e_if函數

    • 加工規則

      e_if(e_match("status1", "200"), e_set("status1_info", "normal"),
           e_match("status2", "404"), e_set("status2_info", "error"))
    • 加工結果

      status1: 200
      status2: 404
      status1_info: normal
      status2_info: error
  • e_switch函數

    • 加工規則

      e_switch(e_match("status1", "200"), e_set("status1_info", "normal"), 
               e_match("status2", "404"), e_set("status2_info", "error"))
    • 加工結果

      只要有一個條件滿足,就返回結果,不再進行後續條件判斷。

      status1: 200
      status2: 404
      status1_info: normal

情境7:資料轉化納秒級的Unix時間戳記

部分情境需要Log Service的資料加工能夠滿足納秒級精度時間戳記的需求,當原始日誌中存在Unix時間格式欄位,您可以使用欄位操作函數,將其解析成納秒精度的日誌時間。

  • 原始日誌

    {
      "__source__": "1.2.3.4",
      "__time__": 1704983810,
      "__topic__": "test",
      "log_time_nano":"1705043680630940602"
    }
  • 加工規則

    e_set(
        "__time__", op_div_floor(ct_int(v("log_time_nano")), 1000000000),
    )
    e_set(
        "__time_ns_part__", op_mod(ct_int(v("log_time_nano")), 1000000000),
    )
  • 加工結果

    {
      "__source__": "1.2.3.4",
      "__time__": 1705043680,
      "__time_ns_part__": 630940602,
      "__topic__": "test",
      "log_time_nano":"1705043680630940602"
    }

情境8:資料轉化微秒級標準 ISO8601 時間戳記

部分情境需要Log Service的資料加工滿足高精度時間戳記的需求,當原始日誌中存在標準 ISO8601時間格式的欄位,您可以使用欄位操作函數,將其解析成微秒精度的日誌時間。

  • 原始日誌

    {
      "__source__": "1.2.3.4",
      "__time__": 1704983810,
      "__topic__": "test",
      "log_time":"2024-01-11 23:10:43.992847200"
    }
  • 加工規則

    e_set(
        "__time__", dt_parsetimestamp(v("log_time"), tz="Asia/Shanghai"), mode="overwrite",
    )
    e_set("tmp_ms", dt_prop(v("log_time"), "microsecond"))
    e_set(
        "__time_ns_part__", op_mul(ct_int(v("tmp_ms")), 1000),
    )
  • 加工結果

    {
      "__source__": "1.2.3.4",
      "__time__": 1704985843,
      "__time_ns_part__": 992847000,
      "__topic__": "test",
      "log_time": "2024-01-11 23:10:43.992847200",
      "tmp_ms": "992847"
    }