@@ -6,6 +6,12 @@ import (
6
6
"time"
7
7
8
8
"github.com/stretchr/testify/require"
9
+
10
+ "github.com/grafana/loki/v3/pkg/logproto"
11
+ "github.com/grafana/loki/v3/pkg/logql"
12
+ "github.com/grafana/loki/v3/pkg/logql/syntax"
13
+ "github.com/grafana/loki/v3/pkg/querier/plan"
14
+ "github.com/grafana/loki/v3/pkg/util/httpreq"
9
15
)
10
16
11
17
type fakeTimeLimits struct {
@@ -51,3 +57,118 @@ func Test_validateQueryTimeRangeLimits(t *testing.T) {
51
57
})
52
58
}
53
59
}
60
+
61
+ func TestValidateAggregatedMetricQuery (t * testing.T ) {
62
+ makeReqAndAST := func (queryStr string ) logql.QueryParams {
63
+ now := time .Now ()
64
+ expr , err := syntax .ParseExpr (queryStr )
65
+ if err != nil {
66
+ panic (err )
67
+ }
68
+ switch expr .(type ) {
69
+ case syntax.SampleExpr :
70
+ return logql.SelectSampleParams {SampleQueryRequest : & logproto.SampleQueryRequest {
71
+ Selector : queryStr ,
72
+ Start : now .Add (- time .Hour ),
73
+ End : now ,
74
+ Plan : & plan.QueryPlan {AST : expr },
75
+ },
76
+ }
77
+ default :
78
+ return logql.SelectLogParams {QueryRequest : & logproto.QueryRequest {
79
+ Selector : queryStr ,
80
+ Start : now .Add (- time .Hour ),
81
+ End : now ,
82
+ Direction : logproto .BACKWARD ,
83
+ Plan : & plan.QueryPlan {
84
+ AST : expr ,
85
+ },
86
+ },
87
+ }
88
+ }
89
+ }
90
+
91
+ tcs := []struct {
92
+ desc string
93
+ req logql.QueryParams
94
+ queryTags string
95
+ expectedError error
96
+ }{
97
+ {
98
+ desc : "normal query, no error" ,
99
+ req : makeReqAndAST (`{foo="bar"}` ),
100
+ queryTags : "" ,
101
+ expectedError : nil ,
102
+ },
103
+ {
104
+ desc : "aggregated metric query from explore, no error" ,
105
+ req : makeReqAndAST (`{__aggregated_metric__="service-name"}` ),
106
+ queryTags : "source=" + logsDrilldownAppName ,
107
+ expectedError : nil ,
108
+ },
109
+ {
110
+ desc : "query tags are case insensitive" ,
111
+ req : makeReqAndAST (`{__aggregated_metric__="service-name"}` ),
112
+ queryTags : "Source=" + logsDrilldownAppName ,
113
+ expectedError : nil ,
114
+ },
115
+ {
116
+ desc : "aggregated metric query from explore, multiple selectors, no error" ,
117
+ req : makeReqAndAST (`{app="service-name", __aggregated_metric__="true"}` ),
118
+ queryTags : "source=" + logsDrilldownAppName ,
119
+ expectedError : nil ,
120
+ },
121
+ {
122
+ desc : "aggregated metric query from explore, multiple selectors, filter, no error" ,
123
+ req : makeReqAndAST (`{app="service-name", __aggregated_metric__="true"} |= "test"` ),
124
+ queryTags : "source=" + logsDrilldownAppName ,
125
+ expectedError : nil ,
126
+ },
127
+ {
128
+ desc : "aggregated metrics metric query from explore, multiple selectors, filter, no error" ,
129
+ req : makeReqAndAST (`sum by (service_name)(count_over_time({app="service-name", __aggregated_metric__="true"} |= "test" [5m]))` ),
130
+ queryTags : "source=" + logsDrilldownAppName ,
131
+ expectedError : nil ,
132
+ },
133
+ {
134
+ desc : "aggregated metric query from other source, blocked" ,
135
+ req : makeReqAndAST (`{__aggregated_metric__="service-name"}` ),
136
+ queryTags : "source=other-app" ,
137
+ expectedError : ErrAggMetricsDrilldownOnly ,
138
+ },
139
+ {
140
+ desc : "aggregated metric query with no source, blocked" ,
141
+ req : makeReqAndAST (`{__aggregated_metric__="service-name"}` ),
142
+ queryTags : "" ,
143
+ expectedError : ErrAggMetricsDrilldownOnly ,
144
+ },
145
+ {
146
+ desc : "aggregated metric query with no source, multiple selectors, blocked" ,
147
+ req : makeReqAndAST (`{app="service-name", __aggregated_metric__="true"}` ),
148
+ queryTags : "" ,
149
+ expectedError : ErrAggMetricsDrilldownOnly ,
150
+ },
151
+ {
152
+ desc : "aggregated metrics metric query with no source, multiple selectors, filter, blocked" ,
153
+ req : makeReqAndAST (`sum by (service_name)(count_over_time({app="service-name", __aggregated_metric__="true"} |= "test" [5m]))` ),
154
+ queryTags : "" ,
155
+ expectedError : ErrAggMetricsDrilldownOnly ,
156
+ },
157
+ }
158
+
159
+ for _ , tc := range tcs {
160
+ t .Run (tc .desc , func (t * testing.T ) {
161
+ ctx := context .Background ()
162
+ if tc .queryTags != "" {
163
+ ctx = httpreq .InjectQueryTags (ctx , tc .queryTags )
164
+ }
165
+
166
+ err := ValidateAggregatedMetricQuery (ctx , tc .req )
167
+ if tc .expectedError != nil {
168
+ require .ErrorIs (t , err , tc .expectedError )
169
+ } else {
170
+ require .NoError (t , err )
171
+ }
172
+ })
173
+ }
174
+ }
0 commit comments