@@ -226,6 +226,15 @@ func Test_e2e_editors(t *testing.T) {
226
226
m2 .PutStr ("test" , "pass" )
227
227
},
228
228
},
229
+ {
230
+ statement : `merge_maps(attributes, {"map_literal": {"list": [{"foo":"bar"}, "test"]}}, "upsert")` ,
231
+ want : func (tCtx ottllog.TransformContext ) {
232
+ mapAttr := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("map_literal" )
233
+ l := mapAttr .PutEmptySlice ("list" )
234
+ l .AppendEmpty ().SetEmptyMap ().PutStr ("foo" , "bar" )
235
+ l .AppendEmpty ().SetStr ("test" )
236
+ },
237
+ },
229
238
{
230
239
statement : `replace_all_matches(attributes, "*/*", "test")` ,
231
240
want : func (tCtx ottllog.TransformContext ) {
@@ -1125,6 +1134,48 @@ func Test_e2e_converters(t *testing.T) {
1125
1134
m .PutInt ("bar" , 5 )
1126
1135
},
1127
1136
},
1137
+ {
1138
+ statement : `set(attributes["test"], {"list":[{"foo":"bar"}]})` ,
1139
+ want : func (tCtx ottllog.TransformContext ) {
1140
+ m := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("test" )
1141
+ m2 := m .PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ()
1142
+ m2 .PutStr ("foo" , "bar" )
1143
+ },
1144
+ },
1145
+ {
1146
+ statement : `set(attributes, {"list":[{"foo":"bar"}]})` ,
1147
+ want : func (tCtx ottllog.TransformContext ) {
1148
+ tCtx .GetLogRecord ().Attributes ().Clear ()
1149
+ m2 := tCtx .GetLogRecord ().Attributes ().PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ()
1150
+ m2 .PutStr ("foo" , "bar" )
1151
+ },
1152
+ },
1153
+ {
1154
+ statement : `set(attributes["arr"], [{"list":[{"foo":"bar"}]}, {"bar":"baz"}])` ,
1155
+ want : func (tCtx ottllog.TransformContext ) {
1156
+ arr := tCtx .GetLogRecord ().Attributes ().PutEmptySlice ("arr" )
1157
+ arr .AppendEmpty ().SetEmptyMap ().PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ().PutStr ("foo" , "bar" )
1158
+ arr .AppendEmpty ().SetEmptyMap ().PutStr ("bar" , "baz" )
1159
+ },
1160
+ },
1161
+ {
1162
+ statement : `set(attributes["test"], IsList([{"list":[{"foo":"bar"}]}, {"bar":"baz"}]))` ,
1163
+ want : func (tCtx ottllog.TransformContext ) {
1164
+ tCtx .GetLogRecord ().Attributes ().PutBool ("test" , true )
1165
+ },
1166
+ },
1167
+ {
1168
+ statement : `set(attributes["test"], IsMap({"list":[{"foo":"bar"}]}))` ,
1169
+ want : func (tCtx ottllog.TransformContext ) {
1170
+ tCtx .GetLogRecord ().Attributes ().PutBool ("test" , true )
1171
+ },
1172
+ },
1173
+ {
1174
+ statement : `set(attributes["test"], Len([{"list":[{"foo":"bar"}]}, {"bar":"baz"}]))` ,
1175
+ want : func (tCtx ottllog.TransformContext ) {
1176
+ tCtx .GetLogRecord ().Attributes ().PutInt ("test" , 2 )
1177
+ },
1178
+ },
1128
1179
}
1129
1180
1130
1181
for _ , tt := range tests {
@@ -1268,41 +1319,176 @@ func Test_e2e_ottl_features(t *testing.T) {
1268
1319
}
1269
1320
}
1270
1321
1322
+ func Test_e2e_ottl_statement_sequence (t * testing.T ) {
1323
+ tests := []struct {
1324
+ name string
1325
+ statements []string
1326
+ want func (tCtx ottllog.TransformContext )
1327
+ }{
1328
+ {
1329
+ name : "delete key of map literal" ,
1330
+ statements : []string {
1331
+ `set(attributes["test"], {"foo":"bar", "list":[{"test":"hello"}]})` ,
1332
+ `delete_key(attributes["test"], "foo")` ,
1333
+ },
1334
+ want : func (tCtx ottllog.TransformContext ) {
1335
+ m := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("test" )
1336
+ m .PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ().PutStr ("test" , "hello" )
1337
+ },
1338
+ },
1339
+ {
1340
+ name : "delete matching keys of map literal" ,
1341
+ statements : []string {
1342
+ `set(attributes["test"], {"foo":"bar", "list":[{"test":"hello"}]})` ,
1343
+ `delete_matching_keys(attributes["test"], ".*oo")` ,
1344
+ },
1345
+ want : func (tCtx ottllog.TransformContext ) {
1346
+ m := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("test" )
1347
+ m .PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ().PutStr ("test" , "hello" )
1348
+ },
1349
+ },
1350
+ {
1351
+ name : "keep matching keys of map literal" ,
1352
+ statements : []string {
1353
+ `set(attributes["test"], {"foo":"bar", "list":[{"test":"hello"}]})` ,
1354
+ `keep_matching_keys(attributes["test"], ".*ist")` ,
1355
+ },
1356
+ want : func (tCtx ottllog.TransformContext ) {
1357
+ m := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("test" )
1358
+ m .PutEmptySlice ("list" ).AppendEmpty ().SetEmptyMap ().PutStr ("test" , "hello" )
1359
+ },
1360
+ },
1361
+ {
1362
+ name : "flatten map literal" ,
1363
+ statements : []string {
1364
+ `set(attributes["test"], {"foo":"bar", "list":[{"test":"hello"}]})` ,
1365
+ `flatten(attributes["test"])` ,
1366
+ },
1367
+ want : func (tCtx ottllog.TransformContext ) {
1368
+ m := tCtx .GetLogRecord ().Attributes ().PutEmptyMap ("test" )
1369
+ m .PutStr ("foo" , "bar" )
1370
+ m .PutStr ("list.0.test" , "hello" )
1371
+ },
1372
+ },
1373
+ }
1374
+
1375
+ for _ , tt := range tests {
1376
+ t .Run (tt .name , func (t * testing.T ) {
1377
+ tCtx := constructLogTransformContext ()
1378
+
1379
+ for _ , statement := range tt .statements {
1380
+ logStatements , err := parseStatementWithAndWithoutPathContext (statement )
1381
+ assert .NoError (t , err )
1382
+
1383
+ for _ , s := range logStatements {
1384
+ _ , _ , _ = s .Execute (context .Background (), tCtx )
1385
+ }
1386
+ }
1387
+
1388
+ exTCtx := constructLogTransformContext ()
1389
+ tt .want (exTCtx )
1390
+
1391
+ assert .NoError (t , plogtest .CompareResourceLogs (newResourceLogs (exTCtx ), newResourceLogs (tCtx )))
1392
+ })
1393
+ }
1394
+ }
1395
+
1271
1396
func Test_e2e_ottl_value_expressions (t * testing.T ) {
1272
1397
tests := []struct {
1273
1398
name string
1274
1399
statement string
1275
- want any
1400
+ want func () any
1276
1401
}{
1277
1402
{
1278
1403
name : "string literal" ,
1279
1404
statement : `"foo"` ,
1280
- want : "foo" ,
1405
+ want : func () any {
1406
+ return "foo"
1407
+ },
1281
1408
},
1282
1409
{
1283
1410
name : "attribute value" ,
1284
1411
statement : `resource.attributes["host.name"]` ,
1285
- want : "localhost" ,
1412
+ want : func () any {
1413
+ return "localhost"
1414
+ },
1286
1415
},
1287
1416
{
1288
1417
name : "accessing enum" ,
1289
1418
statement : `SEVERITY_NUMBER_TRACE` ,
1290
- want : int64 (1 ),
1419
+ want : func () any {
1420
+ return int64 (1 )
1421
+ },
1291
1422
},
1292
1423
{
1293
1424
name : "Using converter" ,
1294
1425
statement : `TraceID(0x0102030405060708090a0b0c0d0e0f10)` ,
1295
- want : pcommon.TraceID {0x1 , 0x2 , 0x3 , 0x4 , 0x5 , 0x6 , 0x7 , 0x8 , 0x9 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf , 0x10 },
1426
+ want : func () any {
1427
+ return pcommon.TraceID {0x1 , 0x2 , 0x3 , 0x4 , 0x5 , 0x6 , 0x7 , 0x8 , 0x9 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf , 0x10 }
1428
+ },
1296
1429
},
1297
1430
{
1298
1431
name : "Adding results of two converter operations" ,
1299
1432
statement : `Len(attributes) + Len(attributes)` ,
1300
- want : int64 (24 ),
1433
+ want : func () any {
1434
+ return int64 (28 )
1435
+ },
1301
1436
},
1302
1437
{
1303
1438
name : "Nested converter operations" ,
1304
1439
statement : `Hex(Len(attributes) + Len(attributes))` ,
1305
- want : "0000000000000018" ,
1440
+ want : func () any {
1441
+ return "000000000000001c"
1442
+ },
1443
+ },
1444
+ {
1445
+ name : "return map type 1" ,
1446
+ statement : `attributes["foo"]` ,
1447
+ want : func () any {
1448
+ m := pcommon .NewMap ()
1449
+ _ = m .FromRaw (map [string ]any {
1450
+ "bar" : "pass" ,
1451
+ })
1452
+ return m
1453
+ },
1454
+ },
1455
+ {
1456
+ name : "return map type 2" ,
1457
+ statement : `attributes["foo2"]` ,
1458
+ want : func () any {
1459
+ m := pcommon .NewMap ()
1460
+ _ = m .FromRaw (map [string ]any {
1461
+ "slice" : []any {
1462
+ "val" ,
1463
+ },
1464
+ })
1465
+ return m
1466
+ },
1467
+ },
1468
+ {
1469
+ name : "return map type 3" ,
1470
+ statement : `attributes["foo3"]` ,
1471
+ want : func () any {
1472
+ m := pcommon .NewMap ()
1473
+ _ = m .FromRaw (map [string ]any {
1474
+ "nested" : map [string ]any {
1475
+ "test" : "pass" ,
1476
+ },
1477
+ })
1478
+ return m
1479
+ },
1480
+ },
1481
+ {
1482
+ name : "return list" ,
1483
+ statement : `attributes["things"]` ,
1484
+ want : func () any {
1485
+ s := pcommon .NewSlice ()
1486
+ _ = s .FromRaw ([]any {
1487
+ map [string ]any {"name" : "foo" },
1488
+ map [string ]any {"name" : "bar" },
1489
+ })
1490
+ return s
1491
+ },
1306
1492
},
1307
1493
}
1308
1494
@@ -1314,11 +1500,11 @@ func Test_e2e_ottl_value_expressions(t *testing.T) {
1314
1500
valueExpr , err := logParser .ParseValueExpression (tt .statement )
1315
1501
assert .NoError (t , err )
1316
1502
1317
- tCtx := constructLogTransformContext ()
1503
+ tCtx := constructLogTransformContextValueExpressions ()
1318
1504
val , err := valueExpr .Eval (context .Background (), tCtx )
1319
1505
assert .NoError (t , err )
1320
1506
1321
- assert .Equal (t , tt .want , val )
1507
+ assert .Equal (t , tt .want () , val )
1322
1508
})
1323
1509
}
1324
1510
}
@@ -1526,6 +1712,58 @@ func constructLogTransformContextEditors() ottllog.TransformContext {
1526
1712
return ottllog .NewTransformContext (logRecord , scope , resource , plog .NewScopeLogs (), plog .NewResourceLogs ())
1527
1713
}
1528
1714
1715
+ func constructLogTransformContextValueExpressions () ottllog.TransformContext {
1716
+ resource := pcommon .NewResource ()
1717
+ resource .Attributes ().PutStr ("host.name" , "localhost" )
1718
+ resource .Attributes ().PutStr ("A|B|C" , "newValue" )
1719
+
1720
+ scope := pcommon .NewInstrumentationScope ()
1721
+ scope .SetName ("scope" )
1722
+
1723
+ logRecord := plog .NewLogRecord ()
1724
+ logRecord .Body ().SetStr ("operationA" )
1725
+ logRecord .SetTimestamp (TestLogTimestamp )
1726
+ logRecord .SetObservedTimestamp (TestObservedTimestamp )
1727
+ logRecord .SetDroppedAttributesCount (1 )
1728
+ logRecord .SetFlags (plog .DefaultLogRecordFlags .WithIsSampled (true ))
1729
+ logRecord .SetSeverityNumber (1 )
1730
+ logRecord .SetTraceID (traceID )
1731
+ logRecord .SetSpanID (spanID )
1732
+ logRecord .Attributes ().PutStr ("http.method" , "get" )
1733
+ logRecord .Attributes ().PutStr ("http.path" , "/health" )
1734
+ logRecord .Attributes ().PutStr ("http.url" , "http://localhost/health" )
1735
+ logRecord .Attributes ().PutStr ("flags" , "A|B|C" )
1736
+ logRecord .Attributes ().PutStr ("total.string" , "123456789" )
1737
+ logRecord .Attributes ().PutStr ("A|B|C" , "something" )
1738
+ logRecord .Attributes ().PutStr ("foo" , "foo" )
1739
+ logRecord .Attributes ().PutStr ("slice" , "slice" )
1740
+ logRecord .Attributes ().PutStr ("val" , "val2" )
1741
+ logRecord .Attributes ().PutInt ("int_value" , 0 )
1742
+ arr := logRecord .Attributes ().PutEmptySlice ("array" )
1743
+ arr0 := arr .AppendEmpty ()
1744
+ arr0 .SetStr ("looong" )
1745
+ m := logRecord .Attributes ().PutEmptyMap ("foo" )
1746
+ m .PutStr ("bar" , "pass" )
1747
+
1748
+ m2 := logRecord .Attributes ().PutEmptyMap ("foo2" )
1749
+ s := m2 .PutEmptySlice ("slice" )
1750
+ v := s .AppendEmpty ()
1751
+ v .SetStr ("val" )
1752
+
1753
+ m3 := logRecord .Attributes ().PutEmptyMap ("foo3" )
1754
+ m31 := m3 .PutEmptyMap ("nested" )
1755
+ m31 .PutStr ("test" , "pass" )
1756
+
1757
+ s2 := logRecord .Attributes ().PutEmptySlice ("things" )
1758
+ thing1 := s2 .AppendEmpty ().SetEmptyMap ()
1759
+ thing1 .PutStr ("name" , "foo" )
1760
+
1761
+ thing2 := s2 .AppendEmpty ().SetEmptyMap ()
1762
+ thing2 .PutStr ("name" , "bar" )
1763
+
1764
+ return ottllog .NewTransformContext (logRecord , scope , resource , plog .NewScopeLogs (), plog .NewResourceLogs ())
1765
+ }
1766
+
1529
1767
func constructSpanTransformContext () ottlspan.TransformContext {
1530
1768
resource := pcommon .NewResource ()
1531
1769
0 commit comments