diff --git a/network/ws/epoll_linux.go b/network/ws/epoll_linux.go index bb40098a..121e3434 100644 --- a/network/ws/epoll_linux.go +++ b/network/ws/epoll_linux.go @@ -3,6 +3,7 @@ // This product includes software developed at Guance Cloud (https://www.guance.com/). // Copyright 2021-present Guance, Inc. +//go:build linux // +build linux package ws @@ -90,7 +91,7 @@ func (e *epoll) Close() error { return err } - //if err := e.Remove(c); err != nil { + // if err := e.Remove(c); err != nil { // l.Errorf("e.Remove(): %s", err.Error()) // return err //} diff --git a/pipeline/ptinput/funcs/all.go b/pipeline/ptinput/funcs/all.go index c6413d19..868fe60e 100644 --- a/pipeline/ptinput/funcs/all.go +++ b/pipeline/ptinput/funcs/all.go @@ -77,6 +77,7 @@ var FuncsMap = map[string]runtime.FuncCall{ "create_point": CreatePoint, "parse_int": ParseInt, "format_int": FormatInt, + "pt_name": PtName, // disable "json_all": JSONAll, } @@ -141,6 +142,7 @@ var FuncsCheckMap = map[string]runtime.FuncCheck{ "create_point": CreatePointChecking, "parse_int": ParseIntChecking, "format_int": FormatIntChecking, + "pt_name": PtNameChecking, // disable "json_all": JSONAllChecking, } diff --git a/pipeline/ptinput/funcs/all_doc.go b/pipeline/ptinput/funcs/all_doc.go index 4d48b49e..59cfd716 100644 --- a/pipeline/ptinput/funcs/all_doc.go +++ b/pipeline/ptinput/funcs/all_doc.go @@ -76,6 +76,7 @@ var PipelineFunctionDocs = map[string]*PLDoc{ "create_point()": &createPointMarkdown, "parse_int()": &parseIntMarkdown, "format_int()": &formatIntMarkdown, + "pt_name()": &ptNameMarkdown, } var PipelineFunctionDocsEN = map[string]*PLDoc{ @@ -136,6 +137,7 @@ var PipelineFunctionDocsEN = map[string]*PLDoc{ "create_point()": &createPointMarkdownEN, "parse_int()": &parseIntMarkdownEN, "format_int()": &formatIntMarkdownEN, + "pt_name()": &ptNameMarkdownEN, } // embed docs. @@ -311,6 +313,9 @@ var ( //go:embed md/format_int.md docFormatInt string + + //go:embed md/pt_name.md + docPtName string ) const ( @@ -685,4 +690,11 @@ var ( langTagZhCN: {cStringOp}, }, } + + ptNameMarkdown = PLDoc{ + Doc: docPtName, + FnCategory: map[string][]string{ + langTagZhCN: {cOther}, + }, + } ) diff --git a/pipeline/ptinput/funcs/all_doc_en.go b/pipeline/ptinput/funcs/all_doc_en.go index b4152e96..2027184c 100644 --- a/pipeline/ptinput/funcs/all_doc_en.go +++ b/pipeline/ptinput/funcs/all_doc_en.go @@ -182,6 +182,9 @@ var ( //go:embed md/format_int.en.md docFormatIntEN string + + //go:embed md/pt_name.en.md + docPtNameEN string ) const ( @@ -559,4 +562,11 @@ var ( langTagEnUS: {eStringOp}, }, } + + ptNameMarkdownEN = PLDoc{ + Doc: docPtNameEN, + FnCategory: map[string][]string{ + langTagEnUS: {eOther}, + }, + } ) diff --git a/pipeline/ptinput/funcs/fn_pt_name.go b/pipeline/ptinput/funcs/fn_pt_name.go new file mode 100644 index 00000000..e03ce969 --- /dev/null +++ b/pipeline/ptinput/funcs/fn_pt_name.go @@ -0,0 +1,31 @@ +package funcs + +import ( + "fmt" + + "github.com/GuanceCloud/platypus/pkg/ast" + "github.com/GuanceCloud/platypus/pkg/engine/runtime" + "github.com/GuanceCloud/platypus/pkg/errchain" +) + +func PtNameChecking(ctx *runtime.Context, funcExpr *ast.CallExpr) *errchain.PlError { + if len(funcExpr.Param) > 1 { + return runtime.NewRunError(ctx, fmt.Sprintf( + "func `%s' can have at most one parameter", funcExpr.Name), funcExpr.NamePos) + } + + return nil +} + +func PtName(ctx *runtime.Context, funcExpr *ast.CallExpr) *errchain.PlError { + if len(funcExpr.Param) == 1 { + if val, _, err := runtime.RunStmt(ctx, funcExpr.Param[0]); err == nil { + if val, ok := val.(string); ok { + _ = setPtName(ctx.InData(), val) + } + } + } + + ctx.Regs.ReturnAppend(getPtName(ctx.InData()), ast.String) + return nil +} diff --git a/pipeline/ptinput/funcs/fn_pt_name_test.go b/pipeline/ptinput/funcs/fn_pt_name_test.go new file mode 100644 index 00000000..47286fa7 --- /dev/null +++ b/pipeline/ptinput/funcs/fn_pt_name_test.go @@ -0,0 +1,122 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package funcs + +import ( + "testing" + "time" + + "github.com/GuanceCloud/cliutils/pipeline/ptinput" + "github.com/GuanceCloud/cliutils/point" + "github.com/stretchr/testify/assert" +) + +func TestPtName(t *testing.T) { + defatultPtName := "default" + + cases := []struct { + name, pl, in string + out string + expect string + fail bool + }{ + { + name: "pt_name_set_and_get", + in: `162.62.81.1 - - [29/Nov/2021:07:30:50 +0000] "123 /?signature=b8d8ea×tamp=1638171049 HTTP/1.1" 200 413 "-" "Mozilla/4.0"`, + pl: ` + set_tag(client_ip) + grok(_, "%{IPORHOST:client_ip} %{NOTSPACE} %{NOTSPACE} \\[%{HTTPDATE:time}\\] \"%{DATA:data} %{GREEDYDATA} HTTP/%{NUMBER}\" %{INT:status_code} %{INT:bytes}") + cast(data, "int") + add_key("pt_name",pt_name(client_ip)) + + `, + out: "pt_name", + expect: "162.62.81.1", + fail: false, + }, + { + name: "pt_name_set_str_and_get", + in: `162.62.81.1 - - [29/Nov/2021:07:30:50 +0000] "123 /?signature=b8d8ea×tamp=1638171049 HTTP/1.1" 200 413 "-" "Mozilla/4.0"`, + pl: ` + set_tag(client_ip) + grok(_, "%{IPORHOST:client_ip} %{NOTSPACE} %{NOTSPACE} \\[%{HTTPDATE:time}\\] \"%{DATA:data} %{GREEDYDATA} HTTP/%{NUMBER}\" %{INT:status_code} %{INT:bytes}") + cast(data, "int") + add_key("pt_name", pt_name("aa")) + + `, + out: "pt_name", + expect: "aa", + fail: false, + }, + { + name: "pt_name_set_int_1_and_get", + in: `162.62.81.1 - - [29/Nov/2021:07:30:50 +0000] "123 /?signature=b8d8ea×tamp=1638171049 HTTP/1.1" 200 413 "-" "Mozilla/4.0"`, + pl: ` + set_tag(client_ip) + grok(_, "%{IPORHOST:client_ip} %{NOTSPACE} %{NOTSPACE} \\[%{HTTPDATE:time}\\] \"%{DATA:data} %{GREEDYDATA} HTTP/%{NUMBER}\" %{INT:status_code} %{INT:bytes}") + cast(data, "int") + add_key("pt_name",pt_name(1)) + + `, + out: "pt_name", + expect: defatultPtName, + fail: false, + }, + { + name: "pt_name_set_int_var_and_get", + in: `162.62.81.1 - - [29/Nov/2021:07:30:50 +0000] "123 /?signature=b8d8ea×tamp=1638171049 HTTP/1.1" 200 413 "-" "Mozilla/4.0"`, + pl: ` + set_tag(client_ip) + grok(_, "%{IPORHOST:client_ip} %{NOTSPACE} %{NOTSPACE} \\[%{HTTPDATE:time}\\] \"%{DATA:data} %{GREEDYDATA} HTTP/%{NUMBER}\" %{INT:status_code} %{INT:bytes}") + cast(data, "int") + a=1 + add_key("pt_name",pt_name(aa)) + `, + out: "pt_name", + expect: defatultPtName, + fail: false, + }, + { + name: "pt_name_get", + in: `162.62.81.1 - - [29/Nov/2021:07:30:50 +0000] "123 /?signature=b8d8ea×tamp=1638171049 HTTP/1.1" 200 413 "-" "Mozilla/4.0"`, + pl: ` + grok(_, "%{IPORHOST:client_ip} %{NOTSPACE} %{NOTSPACE} \\[%{HTTPDATE:time}\\] \"%{DATA:data} %{GREEDYDATA} HTTP/%{NUMBER}\" %{INT:status_code} %{INT:bytes}") + set_tag(client_ip) + cast(data, "int") + add_key("pt_name", pt_name()) + `, + out: "pt_name", + expect: defatultPtName, + fail: false, + }, + } + + for idx, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + runner, err := NewTestingRunner(tc.pl) + if err != nil { + if tc.fail { + t.Logf("[%d]expect error: %s", idx, err) + } else { + t.Errorf("[%d] failed: %s", idx, err) + } + return + } + pt := ptinput.NewPlPoint( + point.Logging, defatultPtName, nil, map[string]any{"message": tc.in}, time.Now()) + errR := runScript(runner, pt) + + if errR != nil { + t.Fatal(errR.Error()) + } + + _, _, ok := pt.GetWithIsTag(tc.out) + assert.True(t, ok) + assert.Equal(t, tc.expect, pt.GetPtName()) + t.Logf("[%d] PASS", idx) + }) + } +} diff --git a/pipeline/ptinput/funcs/fn_set_measurement.go b/pipeline/ptinput/funcs/fn_set_measurement.go index b3f5a9ca..f9368588 100644 --- a/pipeline/ptinput/funcs/fn_set_measurement.go +++ b/pipeline/ptinput/funcs/fn_set_measurement.go @@ -46,7 +46,7 @@ func SetMeasurement(ctx *runtime.Context, funcExpr *ast.CallExpr) *errchain.PlEr } if dtype == ast.String { if val, ok := val.(string); ok { - _ = setMeasurement(ctx.InData(), val) + _ = setPtName(ctx.InData(), val) } } diff --git a/pipeline/ptinput/funcs/md/pt_name.en.md b/pipeline/ptinput/funcs/md/pt_name.en.md new file mode 100644 index 00000000..c5c8523e --- /dev/null +++ b/pipeline/ptinput/funcs/md/pt_name.en.md @@ -0,0 +1,24 @@ +### `pt_name()` {#fn-pt-name} + +Function prototype: `fn pt_name(name: str = "") -> str` + +Function description: Get the name of point; if the parameter is not empty, set the new name. + +Function parameters: + +- `name`: Value as point name; defaults to empty string. + +The field mapping relationship between point name and various types of data storage: + +| category | field name | +| ------------- | ---------- | +| custom_object | class | +| keyevent | - | +| logging | source | +| metric | - | +| network | source | +| object | class | +| profiling | source | +| rum | source | +| security | rule | +| tracing | source | diff --git a/pipeline/ptinput/funcs/md/pt_name.md b/pipeline/ptinput/funcs/md/pt_name.md new file mode 100644 index 00000000..afd49407 --- /dev/null +++ b/pipeline/ptinput/funcs/md/pt_name.md @@ -0,0 +1,24 @@ +### `pt_name()` {#fn-pt-name} + +函数原型:`fn pt_name(name: str = "") -> str` + +函数说明:获取 point 的 name;如果参数不为空则设置新的 name。 + +函数参数: + +- `name`: 值作为 point name;默认值为空字符串 + +Point Name 与各个类型数据存储时的字段映射关系: + +| 类别 | 字段名 | +| ------------- | ------ | +| custom_object | class | +| keyevent | - | +| logging | source | +| metric | - | +| network | source | +| object | class | +| profiling | source | +| rum | source | +| security | rule | +| tracing | source | diff --git a/pipeline/ptinput/funcs/utils.go b/pipeline/ptinput/funcs/utils.go index 731cb9c2..a8943b2e 100644 --- a/pipeline/ptinput/funcs/utils.go +++ b/pipeline/ptinput/funcs/utils.go @@ -325,7 +325,7 @@ func renamePtKey(in any, to, from string) error { return pt.RenameKey(from, to) } -func setMeasurement(in any, val string) error { +func setPtName(in any, val string) error { pt, err := getPoint(in) if err != nil { return err @@ -334,6 +334,14 @@ func setMeasurement(in any, val string) error { return nil } +func getPtName(in any) string { + pt, err := getPoint(in) + if err != nil { + return "" + } + return pt.GetPtName() +} + func markPtDrop(in any) error { pt, err := getPoint(in) if err != nil {