diff --git a/CHANGELOG.md b/CHANGELOG.md
index f895db85e97..299cc75faf3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
* [CHANGE] Update Go to 1.22.4 [#3757](https://github.com/grafana/tempo/pull/3757) [#3793](https://github.com/grafana/tempo/pull/3793) (@joe-elliott, @mapno)
* [CHANGE] Make vParquet4 the default block encoding [#3810](https://github.com/grafana/tempo/pull/3810) (@ie-pham)
* [FEATURE] TraceQL support for link scope and link:traceID and link:spanID [#3741](https://github.com/grafana/tempo/pull/3741) (@stoewer)
+* [FEATURE] TraceQL support for link attribute querying [#3814](https://github.com/grafana/tempo/pull/3814) (@ie-pham)
* [FEATURE] TraceQL support for event scope and event:name intrinsic [#3708](https://github.com/grafana/tempo/pull/3708) (@stoewer)
* [FEATURE] TraecQL support for event attributes [#3708](https://github.com/grafana/tempo/pull/3748) (@ie-pham)
* [FEATURE] Flush and query RF1 blocks for TraceQL metric queries [#3628](https://github.com/grafana/tempo/pull/3628) [#3691](https://github.com/grafana/tempo/pull/3691) [#3723](https://github.com/grafana/tempo/pull/3723) (@mapno)
diff --git a/docs/sources/tempo/traceql/_index.md b/docs/sources/tempo/traceql/_index.md
index 6c410f28770..f41c18f9a0d 100644
--- a/docs/sources/tempo/traceql/_index.md
+++ b/docs/sources/tempo/traceql/_index.md
@@ -110,7 +110,7 @@ This example searches all Kubernetes clusters called `service-name` that have a
### Attribute fields
-TraceQL has three different attribute scopes: span attributes, resource attributes, and event attributes. By expanding a span in the Grafana UI, you can see both its span attributes (1 in the screenshot) and resource attributes (2 in the screenshot).
+TraceQL has four different attribute scopes: span attributes, resource attributes, event attributes, and link attributes. By expanding a span in the Grafana UI, you can see both its span attributes (1 in the screenshot) and resource attributes (2 in the screenshot).
![Example of span and resource attributes.](assets/span-resource-attributes.png)
@@ -142,6 +142,11 @@ You can query for an exception in your span event:
{ event.exception.message =~ ".*something went wrong.*" }
```
+You can search for an attribute in your link:
+```
+{ link.opentracing.ref_type = "child_of" }
+```
+
### Unscoped attribute fields
Attributes can be unscoped if you are unsure if the requested attribute exists on the span or resource.
diff --git a/pkg/parquetquery/iters_test.go b/pkg/parquetquery/iters_test.go
index 71f0c0473d9..cec4e081a01 100644
--- a/pkg/parquetquery/iters_test.go
+++ b/pkg/parquetquery/iters_test.go
@@ -33,8 +33,8 @@ func TestNext(t *testing.T) {
rn2 := RowNumber{0, 0, 0, 0, 0, 0, 0, 0}
for i := 0; i < 1000; i++ {
- r := rand.Intn(MaxDefinitionLevel)
- d := rand.Intn(MaxDefinitionLevel)
+ r := rand.Intn(MaxDefinitionLevel + 1)
+ d := rand.Intn(MaxDefinitionLevel + 1)
rn1.Next(r, d)
rn2.nextSlow(r, d)
diff --git a/pkg/traceql/expr.y b/pkg/traceql/expr.y
index 4c5aa59e5cd..bbb905264ef 100644
--- a/pkg/traceql/expr.y
+++ b/pkg/traceql/expr.y
@@ -94,7 +94,7 @@ import (
KIND_UNSPECIFIED KIND_INTERNAL KIND_SERVER KIND_CLIENT KIND_PRODUCER KIND_CONSUMER
IDURATION CHILDCOUNT NAME STATUS STATUS_MESSAGE PARENT KIND ROOTNAME ROOTSERVICENAME
ROOTSERVICE TRACEDURATION NESTEDSETLEFT NESTEDSETRIGHT NESTEDSETPARENT ID TRACE_ID SPAN_ID
- PARENT_DOT RESOURCE_DOT SPAN_DOT TRACE_COLON SPAN_COLON EVENT_COLON EVENT_DOT LINK_COLON
+ PARENT_DOT RESOURCE_DOT SPAN_DOT TRACE_COLON SPAN_COLON EVENT_COLON EVENT_DOT LINK_COLON LINK_DOT
COUNT AVG MAX MIN SUM
BY COALESCE SELECT
END_ATTRIBUTE
@@ -419,4 +419,5 @@ attributeField:
| PARENT_DOT RESOURCE_DOT IDENTIFIER END_ATTRIBUTE { $$ = NewScopedAttribute(AttributeScopeResource, true, $3) }
| PARENT_DOT SPAN_DOT IDENTIFIER END_ATTRIBUTE { $$ = NewScopedAttribute(AttributeScopeSpan, true, $3) }
| EVENT_DOT IDENTIFIER END_ATTRIBUTE { $$ = NewScopedAttribute(AttributeScopeEvent, false, $2) }
+ | LINK_DOT IDENTIFIER END_ATTRIBUTE { $$ = NewScopedAttribute(AttributeScopeLink, false, $2) }
;
diff --git a/pkg/traceql/expr.y.go b/pkg/traceql/expr.y.go
index a1e6c539321..52bb44396ad 100644
--- a/pkg/traceql/expr.y.go
+++ b/pkg/traceql/expr.y.go
@@ -103,51 +103,52 @@ const SPAN_COLON = 57390
const EVENT_COLON = 57391
const EVENT_DOT = 57392
const LINK_COLON = 57393
-const COUNT = 57394
-const AVG = 57395
-const MAX = 57396
-const MIN = 57397
-const SUM = 57398
-const BY = 57399
-const COALESCE = 57400
-const SELECT = 57401
-const END_ATTRIBUTE = 57402
-const RATE = 57403
-const COUNT_OVER_TIME = 57404
-const QUANTILE_OVER_TIME = 57405
-const HISTOGRAM_OVER_TIME = 57406
-const COMPARE = 57407
-const WITH = 57408
-const PIPE = 57409
-const AND = 57410
-const OR = 57411
-const EQ = 57412
-const NEQ = 57413
-const LT = 57414
-const LTE = 57415
-const GT = 57416
-const GTE = 57417
-const NRE = 57418
-const RE = 57419
-const DESC = 57420
-const ANCE = 57421
-const SIBL = 57422
-const NOT_CHILD = 57423
-const NOT_PARENT = 57424
-const NOT_DESC = 57425
-const NOT_ANCE = 57426
-const UNION_CHILD = 57427
-const UNION_PARENT = 57428
-const UNION_DESC = 57429
-const UNION_ANCE = 57430
-const UNION_SIBL = 57431
-const ADD = 57432
-const SUB = 57433
-const NOT = 57434
-const MUL = 57435
-const DIV = 57436
-const MOD = 57437
-const POW = 57438
+const LINK_DOT = 57394
+const COUNT = 57395
+const AVG = 57396
+const MAX = 57397
+const MIN = 57398
+const SUM = 57399
+const BY = 57400
+const COALESCE = 57401
+const SELECT = 57402
+const END_ATTRIBUTE = 57403
+const RATE = 57404
+const COUNT_OVER_TIME = 57405
+const QUANTILE_OVER_TIME = 57406
+const HISTOGRAM_OVER_TIME = 57407
+const COMPARE = 57408
+const WITH = 57409
+const PIPE = 57410
+const AND = 57411
+const OR = 57412
+const EQ = 57413
+const NEQ = 57414
+const LT = 57415
+const LTE = 57416
+const GT = 57417
+const GTE = 57418
+const NRE = 57419
+const RE = 57420
+const DESC = 57421
+const ANCE = 57422
+const SIBL = 57423
+const NOT_CHILD = 57424
+const NOT_PARENT = 57425
+const NOT_DESC = 57426
+const NOT_ANCE = 57427
+const UNION_CHILD = 57428
+const UNION_PARENT = 57429
+const UNION_DESC = 57430
+const UNION_ANCE = 57431
+const UNION_SIBL = 57432
+const ADD = 57433
+const SUB = 57434
+const NOT = 57435
+const MUL = 57436
+const DIV = 57437
+const MOD = 57438
+const POW = 57439
var yyToknames = [...]string{
"$end",
@@ -201,6 +202,7 @@ var yyToknames = [...]string{
"EVENT_COLON",
"EVENT_DOT",
"LINK_COLON",
+ "LINK_DOT",
"COUNT",
"AVG",
"MAX",
@@ -258,158 +260,160 @@ var yyExca = [...]int{
-1, 1,
1, -1,
-2, 0,
- -1, 286,
+ -1, 288,
13, 86,
-2, 94,
}
const yyPrivate = 57344
-const yyLast = 948
+const yyLast = 959
var yyAct = [...]int{
- 101, 5, 100, 6, 99, 8, 223, 7, 274, 98,
- 12, 67, 18, 13, 284, 2, 242, 90, 224, 94,
- 77, 322, 200, 70, 66, 19, 20, 21, 30, 17,
- 29, 287, 150, 332, 151, 331, 154, 315, 152, 229,
- 230, 312, 231, 232, 233, 242, 231, 232, 233, 242,
- 180, 182, 183, 184, 185, 186, 187, 188, 189, 190,
- 191, 192, 193, 194, 195, 196, 197, 319, 311, 310,
- 309, 23, 26, 24, 25, 27, 14, 318, 15, 85,
- 86, 206, 87, 88, 89, 90, 72, 73, 199, 74,
- 75, 76, 77, 227, 359, 226, 346, 225, 214, 216,
- 217, 218, 219, 220, 221, 87, 88, 89, 90, 199,
- 22, 222, 336, 335, 265, 245, 246, 247, 74, 75,
- 76, 77, 243, 244, 234, 235, 236, 237, 238, 239,
- 241, 240, 243, 244, 234, 235, 236, 237, 238, 239,
- 241, 240, 329, 204, 229, 230, 364, 231, 232, 233,
- 242, 251, 266, 267, 229, 230, 337, 231, 232, 233,
- 242, 368, 281, 200, 269, 270, 271, 272, 367, 291,
- 363, 291, 356, 291, 282, 234, 235, 236, 237, 238,
- 239, 241, 240, 281, 19, 20, 21, 338, 17, 17,
- 160, 181, 252, 253, 328, 229, 230, 324, 231, 232,
- 233, 242, 150, 255, 151, 323, 154, 268, 152, 203,
- 256, 362, 257, 286, 355, 291, 352, 258, 353, 354,
- 85, 86, 288, 87, 88, 89, 90, 351, 350, 282,
- 23, 26, 24, 25, 27, 14, 161, 15, 342, 155,
- 156, 157, 158, 159, 339, 340, 204, 320, 321, 292,
- 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
- 303, 304, 305, 306, 307, 341, 19, 20, 21, 22,
- 17, 259, 160, 260, 262, 263, 283, 261, 280, 227,
- 227, 226, 226, 225, 225, 264, 279, 67, 278, 67,
- 277, 327, 227, 276, 226, 207, 225, 325, 326, 70,
- 163, 70, 288, 78, 79, 80, 81, 82, 83, 148,
- 330, 147, 23, 26, 24, 25, 27, 14, 161, 15,
- 290, 291, 146, 85, 86, 145, 87, 88, 89, 90,
- 333, 150, 334, 151, 144, 154, 143, 152, 92, 91,
- 84, 17, 227, 227, 226, 226, 225, 225, 348, 349,
- 366, 22, 71, 227, 361, 226, 347, 225, 28, 360,
- 140, 141, 142, 227, 275, 226, 314, 225, 313, 365,
- 102, 103, 104, 108, 131, 254, 93, 95, 358, 357,
- 107, 105, 106, 110, 109, 111, 112, 113, 114, 115,
- 116, 117, 118, 119, 120, 121, 122, 124, 123, 125,
- 126, 250, 127, 128, 129, 130, 202, 345, 344, 134,
- 132, 133, 136, 137, 138, 135, 139, 317, 273, 102,
- 103, 104, 108, 131, 249, 248, 95, 343, 69, 107,
- 105, 106, 110, 109, 111, 112, 113, 114, 115, 116,
- 117, 118, 119, 120, 121, 122, 124, 123, 125, 126,
- 16, 127, 128, 129, 130, 316, 96, 97, 134, 132,
- 133, 136, 137, 138, 135, 139, 308, 4, 149, 10,
- 153, 1, 243, 244, 234, 235, 236, 237, 238, 239,
- 241, 240, 0, 72, 73, 0, 74, 75, 76, 77,
- 0, 0, 0, 0, 229, 230, 289, 231, 232, 233,
- 242, 0, 0, 0, 228, 96, 97, 0, 0, 0,
- 243, 244, 234, 235, 236, 237, 238, 239, 241, 240,
- 0, 243, 244, 234, 235, 236, 237, 238, 239, 241,
- 240, 0, 229, 230, 0, 231, 232, 233, 242, 0,
- 0, 0, 0, 229, 230, 0, 231, 232, 233, 242,
- 0, 243, 244, 234, 235, 236, 237, 238, 239, 241,
- 240, 243, 244, 234, 235, 236, 237, 238, 239, 241,
- 240, 201, 0, 229, 230, 0, 231, 232, 233, 242,
- 0, 0, 0, 229, 230, 0, 231, 232, 233, 242,
- 78, 79, 80, 81, 82, 83, 198, 78, 79, 80,
- 81, 82, 83, 0, 0, 0, 0, 0, 0, 0,
- 85, 86, 0, 87, 88, 89, 90, 72, 73, 0,
- 74, 75, 76, 77, 0, 0, 48, 53, 0, 0,
- 50, 0, 49, 0, 57, 0, 51, 52, 54, 55,
- 56, 59, 58, 60, 61, 64, 63, 62, 0, 0,
- 0, 31, 36, 0, 0, 33, 0, 32, 0, 42,
- 0, 34, 35, 37, 38, 39, 40, 41, 43, 44,
- 45, 46, 47, 48, 53, 0, 0, 50, 0, 49,
+ 101, 5, 100, 6, 99, 8, 224, 7, 276, 98,
+ 12, 67, 18, 13, 286, 2, 243, 90, 225, 94,
+ 77, 325, 201, 70, 66, 230, 231, 30, 232, 233,
+ 234, 243, 151, 29, 152, 200, 155, 200, 153, 85,
+ 86, 335, 87, 88, 89, 90, 232, 233, 234, 243,
+ 181, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 322, 72, 73,
+ 334, 74, 75, 76, 77, 318, 317, 321, 314, 313,
+ 312, 207, 87, 88, 89, 90, 74, 75, 76, 77,
+ 332, 311, 201, 228, 362, 227, 349, 226, 215, 217,
+ 218, 219, 220, 221, 222, 339, 338, 268, 269, 267,
+ 367, 223, 252, 370, 293, 246, 247, 248, 340, 366,
+ 293, 17, 371, 244, 245, 235, 236, 237, 238, 239,
+ 240, 242, 241, 244, 245, 235, 236, 237, 238, 239,
+ 240, 242, 241, 68, 11, 230, 231, 341, 232, 233,
+ 234, 243, 331, 253, 254, 230, 231, 327, 232, 233,
+ 234, 243, 326, 283, 270, 271, 272, 273, 274, 359,
+ 293, 358, 293, 356, 357, 284, 235, 236, 237, 238,
+ 239, 240, 242, 241, 283, 19, 20, 21, 17, 17,
+ 182, 161, 277, 354, 353, 204, 230, 231, 365, 232,
+ 233, 234, 243, 151, 355, 152, 345, 155, 344, 153,
+ 342, 343, 323, 324, 288, 206, 209, 210, 211, 212,
+ 213, 214, 285, 290, 282, 19, 20, 21, 281, 17,
+ 284, 161, 23, 26, 24, 25, 27, 14, 162, 15,
+ 205, 156, 157, 158, 159, 160, 369, 205, 292, 293,
+ 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+ 304, 305, 306, 307, 308, 309, 280, 279, 278, 208,
+ 164, 22, 23, 26, 24, 25, 27, 14, 162, 15,
+ 149, 228, 228, 227, 227, 226, 226, 148, 257, 67,
+ 147, 67, 146, 330, 228, 258, 227, 259, 226, 328,
+ 329, 70, 260, 70, 290, 78, 79, 80, 81, 82,
+ 83, 22, 333, 145, 144, 92, 91, 364, 85, 86,
+ 84, 87, 88, 89, 90, 85, 86, 350, 87, 88,
+ 89, 90, 71, 336, 151, 337, 152, 316, 155, 28,
+ 153, 141, 142, 143, 315, 228, 228, 227, 227, 226,
+ 226, 351, 352, 361, 360, 256, 228, 255, 227, 251,
+ 226, 275, 363, 348, 347, 250, 228, 249, 227, 346,
+ 226, 69, 368, 102, 103, 104, 108, 131, 16, 93,
+ 95, 4, 150, 107, 105, 106, 110, 109, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 124, 123, 125, 126, 10, 127, 128, 129, 130, 203,
+ 154, 1, 134, 132, 133, 137, 138, 139, 135, 140,
+ 136, 320, 0, 102, 103, 104, 108, 131, 0, 0,
+ 95, 0, 0, 107, 105, 106, 110, 109, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 124, 123, 125, 126, 0, 127, 128, 129, 130, 319,
+ 96, 97, 134, 132, 133, 137, 138, 139, 135, 140,
+ 136, 310, 0, 0, 0, 0, 0, 244, 245, 235,
+ 236, 237, 238, 239, 240, 242, 241, 72, 73, 0,
+ 74, 75, 76, 77, 0, 0, 0, 0, 0, 230,
+ 231, 291, 232, 233, 234, 243, 0, 0, 0, 229,
+ 96, 97, 0, 0, 0, 244, 245, 235, 236, 237,
+ 238, 239, 240, 242, 241, 0, 0, 244, 245, 235,
+ 236, 237, 238, 239, 240, 242, 241, 230, 231, 0,
+ 232, 233, 234, 243, 0, 0, 0, 0, 0, 230,
+ 231, 0, 232, 233, 234, 243, 0, 244, 245, 235,
+ 236, 237, 238, 239, 240, 242, 241, 244, 245, 235,
+ 236, 237, 238, 239, 240, 242, 241, 202, 0, 230,
+ 231, 0, 232, 233, 234, 243, 0, 0, 0, 230,
+ 231, 0, 232, 233, 234, 243, 78, 79, 80, 81,
+ 82, 83, 199, 78, 79, 80, 81, 82, 83, 0,
+ 0, 0, 0, 0, 0, 0, 85, 86, 0, 87,
+ 88, 89, 90, 72, 73, 0, 74, 75, 76, 77,
+ 0, 0, 0, 48, 53, 0, 0, 50, 0, 49,
0, 57, 0, 51, 52, 54, 55, 56, 59, 58,
- 60, 61, 64, 63, 62, 31, 36, 0, 0, 33,
- 0, 32, 0, 42, 0, 34, 35, 37, 38, 39,
- 40, 41, 43, 44, 45, 46, 47, 19, 20, 21,
- 50, 17, 49, 285, 57, 0, 51, 52, 54, 55,
- 56, 59, 58, 60, 61, 64, 63, 62, 33, 0,
- 32, 0, 42, 0, 34, 35, 37, 38, 39, 40,
- 41, 43, 44, 45, 46, 47, 0, 0, 0, 0,
- 0, 0, 0, 23, 26, 24, 25, 27, 14, 0,
- 15, 19, 20, 21, 0, 17, 0, 9, 0, 19,
- 20, 21, 0, 17, 0, 160, 19, 20, 21, 0,
- 0, 0, 215, 0, 0, 0, 0, 0, 0, 0,
- 68, 11, 22, 0, 0, 65, 3, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 23, 26, 24,
- 25, 27, 14, 0, 15, 23, 26, 24, 25, 27,
- 0, 0, 23, 26, 24, 25, 27, 162, 164, 165,
- 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 0, 0, 22, 0, 0, 0,
- 0, 131, 0, 0, 22, 0, 0, 0, 0, 0,
- 0, 22, 205, 208, 209, 210, 211, 212, 213, 118,
+ 60, 61, 64, 63, 62, 0, 0, 0, 31, 36,
+ 0, 0, 33, 0, 32, 0, 42, 0, 34, 35,
+ 37, 38, 39, 40, 41, 43, 44, 45, 46, 47,
+ 48, 53, 0, 0, 50, 0, 49, 0, 57, 0,
+ 51, 52, 54, 55, 56, 59, 58, 60, 61, 64,
+ 63, 62, 31, 36, 0, 0, 33, 0, 32, 0,
+ 42, 0, 34, 35, 37, 38, 39, 40, 41, 43,
+ 44, 45, 46, 47, 19, 20, 21, 0, 17, 0,
+ 289, 0, 19, 20, 21, 50, 17, 49, 287, 57,
+ 0, 51, 52, 54, 55, 56, 59, 58, 60, 61,
+ 64, 63, 62, 33, 0, 32, 0, 42, 0, 34,
+ 35, 37, 38, 39, 40, 41, 43, 44, 45, 46,
+ 47, 23, 26, 24, 25, 27, 14, 0, 15, 23,
+ 26, 24, 25, 27, 14, 0, 15, 19, 20, 21,
+ 0, 17, 0, 9, 0, 19, 20, 21, 0, 17,
+ 0, 161, 19, 20, 21, 0, 0, 0, 216, 0,
+ 22, 261, 0, 262, 264, 265, 0, 263, 22, 0,
+ 0, 0, 65, 3, 0, 266, 0, 0, 0, 0,
+ 0, 0, 0, 0, 23, 26, 24, 25, 27, 14,
+ 0, 15, 23, 26, 24, 25, 27, 0, 0, 23,
+ 26, 24, 25, 27, 163, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 131, 0, 22, 0, 0, 0, 0, 0, 0,
+ 0, 22, 0, 0, 0, 0, 0, 0, 22, 118,
119, 120, 121, 122, 124, 123, 125, 126, 0, 127,
- 128, 129, 130, 0, 0, 0, 134, 132, 133, 136,
- 137, 138, 135, 139, 102, 103, 104, 108, 0, 0,
- 0, 207, 0, 0, 107, 105, 106, 110, 109, 111,
- 112, 113, 114, 115, 116, 117, 102, 103, 104, 108,
- 0, 0, 0, 0, 0, 0, 107, 105, 106, 110,
- 109, 111, 112, 113, 114, 115, 116, 117,
+ 128, 129, 130, 0, 0, 0, 134, 132, 133, 137,
+ 138, 139, 135, 140, 136, 102, 103, 104, 108, 0,
+ 0, 0, 208, 0, 0, 107, 105, 106, 110, 109,
+ 111, 112, 113, 114, 115, 116, 117, 102, 103, 104,
+ 108, 0, 0, 0, 0, 0, 0, 107, 105, 106,
+ 110, 109, 111, 112, 113, 114, 115, 116, 117,
}
var yyPact = [...]int{
- 765, -36, -39, 627, -1000, 605, -1000, -1000, -1000, 765,
- -1000, 527, -1000, 520, 327, 326, -1000, 365, -1000, -1000,
- -1000, -1000, 354, 324, 322, 313, 310, 299, -1000, 297,
- 178, 288, 288, 288, 288, 288, 288, 288, 288, 288,
- 288, 288, 288, 288, 288, 288, 288, 288, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 583, 96, 558, 393, 196,
- 233, 899, 283, 283, 283, 283, 283, 283, -1000, -1000,
- -1000, -1000, -1000, -1000, 780, 780, 780, 780, 780, 780,
- 780, 414, 852, -1000, 493, 414, 414, 414, -1000, -1000,
+ 781, -34, -41, 633, -1000, 611, -1000, -1000, -1000, 781,
+ -1000, 532, -1000, 525, 304, 303, -1000, 368, -1000, -1000,
+ -1000, -1000, 335, 302, 301, 280, 278, 275, -1000, 268,
+ 179, 258, 258, 258, 258, 258, 258, 258, 258, 258,
+ 258, 258, 258, 258, 258, 258, 258, 258, 178, 178,
+ 178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
+ 178, 178, 178, 178, 178, 589, 24, 564, 396, 182,
+ 234, 910, 257, 257, 257, 257, 257, 257, -1000, -1000,
+ -1000, -1000, -1000, -1000, 796, 796, 796, 796, 796, 796,
+ 796, 418, 862, -1000, 498, 418, 418, 418, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
- -1000, 421, 420, 397, 147, 371, 176, 244, 85, 110,
- -1000, -1000, -1000, 194, 414, 414, 414, 414, 360, -1000,
- 605, -1000, -1000, -1000, -1000, 281, 278, 276, 274, 266,
- 773, 264, 666, 711, -1000, -1000, -1000, -1000, 666, -1000,
+ -1000, 363, 361, 355, 108, 353, 351, 261, 784, 80,
+ 65, -1000, -1000, -1000, 151, 418, 418, 418, 418, 188,
+ -1000, 611, -1000, -1000, -1000, -1000, 256, 255, 254, 216,
+ 212, 789, 210, 680, 726, -1000, -1000, -1000, -1000, 680,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
- 648, 179, -1000, -1000, -1000, -1000, 648, -1000, -1000, -1000,
+ -1000, 662, 178, -1000, -1000, -1000, -1000, 662, -1000, -1000,
-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
- 260, -1000, -1000, -1000, -1000, -4, -1000, 19, 25, 25,
- -76, -76, -76, -76, -11, 780, 12, 12, -79, -79,
- -79, -79, 483, 307, -1000, -1000, -1000, -1000, -1000, 414,
- 414, 414, 414, 414, 414, 414, 414, 414, 414, 414,
- 414, 414, 414, 414, 414, 453, -47, -47, 10, 9,
- 8, -19, 364, 362, -23, -1000, -1000, -1000, -1000, -1000,
- -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 442,
- 404, 64, 54, 234, -1000, -49, 192, 184, 852, 852,
- 331, 558, 130, 181, 75, 711, -1000, 19, -45, -1000,
- -1000, 852, -47, -47, -80, -80, -80, -51, -51, -51,
- -51, -51, -51, -51, -51, -80, 105, 105, -1000, -1000,
- -1000, -1000, -1000, -25, -27, -1000, -1000, -1000, -1000, -1000,
- -1000, 360, 921, 56, 55, 142, 174, 231, -1000, 260,
- -1000, -1000, -1000, -1000, -1000, 253, 226, 401, 39, -1000,
- 350, 852, 852, 214, -1000, -1000, 204, 205, 201, 159,
- 372, 37, 852, -1000, 348, -1000, -1000, -1000, -1000, 199,
- 157, 132, 852, -1000, 344, 155, 148, -1000, -1000,
+ -1000, 219, -1000, -1000, -1000, -1000, -23, -1000, 718, -8,
+ -8, -77, -77, -77, -77, -52, 796, -12, -12, -80,
+ -80, -80, -80, 488, 235, -1000, -1000, -1000, -1000, -1000,
+ 418, 418, 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 458, -48, -48, 30,
+ 19, 18, 17, 340, 333, 15, 14, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, 446, 408, 64, 54, 199, -1000, -50, 149, 144,
+ 862, 862, 111, 564, 227, 139, 22, 726, -1000, 718,
+ -46, -1000, -1000, 862, -48, -48, -81, -81, -81, -66,
+ -66, -66, -66, -66, -66, -66, -66, -81, 105, 105,
+ -1000, -1000, -1000, -1000, -1000, 9, -20, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, 188, 932, 48, 47, 104, 134,
+ 197, -1000, 219, -1000, -1000, -1000, -1000, -1000, 196, 194,
+ 357, 38, -1000, 321, 862, 862, 180, -1000, -1000, 192,
+ 160, 158, 156, 347, 36, 862, -1000, 311, -1000, -1000,
+ -1000, -1000, 186, 106, 96, 862, -1000, 240, 100, 109,
+ -1000, -1000,
}
var yyPgo = [...]int{
- 0, 471, 7, 470, 5, 6, 1, 805, 469, 14,
- 10, 3, 340, 468, 467, 800, 13, 450, 428, 12,
- 19, 9, 4, 2, 0, 18, 427, 8, 418, 358,
+ 0, 411, 7, 410, 5, 6, 1, 822, 404, 14,
+ 10, 3, 320, 382, 381, 143, 13, 378, 371, 12,
+ 19, 9, 4, 2, 0, 18, 369, 8, 361, 339,
}
var yyR1 = [...]int{
@@ -432,7 +436,7 @@ var yyR1 = [...]int{
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 23, 23, 23, 23,
- 23, 23, 23,
+ 23, 23, 23, 23,
}
var yyR2 = [...]int{
@@ -455,47 +459,48 @@ var yyR2 = [...]int{
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 3,
+ 4, 4, 3, 3,
}
var yyChk = [...]int{
-1000, -1, -9, -7, -14, -6, -11, -2, -4, 12,
- -8, -15, -10, -16, 57, 59, -17, 10, -19, 6,
- 7, 8, 91, 52, 54, 55, 53, 56, -29, 66,
- 67, 68, 74, 72, 78, 79, 69, 80, 81, 82,
- 83, 84, 76, 85, 86, 87, 88, 89, 68, 74,
- 72, 78, 79, 69, 80, 81, 82, 76, 84, 83,
- 85, 86, 89, 88, 87, -7, -9, -6, -15, -18,
- -16, -12, 90, 91, 93, 94, 95, 96, 70, 71,
- 72, 73, 74, 75, -12, 90, 91, 93, 94, 95,
- 96, 12, 12, 11, -20, 12, 91, 92, -21, -22,
+ -8, -15, -10, -16, 58, 60, -17, 10, -19, 6,
+ 7, 8, 92, 53, 55, 56, 54, 57, -29, 67,
+ 68, 69, 75, 73, 79, 80, 70, 81, 82, 83,
+ 84, 85, 77, 86, 87, 88, 89, 90, 69, 75,
+ 73, 79, 80, 70, 81, 82, 83, 77, 85, 84,
+ 86, 87, 90, 89, 88, -7, -9, -6, -15, -18,
+ -16, -12, 91, 92, 94, 95, 96, 97, 71, 72,
+ 73, 74, 75, 76, -12, 91, 92, 94, 95, 96,
+ 97, 12, 12, 11, -20, 12, 92, 93, -21, -22,
-23, -24, 5, 6, 7, 16, 17, 15, 8, 19,
18, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 33, 32, 34, 35, 37, 38, 39,
- 40, 9, 45, 46, 44, 50, 47, 48, 49, 51,
- 6, 7, 8, 12, 12, 12, 12, 12, 12, -13,
- -6, -11, -2, -3, -4, 61, 62, 63, 64, 65,
- 12, 58, -7, 12, -7, -7, -7, -7, -7, -7,
+ 40, 9, 45, 46, 44, 50, 52, 47, 48, 49,
+ 51, 6, 7, 8, 12, 12, 12, 12, 12, 12,
+ -13, -6, -11, -2, -3, -4, 62, 63, 64, 65,
+ 66, 12, 59, -7, 12, -7, -7, -7, -7, -7,
-7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -6, 12, -6, -6, -6, -6, -6, -6, -6, -6,
- -6, -6, -6, -6, -6, -6, -6, -6, 13, 13,
- 67, 13, 13, 13, 13, -15, -21, 12, -15, -15,
- -15, -15, -15, -15, -16, 12, -16, -16, -16, -16,
- -16, -16, -20, -5, -25, -22, -23, -24, 11, 90,
- 91, 93, 94, 95, 70, 71, 72, 73, 74, 75,
- 77, 76, 96, 68, 69, -20, -20, -20, 4, 4,
- 4, 4, 45, 46, 4, 27, 34, 36, 41, 27,
- 29, 33, 30, 31, 41, 29, 42, 43, 13, -20,
- -20, -20, -20, -28, -27, 4, 12, 12, 12, 12,
- 12, -6, -16, 12, -9, 12, -19, 12, -9, 13,
- 13, 14, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, 13, 60,
- 60, 60, 60, 4, 4, 60, 13, 13, 13, 13,
- 13, 14, 70, 13, 13, -25, -25, -10, 13, 67,
- -25, 60, 60, -27, -21, 57, 57, 14, 13, 13,
- 14, 12, 12, -26, 7, 6, 57, 6, -5, -5,
- 14, 13, 12, 13, 14, 13, 13, 7, 6, 57,
- -5, 6, 12, 13, 14, -5, 6, 13, 13,
+ -7, -6, 12, -6, -6, -6, -6, -6, -6, -6,
+ -6, -6, -6, -6, -6, -6, -6, -6, -6, 13,
+ 13, 68, 13, 13, 13, 13, -15, -21, 12, -15,
+ -15, -15, -15, -15, -15, -16, 12, -16, -16, -16,
+ -16, -16, -16, -20, -5, -25, -22, -23, -24, 11,
+ 91, 92, 94, 95, 96, 71, 72, 73, 74, 75,
+ 76, 78, 77, 97, 69, 70, -20, -20, -20, 4,
+ 4, 4, 4, 45, 46, 4, 4, 27, 34, 36,
+ 41, 27, 29, 33, 30, 31, 41, 29, 42, 43,
+ 13, -20, -20, -20, -20, -28, -27, 4, 12, 12,
+ 12, 12, 12, -6, -16, 12, -9, 12, -19, 12,
+ -9, 13, 13, 14, -20, -20, -20, -20, -20, -20,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ 13, 61, 61, 61, 61, 4, 4, 61, 61, 13,
+ 13, 13, 13, 13, 14, 71, 13, 13, -25, -25,
+ -10, 13, 68, -25, 61, 61, -27, -21, 58, 58,
+ 14, 13, 13, 14, 12, 12, -26, 7, 6, 58,
+ 6, -5, -5, 14, 13, 12, 13, 14, 13, 13,
+ 7, 6, 58, -5, 6, 12, 13, 14, -5, 6,
+ 13, 13,
}
var yyDef = [...]int{
@@ -513,29 +518,30 @@ var yyDef = [...]int{
152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 98, 99, 100, 0, 0, 0, 0, 0, 0, 4,
- 30, 31, 32, 33, 34, 0, 0, 0, 0, 0,
- 0, 0, 7, 0, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 48, 0, 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 6, 25,
- 0, 47, 77, 85, 87, 75, 76, 0, 78, 79,
- 80, 81, 82, 83, 68, 0, 88, 89, 90, 91,
- 92, 93, 0, 0, 41, 38, 39, 40, 67, 0,
+ 0, 98, 99, 100, 0, 0, 0, 0, 0, 0,
+ 4, 30, 31, 32, 33, 34, 0, 0, 0, 0,
+ 0, 0, 0, 7, 0, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 48, 0, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 6,
+ 25, 0, 47, 77, 85, 87, 75, 76, 0, 78,
+ 79, 80, 81, 82, 83, 68, 0, 88, 89, 90,
+ 91, 92, 93, 0, 0, 41, 38, 39, 40, 67,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 138, 139, 0, 0,
- 0, 0, 0, 0, 0, 173, 174, 175, 176, 177,
- 178, 179, 180, 181, 182, 183, 184, 185, 101, 0,
- 0, 0, 0, 0, 119, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, -2, 0, 0, 35,
- 37, 0, 122, 123, 124, 125, 126, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 121, 186,
- 187, 188, 189, 0, 0, 192, 102, 103, 104, 105,
- 118, 0, 0, 106, 108, 0, 0, 0, 36, 0,
- 42, 190, 191, 120, 117, 0, 0, 0, 112, 114,
- 0, 0, 0, 0, 43, 44, 0, 0, 0, 0,
- 0, 110, 0, 115, 0, 107, 109, 45, 46, 0,
- 0, 0, 0, 113, 0, 0, 0, 111, 116,
+ 0, 0, 0, 0, 0, 0, 0, 138, 139, 0,
+ 0, 0, 0, 0, 0, 0, 0, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+ 101, 0, 0, 0, 0, 0, 119, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -2, 0,
+ 0, 35, 37, 0, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 121, 186, 187, 188, 189, 0, 0, 192, 193, 102,
+ 103, 104, 105, 118, 0, 0, 106, 108, 0, 0,
+ 0, 36, 0, 42, 190, 191, 120, 117, 0, 0,
+ 0, 112, 114, 0, 0, 0, 0, 43, 44, 0,
+ 0, 0, 0, 0, 110, 0, 115, 0, 107, 109,
+ 45, 46, 0, 0, 0, 0, 113, 0, 0, 0,
+ 111, 116,
}
var yyTok1 = [...]int{
@@ -552,7 +558,7 @@ var yyTok2 = [...]int{
62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
- 92, 93, 94, 95, 96,
+ 92, 93, 94, 95, 96, 97,
}
var yyTok3 = [...]int{
0,
@@ -2047,6 +2053,12 @@ yydefault:
{
yyVAL.attributeField = NewScopedAttribute(AttributeScopeEvent, false, yyDollar[2].staticStr)
}
+ case 193:
+ yyDollar = yyS[yypt-3 : yypt+1]
+//line pkg/traceql/expr.y:422
+ {
+ yyVAL.attributeField = NewScopedAttribute(AttributeScopeLink, false, yyDollar[2].staticStr)
+ }
}
goto yystack /* stack new state and value */
}
diff --git a/pkg/traceql/lexer.go b/pkg/traceql/lexer.go
index afc07981fdb..a1ad1aa096c 100644
--- a/pkg/traceql/lexer.go
+++ b/pkg/traceql/lexer.go
@@ -87,6 +87,7 @@ var tokens = map[string]int{
"event:": EVENT_COLON,
"link:": LINK_COLON,
"event.": EVENT_DOT,
+ "link.": LINK_DOT,
"count": COUNT,
"avg": AVG,
"max": MAX,
@@ -215,7 +216,8 @@ func (l *lexer) Lex(lval *yySymType) int {
multiTok == TRACE_COLON ||
multiTok == EVENT_COLON ||
multiTok == LINK_COLON ||
- multiTok == EVENT_DOT {
+ multiTok == EVENT_DOT ||
+ multiTok == LINK_DOT {
l.currentScope = multiTok
}
@@ -406,5 +408,6 @@ func startsAttribute(tok int) bool {
tok == RESOURCE_DOT ||
tok == SPAN_DOT ||
tok == PARENT_DOT ||
- tok == EVENT_DOT
+ tok == EVENT_DOT ||
+ tok == LINK_DOT
}
diff --git a/pkg/traceql/lexer_test.go b/pkg/traceql/lexer_test.go
index 3767d343f66..66123ea175a 100644
--- a/pkg/traceql/lexer_test.go
+++ b/pkg/traceql/lexer_test.go
@@ -51,6 +51,13 @@ func TestLexerAttributes(t *testing.T) {
{`event.foo3`, []int{EVENT_DOT, IDENTIFIER, END_ATTRIBUTE}},
{`event.foo+bar`, []int{EVENT_DOT, IDENTIFIER, END_ATTRIBUTE}},
{`event.foo-bar`, []int{EVENT_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ // link attributes
+ {`link.foo`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ {`link.count`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ {`link.count`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ {`link.foo3`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ {`link.foo+bar`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
+ {`link.foo-bar`, []int{LINK_DOT, IDENTIFIER, END_ATTRIBUTE}},
// parent span attributes
{`parent.span.foo`, []int{PARENT_DOT, SPAN_DOT, IDENTIFIER, END_ATTRIBUTE}},
{`parent.span.count`, []int{PARENT_DOT, SPAN_DOT, IDENTIFIER, END_ATTRIBUTE}},
diff --git a/pkg/traceql/parse_test.go b/pkg/traceql/parse_test.go
index e9d1ac8ed70..c067a0a0813 100644
--- a/pkg/traceql/parse_test.go
+++ b/pkg/traceql/parse_test.go
@@ -1021,6 +1021,7 @@ func TestAttributes(t *testing.T) {
{in: "resource.foo.bar.baz", expected: NewScopedAttribute(AttributeScopeResource, false, "foo.bar.baz")},
{in: "span.foo.bar", expected: NewScopedAttribute(AttributeScopeSpan, false, "foo.bar")},
{in: "event.foo.bar", expected: NewScopedAttribute(AttributeScopeEvent, false, "foo.bar")},
+ {in: "link.foo.bar", expected: NewScopedAttribute(AttributeScopeLink, false, "foo.bar")},
{in: "parent.resource.foo", expected: NewScopedAttribute(AttributeScopeResource, true, "foo")},
{in: "parent.span.foo", expected: NewScopedAttribute(AttributeScopeSpan, true, "foo")},
{in: "parent.resource.foo.bar.baz", expected: NewScopedAttribute(AttributeScopeResource, true, "foo.bar.baz")},
diff --git a/pkg/traceql/test_examples.yaml b/pkg/traceql/test_examples.yaml
index 6b0a1531d05..e4b5c90dca2 100644
--- a/pkg/traceql/test_examples.yaml
+++ b/pkg/traceql/test_examples.yaml
@@ -52,6 +52,7 @@ valid:
- '{ 1 < 1h }'
- '{ 1 <= 1.1 }'
- '{ event.foo = "bar" }'
+ - '{ link.foo = "bar" }'
# scoped intrinsics
- '{ trace:duration > 2s }'
- '{ trace:rootName = "a" }'
diff --git a/tempodb/encoding/vparquet4/block_traceql.go b/tempodb/encoding/vparquet4/block_traceql.go
index cea7fe5aaf2..eb32d96a004 100644
--- a/tempodb/encoding/vparquet4/block_traceql.go
+++ b/tempodb/encoding/vparquet4/block_traceql.go
@@ -887,6 +887,11 @@ const (
columnPathEventAttrInt = "rs.list.element.ss.list.element.Spans.list.element.Events.list.element.Attrs.list.element.ValueInt.list.element"
columnPathEventAttrDouble = "rs.list.element.ss.list.element.Spans.list.element.Events.list.element.Attrs.list.element.ValueDouble.list.element"
columnPathEventAttrBool = "rs.list.element.ss.list.element.Spans.list.element.Events.list.element.Attrs.list.element.ValueBool.list.element"
+ columnPathLinkAttrKey = "rs.list.element.ss.list.element.Spans.list.element.Links.list.element.Attrs.list.element.Key"
+ columnPathLinkAttrString = "rs.list.element.ss.list.element.Spans.list.element.Links.list.element.Attrs.list.element.Value.list.element"
+ columnPathLinkAttrInt = "rs.list.element.ss.list.element.Spans.list.element.Links.list.element.Attrs.list.element.ValueInt.list.element"
+ columnPathLinkAttrDouble = "rs.list.element.ss.list.element.Spans.list.element.Links.list.element.Attrs.list.element.ValueDouble.list.element"
+ columnPathLinkAttrBool = "rs.list.element.ss.list.element.Spans.list.element.Links.list.element.Attrs.list.element.ValueBool.list.element"
otherEntrySpansetKey = "spanset"
otherEntrySpanKey = "span"
@@ -1368,36 +1373,47 @@ func (i *mergeSpansetIterator) Close() {
// matching columns using parquetquery.Predicates. Results are collected The final return is an iterator where each result is 1 Spanset for each trace.
//
// Diagram:
-//
-// Event attribute iterator: key --------------------------------------------
-// ... ----------------------------------------- |
-// Event attribute iterator: valueN --------------------------------------- | |
-// | | |
-// V V V
-// ------------
-// Event column iterator 1 --------------------------------------------- | attribute |
-// (ex: name, time since) | | collector |
-// | ------------
-// | |
-// V V
-// Span attribute iterator: key ------------------------- ------------
-// ... ----------------------- | | event |
-// Span attribute iterator: valueN -------------------| | | | collector |
-// | | | -------------
-// V V V |
-// ------------- |
-// | attribute | | list
-// | collector | | of
-// ------------- | events
-// | |
-// | List |
-// | of span |
-// | attributes |
-// Span column iterator 1 --------------------------- | |
-// ... ------------------------ | | |
-// Span column iterator N --------------------- | | | |
-// (ex: name, status) | | | | |
-// V V V V V
+// ------------
+// Link attribute iterator: key -----------------------------------------------------> | attribute |
+// ... ------------------------------------------------------> | collector |
+// Link attribute iterator: valueN -----------------------------------------------------> | |
+// ------------
+// |
+// |
+// Link column iterator 1 --------------------------------------------------------------------- |
+// (ex: span ID, trace ID) | |
+// | |
+// | |
+// V V
+// Event attribute iterator: key -------------------------------------------- ------------
+// ... ----------------------------------------- | | link |
+// Event attribute iterator: valueN --------------------------------------- | | | collector |
+// | | | ------------
+// V V V |
+// ------------ |
+// Event column iterator 1 --------------------------------------------- | attribute | |
+// (ex: name, time since) | | collector | |
+// | ------------ |
+// | | |
+// V V |
+// Span attribute iterator: key ------------------------- ------------ |
+// ... ----------------------- | | event | |
+// Span attribute iterator: valueN -------------------| | | | collector | |
+// | | | ------------- |
+// V V V | |
+// ------------- | |
+// | attribute | | list |
+// | collector | | of |
+// ------------- | events |
+// | | |
+// | List | |
+// | of span | |
+// | attributes | |
+// Span column iterator 1 --------------------------- | | |
+// ... ------------------------ | | | |
+// Span column iterator N --------------------- | | | | |
+// (ex: name, status) | | | | | |
+// V V V V V V
// -------------------------------------------------
// | span collector |
// -------------------------------------------------
@@ -1553,7 +1569,7 @@ func createAllIterator(ctx context.Context, primaryIter parquetquery.Iterator, c
innerIterators = append(innerIterators, eventIter)
}
- linkIter, err := createLinkIterator(makeIter, catConditions.link)
+ linkIter, err := createLinkIterator(makeIter, catConditions.link, allConditions, selectAll)
if err != nil {
return nil, fmt.Errorf("creating link iterator: %w", err)
}
@@ -1643,12 +1659,13 @@ func createEventIterator(makeIter makeIterFn, primaryIter parquetquery.Iterator,
return parquetquery.NewLeftJoinIterator(DefinitionLevelResourceSpansILSSpanEvent, required, eventIters, eventCol, parquetquery.WithPool(pqEventPool))
}
-func createLinkIterator(makeIter makeIterFn, conditions []traceql.Condition) (parquetquery.Iterator, error) {
+func createLinkIterator(makeIter makeIterFn, conditions []traceql.Condition, allConditions, selectAll bool) (parquetquery.Iterator, error) {
if len(conditions) == 0 {
return nil, nil
}
linkIters := make([]parquetquery.Iterator, 0, len(conditions))
+ var genericConditions []traceql.Condition
for _, cond := range conditions {
switch cond.Attribute.Intrinsic {
@@ -1658,6 +1675,7 @@ func createLinkIterator(makeIter makeIterFn, conditions []traceql.Condition) (pa
return nil, err
}
linkIters = append(linkIters, makeIter(columnPathLinkTraceID, pred, columnPathLinkTraceID))
+ continue
case traceql.IntrinsicLinkSpanID:
pred, err := createBytesPredicate(cond.Op, cond.Operands, false)
@@ -1665,14 +1683,51 @@ func createLinkIterator(makeIter makeIterFn, conditions []traceql.Condition) (pa
return nil, err
}
linkIters = append(linkIters, makeIter(columnPathLinkSpanID, pred, columnPathLinkSpanID))
+ continue
}
+ genericConditions = append(genericConditions, cond)
+ }
+
+ attrIter, err := createAttributeIterator(makeIter, genericConditions, DefinitionLevelResourceSpansILSSpanLinkAttrs,
+ columnPathLinkAttrKey, columnPathLinkAttrString, columnPathLinkAttrInt, columnPathLinkAttrDouble, columnPathLinkAttrBool, allConditions, selectAll)
+ if err != nil {
+ return nil, fmt.Errorf("creating link attribute iterator: %w", err)
+ }
+
+ if attrIter != nil {
+ linkIters = append(linkIters, attrIter)
+ }
+
+ var required []parquetquery.Iterator
+ minCount := 0
+
+ if allConditions {
+ // The final number of expected attributes.
+ distinct := map[string]struct{}{}
+ for _, cond := range conditions {
+ distinct[cond.Attribute.Name] = struct{}{}
+ }
+ minCount = len(distinct)
+ }
+
+ linkCol := &linkCollector{
+ minAttributes: minCount,
+ }
+
+ if allConditions {
+ required = append(required, linkIters...)
+ linkIters = nil
+ }
+
+ if len(required) == 0 {
+ required = []parquetquery.Iterator{makeIter(columnPathLinkSpanID, nil, "")}
}
- if len(linkIters) == 0 {
+ if len(linkIters) == 0 && len(required) == 0 {
return nil, nil
}
- return parquetquery.NewJoinIterator(DefinitionLevelResourceSpansILSSpanLink, linkIters, &linkCollector{}, parquetquery.WithPool(pqLinkPool)), nil
+ return parquetquery.NewLeftJoinIterator(DefinitionLevelResourceSpansILSSpanEvent, required, linkIters, linkCol, parquetquery.WithPool(pqLinkPool))
}
// createSpanIterator iterates through all span-level columns, groups them into rows representing
@@ -2939,7 +2994,9 @@ func getLink() *link {
// linkCollector receives rows from the link columns and joins them together into
// map[key]value entries with the right type.
-type linkCollector struct{}
+type linkCollector struct {
+ minAttributes int
+}
var _ parquetquery.GroupPredicate = (*linkCollector)(nil)
@@ -2963,6 +3020,16 @@ func (c *linkCollector) KeepGroup(res *parquetquery.IteratorResult) bool {
l = getLink()
}
+ // extract from attribute collector
+ for _, e := range res.OtherEntries {
+ if v, ok := e.Value.(traceql.Static); ok {
+ l.attrs = append(l.attrs, attrVal{
+ a: newLinkAttr(e.Key),
+ s: v,
+ })
+ }
+ }
+
for _, e := range res.Entries {
switch e.Key {
case columnPathLinkTraceID:
@@ -2978,6 +3045,13 @@ func (c *linkCollector) KeepGroup(res *parquetquery.IteratorResult) bool {
}
}
+ if c.minAttributes > 0 {
+ if len(l.attrs) < c.minAttributes {
+ putLink(l)
+ return false
+ }
+ }
+
res.Reset()
res.AppendOtherValue(otherEntryLinkKey, l)
@@ -2996,6 +3070,10 @@ func newEventAttr(name string) traceql.Attribute {
return traceql.NewScopedAttribute(traceql.AttributeScopeEvent, false, name)
}
+func newLinkAttr(name string) traceql.Attribute {
+ return traceql.NewScopedAttribute(traceql.AttributeScopeLink, false, name)
+}
+
func unionIfNeeded(definitionLevel int, iters []parquetquery.Iterator, pred parquetquery.GroupPredicate) parquetquery.Iterator {
switch len(iters) {
case 0:
diff --git a/tempodb/encoding/vparquet4/block_traceql_meta_test.go b/tempodb/encoding/vparquet4/block_traceql_meta_test.go
index e0f748b8de4..d3c266175d2 100644
--- a/tempodb/encoding/vparquet4/block_traceql_meta_test.go
+++ b/tempodb/encoding/vparquet4/block_traceql_meta_test.go
@@ -640,6 +640,39 @@ func TestBackendBlockSearchFetchMetaData(t *testing.T) {
),
),
},
+ {
+ "Link attribute lookup",
+ makeReq(
+ parse(t, `{link.opentracing.ref_type =~ "child"}`), //
+ ),
+ makeSpansets(
+ makeSpanset(
+ wantTr.TraceID,
+ wantTr.RootSpanName,
+ wantTr.RootServiceName,
+ wantTr.StartTimeUnixNano,
+ wantTr.DurationNano,
+ &span{
+ id: wantTr.ResourceSpans[0].ScopeSpans[0].Spans[0].SpanID,
+ startTimeUnixNanos: wantTr.ResourceSpans[0].ScopeSpans[0].Spans[0].StartTimeUnixNano,
+ durationNanos: wantTr.ResourceSpans[0].ScopeSpans[0].Spans[0].DurationNano,
+ spanAttrs: []attrVal{
+ {traceql.NewIntrinsic(traceql.IntrinsicDuration), traceql.NewStaticDuration(100 * time.Second)},
+ {traceql.NewIntrinsic(traceql.IntrinsicSpanID), traceql.NewStaticString(util.SpanIDToHexString(wantTr.ResourceSpans[0].ScopeSpans[0].Spans[0].SpanID))},
+ },
+ traceAttrs: []attrVal{
+ {traceql.NewIntrinsic(traceql.IntrinsicTraceRootService), traceql.NewStaticString("RootService")},
+ {traceql.NewIntrinsic(traceql.IntrinsicTraceRootSpan), traceql.NewStaticString("RootSpan")},
+ {traceql.NewIntrinsic(traceql.IntrinsicTraceDuration), traceql.NewStaticDuration(100 * time.Millisecond)},
+ {traceql.NewIntrinsic(traceql.IntrinsicTraceID), traceql.NewStaticString(util.TraceIDToHexString(wantTr.TraceID))},
+ },
+ linkAttrs: []attrVal{
+ {traceql.NewScopedAttribute(traceql.AttributeScopeLink, false, "opentracing.ref_type"), traceql.NewStaticString("child-of")},
+ },
+ },
+ ),
+ ),
+ },
}
for _, tc := range testCases {
@@ -678,6 +711,12 @@ func TestBackendBlockSearchFetchMetaData(t *testing.T) {
if len(spn.spanAttrs) == 0 {
spn.spanAttrs = nil
}
+ if len(spn.linkAttrs) == 0 {
+ spn.linkAttrs = nil
+ }
+ if len(spn.eventAttrs) == 0 {
+ spn.eventAttrs = nil
+ }
// sort actual attrs to get consistent comparisons
sortSpanAttrs(spn)
diff --git a/tempodb/encoding/vparquet4/block_traceql_test.go b/tempodb/encoding/vparquet4/block_traceql_test.go
index 8502b412a71..c94fcad3f1c 100644
--- a/tempodb/encoding/vparquet4/block_traceql_test.go
+++ b/tempodb/encoding/vparquet4/block_traceql_test.go
@@ -155,6 +155,7 @@ func TestBackendBlockSearchTraceQL(t *testing.T) {
// Links
{"link:spanID", traceql.MustExtractFetchSpansRequestWithMetadata(`{link:spanID = "1234567890abcdef"}`)},
{"link:traceID", traceql.MustExtractFetchSpansRequestWithMetadata(`{link:traceID = "1234567890abcdef1234567890abcdef"}`)},
+ {"link.opentracing.ref_type", traceql.MustExtractFetchSpansRequestWithMetadata(`{link.opentracing.ref_type = "child-of"}`)},
// Basic data types and operations
{".float = 456.78", traceql.MustExtractFetchSpansRequestWithMetadata(`{.float = 456.78}`)}, // Float ==
{".float != 456.79", traceql.MustExtractFetchSpansRequestWithMetadata(`{.float != 456.79}`)}, // Float !=
@@ -418,7 +419,7 @@ func fullyPopulatedTestTrace(id common.ID) *Trace {
TraceState: "state",
DroppedAttributesCount: 3,
Attrs: []Attribute{
- attr("link-attr-key-1", "link-value-1"),
+ attr("opentracing.ref_type", "child-of"),
},
},
}
diff --git a/tempodb/encoding/vparquet4/schema.go b/tempodb/encoding/vparquet4/schema.go
index 448e40a3323..25d71d2e6b4 100644
--- a/tempodb/encoding/vparquet4/schema.go
+++ b/tempodb/encoding/vparquet4/schema.go
@@ -55,6 +55,7 @@ const (
DefinitionLevelResourceSpansILSSpanEvent = 4
DefinitionLevelResourceSpansILSSpanLink = 4
DefinitionLevelResourceSpansILSSpanEventAttrs = 5
+ DefinitionLevelResourceSpansILSSpanLinkAttrs = 5
FieldResourceAttrKey = "rs.list.element.Resource.Attrs.list.element.Key"
FieldResourceAttrVal = "rs.list.element.Resource.Attrs.list.element.Value.list.element"
diff --git a/tempodb/tempodb_search_test.go b/tempodb/tempodb_search_test.go
index 1e4acc33955..232e0a668de 100644
--- a/tempodb/tempodb_search_test.go
+++ b/tempodb/tempodb_search_test.go
@@ -58,8 +58,8 @@ func TestSearchCompleteBlock(t *testing.T) {
)
})
if vers == vparquet4.VersionString {
- t.Run("event query", func(t *testing.T) {
- runEventSearchTest(t, vers)
+ t.Run("event/link query", func(t *testing.T) {
+ runEventLinkSearchTest(t, vers)
})
}
}
@@ -1578,7 +1578,7 @@ func runCompleteBlockSearchTest(t *testing.T, blockVersion string, runners ...ru
// todo: do some compaction and then call runner again
}
-func runEventSearchTest(t *testing.T, blockVersion string) {
+func runEventLinkSearchTest(t *testing.T, blockVersion string) {
// only run this test for vparquet4
if blockVersion != vparquet4.VersionString {
return
@@ -1624,6 +1624,7 @@ func runEventSearchTest(t *testing.T, blockVersion string) {
rw := r.(*readerWriter)
wantID, wantTr, start, end, wantMeta := makeExpectedTrace()
+ wantIDText := util.TraceIDToHexString(wantID)
searchesThatMatch := []*tempopb.SearchRequest{
{
@@ -1632,6 +1633,12 @@ func runEventSearchTest(t *testing.T, blockVersion string) {
{
Query: "{ event:name = `event name` }",
},
+ {
+ Query: "{ link.relation = `child-of` }",
+ },
+ {
+ Query: "{ link:traceID = `" + wantIDText + "` }",
+ },
}
// Write to wal
@@ -1832,6 +1839,15 @@ func makeExpectedTrace() (
},
},
},
+ Links: []*v1.Span_Link{
+ {
+ TraceId: id,
+ SpanId: []byte{4, 5, 6},
+ Attributes: []*v1_common.KeyValue{
+ stringKV("relation", "child-of"),
+ },
+ },
+ },
},
},
},