diff --git a/pkg/ottl/e2e/e2e_test.go b/pkg/ottl/e2e/e2e_test.go index cab539369016..d0c1d1e2ca29 100644 --- a/pkg/ottl/e2e/e2e_test.go +++ b/pkg/ottl/e2e/e2e_test.go @@ -5,6 +5,7 @@ package e2e import ( "context" + "net/http" "testing" "time" @@ -335,6 +336,628 @@ func Test_e2e_converters(t *testing.T) { tCtx.GetLogRecord().Attributes().PutStr("A|B|C", "something") }, }, + { + statement: `set(attributes["test"], Base64Decode("cGFzcw=="))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], Decode("cGFzcw==", "base64"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], Concat(["A","B"], ":"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "A:B") + }, + }, + { + statement: `set(attributes["test"], ConvertCase(attributes["http.method"], "upper"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", http.MethodGet) + }, + }, + { + statement: `set(attributes["test"], ConvertCase("PASS", "lower"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], ConvertCase("fooBar", "snake"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "foo_bar") + }, + }, + { + statement: `set(attributes["test"], ConvertCase("foo_bar", "camel"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "FooBar") + }, + }, + { + statement: `set(attributes["test"], ConvertAttributesToElementsXML("This is a log message!"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", `This is a log message!1`) + }, + }, + { + statement: `set(body, ConvertTextToElementsXML("foo"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Body().SetStr("foo") + }, + }, + { + statement: `set(body, ConvertTextToElementsXML("foobar", "/a", "custom"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Body().SetStr("foobar") + }, + }, + { + statement: `set(attributes["test"], Double(1.0))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 1.0) + }, + }, + { + statement: `set(attributes["test"], Double("1"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 1.0) + }, + }, + { + statement: `set(attributes["test"], Double(true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 1.0) + }, + }, + { + statement: `set(attributes["test"], Double(1))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 1.0) + }, + }, + { + statement: `set(attributes["test"], "pass") where Time("10", "%M") - Time("01", "%M") < Duration("10m")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], ExtractPatterns("aa123bb", "(?P\\d+)"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("numbers", "123") + }, + }, + { + statement: `set(attributes["test"], ExtractGrokPatterns("http://user:password@example.com:80/path?query=string", "%{ELB_URI}", true))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("url.scheme", "http") + m.PutStr("url.username", "user") + m.PutStr("url.domain", "example.com") + m.PutInt("url.port", 80) + m.PutStr("url.path", "/path") + m.PutStr("url.query", "query=string") + }, + }, + { + statement: `set(attributes["test"], FNV("pass"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 266877920130663416) + }, + }, + { + statement: `set(attributes["test"], Format("%03d-%s", [7, "test"]))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "007-test") + }, + }, + { + statement: `set(attributes["test"], Hour(Time("12", "%H")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 12) + }, + }, + { + statement: `set(attributes["test"], Hours(Duration("90m")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 1.5) + }, + }, + { + statement: `set(attributes["test"], InsertXML("", "/a", ""))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "") + }, + }, + { + statement: `set(attributes["test"], Int(1.0))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1) + }, + }, + { + statement: `set(attributes["test"], Int("1"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1) + }, + }, + { + statement: `set(attributes["test"], Int(true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1) + }, + }, + { + statement: `set(attributes["test"], Int(1))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1) + }, + }, + { + statement: `set(attributes["test"], GetXML("12", "/a//b"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "12") + }, + }, + { + statement: `set(attributes["test"], Hex(1.0))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "3ff0000000000000") + }, + }, + { + statement: `set(attributes["test"], Hex(true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "01") + }, + }, + { + statement: `set(attributes["test"], Hex(12))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "000000000000000c") + }, + }, + { + statement: `set(attributes["test"], Hex("12"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "3132") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsBool(false)`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsDouble(1.0)`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsMap(attributes["foo"])`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsList(attributes["foo"]["slice"])`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsMatch("aa123bb", "\\d{3}")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsString("")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], Len(attributes["foo"]))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 4) + }, + }, + { + statement: `set(attributes["test"], Log(1))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 0) + }, + }, + { + statement: `set(attributes["test"], MD5("pass"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "1a1dc91c907325c69271ddf0c944bc72") + }, + }, + { + statement: `set(attributes["test"], Microseconds(Duration("1ms")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1000) + }, + }, + { + statement: `set(attributes["test"], Milliseconds(Duration("1s")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1000) + }, + }, + { + statement: `set(attributes["test"], Minutes(Duration("1h")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 60) + }, + }, + { + statement: `set(attributes["test"], Nanoseconds(Duration("1ms")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutInt("test", 1000000) + }, + }, + { + statement: `set(attributes["test"], "pass") where Now() - Now() < Duration("1h")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], ParseCSV("val1;val2;val3","header1|header2|header3",";","|","strict"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("header1", "val1") + m.PutStr("header2", "val2") + m.PutStr("header3", "val3") + }, + }, + { + statement: `set(attributes["test"], ParseCSV("val1,val2,val3","header1|header2|header3",headerDelimiter="|",mode="strict"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("header1", "val1") + m.PutStr("header2", "val2") + m.PutStr("header3", "val3") + }, + }, + { + statement: `set(attributes["test"], ParseJSON("{\"id\":1}"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutDouble("id", 1) + }, + }, + { + statement: `set(attributes["test"], ParseJSON("[\"value1\",\"value2\"]"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + m.AppendEmpty().SetStr("value1") + m.AppendEmpty().SetStr("value2") + }, + }, + { + statement: `set(attributes["test"], ParseKeyValue("k1=v1 k2=v2"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("k1", "v1") + m.PutStr("k2", "v2") + }, + }, + { + statement: `set(attributes["test"], ParseKeyValue("k1!v1_k2!v2", "!", "_"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("k1", "v1") + m.PutStr("k2", "v2") + }, + }, + { + statement: `set(attributes["test"], ParseKeyValue("k1!v1_k2!\"v2__!__v2\"", "!", "_"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("k1", "v1") + m.PutStr("k2", "v2__!__v2") + }, + }, + { + statement: `set(attributes["test"], ToKeyValueString(ParseKeyValue("k1=v1 k2=v2"), "=", " ", true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "k1=v1 k2=v2") + }, + }, + { + statement: `set(attributes["test"], ToKeyValueString(ParseKeyValue("k1:v1,k2:v2", ":" , ","), ":", ",", true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "k1:v1,k2:v2") + }, + }, + { + statement: `set(attributes["test"], ToKeyValueString(ParseKeyValue("k1=v1 k2=v2"), "!", "+", true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "k1!v1+k2!v2") + }, + }, + { + statement: `set(attributes["test"], ToKeyValueString(ParseKeyValue("k1=v1 k2=v2=v3"), "=", " ", true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "k1=v1 k2=\"v2=v3\"") + }, + }, + { + statement: `set(attributes["test"], ParseSimplifiedXML("1This is a log message!"))`, + want: func(tCtx ottllog.TransformContext) { + attr := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + log := attr.PutEmptyMap("Log") + log.PutStr("id", "1") + log.PutStr("Message", "This is a log message!") + }, + }, + { + statement: `set(attributes["test"], ParseXML("This is a log message!"))`, + want: func(tCtx ottllog.TransformContext) { + log := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + log.PutStr("tag", "Log") + + attrs := log.PutEmptyMap("attributes") + attrs.PutStr("id", "1") + + logChildren := log.PutEmptySlice("children") + + message := logChildren.AppendEmpty().SetEmptyMap() + message.PutStr("tag", "Message") + message.PutStr("content", "This is a log message!") + }, + }, + { + statement: `set(attributes["test"], RemoveXML("This is a log message!", "/Log/Message"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", ``) + }, + }, + { + statement: `set(attributes["test"], Seconds(Duration("1m")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutDouble("test", 60) + }, + }, + { + statement: `set(attributes["test"], SHA1("pass"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684") + }, + }, + { + statement: `set(attributes["test"], SHA256("pass"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "d74ff0ee8da3b9806b18c877dbf29bbde50b5bd8e4dad7a3a725000feb82e8f1") + }, + }, + { + statement: `set(attributes["test"], SHA512("pass"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "5b722b307fce6c944905d132691d5e4a2214b7fe92b738920eb3fce3a90420a19511c3010a0e7712b054daef5b57bad59ecbd93b3280f210578f547f4aed4d25") + }, + }, + { + statement: `set(attributes["test"], Sort(Split(attributes["flags"], "|"), "desc"))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetStr("C") + s.AppendEmpty().SetStr("B") + s.AppendEmpty().SetStr("A") + }, + }, + { + statement: `set(attributes["test"], Sort([true, false, false]))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetBool(false) + s.AppendEmpty().SetBool(false) + s.AppendEmpty().SetBool(true) + }, + }, + { + statement: `set(attributes["test"], Sort([3, 6, 9], "desc"))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetInt(9) + s.AppendEmpty().SetInt(6) + s.AppendEmpty().SetInt(3) + }, + }, + { + statement: `set(attributes["test"], Sort([Double(1.5), Double(10.2), Double(2.3), Double(0.5)]))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetDouble(0.5) + s.AppendEmpty().SetDouble(1.5) + s.AppendEmpty().SetDouble(2.3) + s.AppendEmpty().SetDouble(10.2) + }, + }, + { + statement: `set(attributes["test"], Sort([Int(11), Double(2.2), Double(-1)]))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetDouble(-1) + s.AppendEmpty().SetDouble(2.2) + s.AppendEmpty().SetInt(11) + }, + }, + { + statement: `set(attributes["test"], Sort([false, Int(11), Double(2.2), "three"]))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetInt(11) + s.AppendEmpty().SetDouble(2.2) + s.AppendEmpty().SetBool(false) + s.AppendEmpty().SetStr("three") + }, + }, + { + statement: `set(span_id, SpanID(0x0000000000000000))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().SetSpanID(pcommon.NewSpanIDEmpty()) + }, + }, + { + statement: `set(attributes["test"], Split(attributes["flags"], "|"))`, + want: func(tCtx ottllog.TransformContext) { + s := tCtx.GetLogRecord().Attributes().PutEmptySlice("test") + s.AppendEmpty().SetStr("A") + s.AppendEmpty().SetStr("B") + s.AppendEmpty().SetStr("C") + }, + }, + { + statement: `set(attributes["test"], String("test"))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "test") + }, + }, + { + statement: `set(attributes["test"], String(attributes["http.method"]))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "get") + }, + }, + { + statement: `set(attributes["test"], String(span_id))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "[1,2,3,4,5,6,7,8]") + }, + }, + { + statement: `set(attributes["test"], String([1,2,3]))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "[1,2,3]") + }, + }, + { + statement: `set(attributes["test"], String(true))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "true") + }, + }, + { + statement: `set(attributes["test"], Substring("pass", 0, 2))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pa") + }, + }, + { + statement: `set(trace_id, TraceID(0x00000000000000000000000000000000))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().SetTraceID(pcommon.NewTraceIDEmpty()) + }, + }, + { + statement: `set(time, TruncateTime(time, Duration("1s")))`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().SetTimestamp(pcommon.NewTimestampFromTime(TestLogTimestamp.AsTime().Truncate(time.Second))) + }, + }, + { + statement: `set(attributes["test"], "pass") where UnixMicro(time) > 0`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where UnixMilli(time) > 0`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where UnixNano(time) > 0`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where UnixSeconds(time) > 0`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "pass") where IsString(UUID())`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "pass") + }, + }, + { + statement: `set(attributes["test"], "\\")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "\\") + }, + }, + { + statement: `set(attributes["test"], "\\\\")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "\\\\") + }, + }, + { + statement: `set(attributes["test"], "\\\\\\")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "\\\\\\") + }, + }, + { + statement: `set(attributes["test"], "\\\\\\\\")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", "\\\\\\\\") + }, + }, + { + statement: `set(attributes["test"], "\"")`, + want: func(tCtx ottllog.TransformContext) { + tCtx.GetLogRecord().Attributes().PutStr("test", `"`) + }, + }, + { + statement: `keep_keys(attributes["foo"], ["\\", "bar"])`, + want: func(tCtx ottllog.TransformContext) { + // keep_keys should see two arguments + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("foo") + m.PutStr("bar", "pass") + }, + }, + { + statement: `set(attributes["test"], UserAgent("curl/7.81.0"))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + m.PutStr("user_agent.original", "curl/7.81.0") + m.PutStr("user_agent.name", "curl") + m.PutStr("user_agent.version", "7.81.0") + }, + }, + { + statement: `set(attributes["test"], SliceToMap(attributes["things"], ["name"]))`, + want: func(tCtx ottllog.TransformContext) { + m := tCtx.GetLogRecord().Attributes().PutEmptyMap("test") + thing1 := m.PutEmptyMap("foo") + thing1.PutStr("name", "foo") + thing1.PutInt("value", 2) + + thing2 := m.PutEmptyMap("bar") + thing2.PutStr("name", "bar") + thing2.PutInt("value", 5) + }, + }, } for _, tt := range tests {