github.com/m3db/m3@v1.5.0/scripts/docker-integration-tests/query_fanout/warning.sh (about) 1 #!/usr/bin/env bash 2 3 set -ex 4 source "$M3_PATH"/scripts/docker-integration-tests/common.sh 5 6 COMPOSE_FILE="$M3_PATH"/scripts/docker-integration-tests/query_fanout/docker-compose.yml 7 HEADER_FILE=headers.out 8 9 function write_metrics { 10 CLUSTER=$1 11 case $CLUSTER in 12 coordinator-cluster-a ) 13 PORT=9003 ;; 14 coordinator-cluster-b ) 15 PORT=19003 ;; 16 coordinator-cluster-c ) 17 PORT=29003 ;; 18 *) 19 echo $CLUSTER "is not a valid coordinator cluster" 20 exit 1 21 esac 22 23 NUM=$2 24 echo "Writing $NUM metrics to $1 [0.0.0.0:$PORT]" 25 set +x 26 for (( i=0; i<$NUM; i++ )) 27 do 28 curl -X POST 0.0.0.0:$PORT/writetagged -d '{ 29 "namespace": "unagg", 30 "id": "{__name__=\"'$METRIC_NAME'\",cluster=\"'$CLUSTER'\",val=\"'$i'\"}", 31 "tags": [ 32 { 33 "name": "__name__", 34 "value": "'$METRIC_NAME'" 35 }, 36 { 37 "name": "cluster", 38 "value": "'$CLUSTER'" 39 }, 40 { 41 "name": "val", 42 "value": "'$i'" 43 } 44 ], 45 "datapoint": { 46 "timestamp":'"$t"', 47 "value": 1 48 } 49 }' 50 done 51 set -x 52 } 53 54 function clean_headers { 55 rm $HEADER_FILE 56 } 57 58 function test_instant_query { 59 LIMIT=$1 60 EXPECTED=$2 61 ENDPOINT=$3||"" 62 EXPECTED_HEADER=$4||"" 63 trap clean_headers EXIT 64 RESPONSE=$(curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 65 "http://0.0.0.0:7201${ENDPOINT}/api/v1/query?query=count($METRIC_NAME)") 66 ACTUAL=$(echo $RESPONSE | jq .data.result[0].value[1] | tr -d \" | tr -d \') 67 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 68 test "$ACTUAL" = "$EXPECTED" 69 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 70 } 71 72 t=$(date +%s) 73 74 function test_range_query { 75 LIMIT=$1 76 EXPECTED=$2 77 EXPECTED_HEADER=$3 78 trap clean_headers EXIT 79 80 start=$t 81 end=$(($start+9)) 82 83 RESPONSE=$(curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 84 "http://0.0.0.0:7201/api/v1/query_range?start=$start&end=$end&step=10&query=count($METRIC_NAME)") 85 ACTUAL=$(echo $RESPONSE | jq .data.result[0].values[0][1] | tr -d \" | tr -d \') 86 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 87 test "$ACTUAL" = "$EXPECTED" 88 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 89 } 90 91 function test_search { 92 s=$(( $(date +%s) - 60 )) 93 start=$(date -r $s +%Y-%m-%dT%H:%M:%SZ) 94 e=$(( $(date +%s) + 60 )) 95 end=$(date -r $e +%Y-%m-%dT%H:%M:%SZ) 96 curl -D headers -X POST 0.0.0.0:7201/search -d '{ 97 "start": "'$start'", 98 "end": "'$end'", 99 "matchers": [ 100 { 101 "type": 0, 102 "name":"'$(echo __name__ | base64)'", 103 "value":"'$(echo $METRIC_NAME | base64)'" 104 } 105 ] 106 } 107 ' 108 109 LIMIT=$1 110 EXPECTED_HEADER=$2 111 trap clean_headers EXIT 112 113 curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 114 "http://0.0.0.0:7201/api/v1/search?query=val:.*" 115 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 116 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 117 } 118 119 function test_labels { 120 LIMIT=$1 121 EXPECTED_HEADER=$2 122 trap clean_headers EXIT 123 124 curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 125 "http://0.0.0.0:7201/api/v1/labels" 126 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 127 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 128 } 129 130 function test_match { 131 LIMIT=$1 132 EXPECTED=$2 133 EXPECTED_HEADER=$3 134 trap clean_headers EXIT 135 RESPONSE=$(curl -gsSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 136 "http://0.0.0.0:7201/api/v1/series?match[]=$METRIC_NAME") 137 138 ACTUAL=$(echo $RESPONSE | jq '.data | length') 139 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 140 # NB: since it's not necessarily deterministic which series we get back from 141 # remote sources, check that we cot at least EXPECTED values, which will be 142 # the bottom bound. 143 test "$ACTUAL" -ge "$EXPECTED" 144 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 145 } 146 147 function test_label_values { 148 LIMIT=$1 149 EXPECTED_HEADER=$2 150 trap clean_headers EXIT 151 152 curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 153 "http://0.0.0.0:7201/api/v1/label/val/values" 154 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 155 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 156 } 157 158 function write_carbon { 159 CLUSTER=$1 160 case $CLUSTER in 161 coordinator-cluster-a ) 162 PORT=7204 ;; 163 coordinator-cluster-b ) 164 PORT=17204 ;; 165 coordinator-cluster-c ) 166 PORT=27204 ;; 167 *) 168 echo $CLUSTER "is not a valid coordinator cluster" 169 exit 1 170 esac 171 172 NUM=$2 173 echo "Writing $NUM metrics to $1 [0.0.0.0:$PORT]" 174 set +x 175 for (( i=0; i<$NUM; i++ )) 176 do 177 echo "$GRAPHITE.$i.$CLUSTER 1 $t" | nc 0.0.0.0 $PORT 178 done 179 set -x 180 } 181 182 function render_carbon { 183 LIMIT=$1 184 EXPECTED=$2 185 EXPECTED_HEADER=$3 186 trap clean_headers EXIT 187 188 start=$(($t)) 189 end=$(($start+200)) 190 RESPONSE=$(curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive:false" \ 191 "http://localhost:7201/api/v1/graphite/render?target=countSeries($GRAPHITE.*.*)&from=$start&until=$end") 192 ACTUAL=$(echo $RESPONSE | jq .[0].datapoints[0][0]) 193 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 194 test "$ACTUAL" = "$EXPECTED" 195 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 196 } 197 198 function find_carbon { 199 LIMIT=$1 200 EXPECTED_HEADER=$2 201 trap clean_headers EXIT 202 203 RESPONSE=$(curl -sSL -D $HEADER_FILE -H "M3-Limit-Max-Series:$LIMIT" -H "M3-Limit-Require-Exhaustive: false" \ 204 "http://localhost:7201/api/v1/graphite/metrics/find?query=$GRAPHITE.*") 205 ACTUAL_HEADER=$(cat $HEADER_FILE | grep M3-Results-Limited | cut -d' ' -f2 | tr -d "\r\n") 206 test "$ACTUAL_HEADER" = "$EXPECTED_HEADER" 207 } 208 209 function test_fanout_warning_fetch { 210 METRIC_NAME="foo_$t" 211 export INSTANT_NAME=$METRIC_NAME 212 # # write 5 metrics to cluster a 213 write_metrics coordinator-cluster-a 5 214 # unlimited query against cluster a has no header 215 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 5 "/m3query" 216 # limited query against cluster a has header 217 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 4 4 "/m3query" max_fetch_series_limit_applied 218 # unlimited query against cluster a has no header 219 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 5 "/prometheus" 220 # limited query against cluster a has header 221 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 4 4 "/prometheus" max_fetch_series_limit_applied 222 223 # write 10 metrics to cluster b 224 write_metrics coordinator-cluster-b 10 225 # unlimited query against cluster a has no header 226 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 15 "/m3query" 227 # remote limited query against cluster a has header 228 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 9 14 "/m3query" max_fetch_series_limit_applied 229 # unlimited query against cluster a has no header 230 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 15 "/prometheus" 231 # remote limited query against cluster a has header 232 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 9 14 "/prometheus" max_fetch_series_limit_applied 233 } 234 235 function test_fanout_warning_fetch_instantaneous { 236 METRIC_NAME="bar_$t" 237 export RANGE_NAME=$METRIC_NAME 238 # write 5 metrics to cluster a 239 write_metrics coordinator-cluster-a 5 240 # unlimited query against cluster a has no header 241 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 100 5 242 # limited query against cluster a has header 243 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 4 4 max_fetch_series_limit_applied 244 245 # write 10 metrics to cluster b 246 write_metrics coordinator-cluster-b 10 247 # unlimited query against cluster a has no header 248 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 100 15 249 # remote limited query against cluster a has header 250 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 9 14 max_fetch_series_limit_applied 251 } 252 253 function test_fanout_warning_search { 254 METRIC_NAME="baz_$t" 255 export SEARCH_NAME=$METRIC_NAME 256 # write 5 metrics to cluster a 257 write_metrics coordinator-cluster-a 5 258 # unlimited query against cluster a has no header 259 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 1000 260 # limited query against cluster a has header 261 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 4 max_fetch_series_limit_applied 262 263 # write 10 metrics to cluster b 264 write_metrics coordinator-cluster-b 10 265 # unlimited query against cluster a has no header 266 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 1000 267 # remote limited query against cluster a has header 268 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 4 max_fetch_series_limit_applied 269 } 270 271 function test_fanout_warning_match { 272 METRIC_NAME="qux_$t" 273 export MATCH_NAME=$METRIC_NAME 274 # write 5 metrics to cluster a 275 write_metrics coordinator-cluster-a 5 276 # unlimited query against cluster a has no header 277 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 6 5 278 # limited query against cluster a has header 279 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 4 4 max_fetch_series_limit_applied 280 281 # write 10 metrics to cluster b 282 write_metrics coordinator-cluster-b 10 283 # unlimited query against cluster a has no header 284 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 11 10 285 # remote limited query against cluster a has header 286 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 9 9 max_fetch_series_limit_applied 287 } 288 289 function test_fanout_warning_labels { 290 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_labels 100 291 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_labels 1 max_fetch_series_limit_applied 292 } 293 294 function test_fanout_warning_label_values { 295 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_label_values 100 296 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_label_values 1 max_fetch_series_limit_applied 297 } 298 299 function test_fanout_warning_fetch_id_mismatch { 300 METRIC_NAME="foo_$t" 301 export INSTANT_NAME=$METRIC_NAME 302 # # write 5 metrics to cluster a 303 write_metrics coordinator-cluster-a 5 304 # unlimited query against cluster a has no header 305 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 5 "/m3query" 306 # limited query against cluster a has header 307 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 4 4 "/m3query" max_fetch_series_limit_applied 308 # unlimited query against cluster a has no header 309 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 5 "/prometheus" 310 # limited query against cluster a has header 311 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 4 4 "/prometheus" max_fetch_series_limit_applied 312 313 # write 10 metrics to cluster b 314 write_metrics coordinator-cluster-b 10 315 # unlimited query against cluster a has no header 316 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 15 "/m3query" 317 # remote limited query against cluster a has header 318 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 9 14 "/m3query" max_fetch_series_limit_applied 319 # unlimited query against cluster a has no header 320 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 15 "/prometheus" 321 # remote limited query against cluster a has header 322 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 9 14 "/prometheus" max_fetch_series_limit_applied 323 } 324 325 function test_fanout_warning_graphite { 326 # Update write time as it will otherwise not be written correctly. 327 t=$(date +%s) 328 # write 5 metrics to cluster a 329 write_carbon coordinator-cluster-a 5 330 # unlimited query against cluster a has no header 331 ATTEMPTS=8 TIMEOUT=1 retry_with_backoff render_carbon 6 5 332 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 6 333 # limited query against cluster a has header 334 ATTEMPTS=8 TIMEOUT=1 retry_with_backoff render_carbon 4 4 max_fetch_series_limit_applied 335 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 4 max_fetch_series_limit_applied 336 337 # Update write time as it will otherwise not be written correctly. 338 t=$(date +%s) 339 # write 10 metrics to cluster b 340 write_carbon coordinator-cluster-b 10 341 # unlimited query against cluster a has no header 342 ATTEMPTS=8 TIMEOUT=1 retry_with_backoff render_carbon 16 15 343 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 16 344 # remote limited query against cluster a has header 345 ATTEMPTS=8 TIMEOUT=1 retry_with_backoff render_carbon 9 14 max_fetch_series_limit_applied 346 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 9 max_fetch_series_limit_applied 347 } 348 349 function verify_range { 350 RANGE=$1 351 PORT=$2 352 EXPECTED=$3 353 start=$(( $t - 3000 )) 354 end=$(( $t + 3000 )) 355 qs="query=sum_over_time($METRIC_NAME[$RANGE])&start=$start&end=$end&step=1s" 356 query="http://0.0.0.0:$PORT/prometheus/api/v1/query_range?$qs" 357 curl -sSLg -D $HEADER_FILE "$query" > /dev/null 358 warn=$(cat $HEADER_FILE | grep M3-Results-Limited | sed 's/M3-Results-Limited: //g') 359 warn=$(echo $warn | sed 's/ /_/g') 360 test $warn=$EXPECTED 361 } 362 363 function test_fanout_warning_range { 364 t=$(date +%s) 365 METRIC_NAME="quart_$t" 366 curl -X POST 0.0.0.0:9003/writetagged -d '{ 367 "namespace": "agg", 368 "id": "{__name__=\"'$METRIC_NAME'\",cluster=\"coordinator-cluster-a\",val=\"1\"}", 369 "tags": [ 370 { 371 "name": "__name__", 372 "value": "'$METRIC_NAME'" 373 }, 374 { 375 "name": "cluster", 376 "value": "coordinator-cluster-a" 377 }, 378 { 379 "name": "val", 380 "value": "1" 381 } 382 ], 383 "datapoint": { 384 "timestamp":'"$t"', 385 "value": 1 386 } 387 }' 388 389 390 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff verify_range 1s 7201 resolution_larger_than_query_range_range:_1s,_resolutions:_5s 391 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff verify_range 1s 17201 resolution_larger_than_query_range_range:_1s,_resolutions:_5s 392 393 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff verify_range 10s 7201 394 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff verify_range 10s 17201 395 } 396 397 function test_fanout_warning_missing_zone { 398 docker-compose -f ${COMPOSE_FILE} stop coordinator-cluster-c 399 400 METRIC_NAME=$INSTANT_NAME 401 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 100 15 remote_store_cluster-c_fetch_data_error 402 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_instant_query 9 14 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 403 404 METRIC_NAME=$RANGE_NAME 405 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 100 15 remote_store_cluster-c_fetch_data_error 406 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_range_query 9 14 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 407 408 METRIC_NAME=$SEARCH_NAME 409 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 1000 remote_store_cluster-c_fetch_data_error 410 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_search 4 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 411 412 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_labels 100 remote_store_cluster-c_fetch_data_error 413 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_labels 1 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 414 415 METRIC_NAME=$MATCH_NAME 416 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 11 10 remote_store_cluster-c_fetch_data_error 417 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_match 9 9 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 418 419 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_label_values 100 remote_store_cluster-c_fetch_data_error 420 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff test_label_values 1 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 421 422 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff render_carbon 16 15 remote_store_cluster-c_fetch_data_error 423 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff render_carbon 9 14 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 424 425 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 16 remote_store_cluster-c_fetch_data_error 426 ATTEMPTS=3 TIMEOUT=1 retry_with_backoff find_carbon 9 max_fetch_series_limit_applied,remote_store_cluster-c_fetch_data_error 427 428 docker-compose -f ${COMPOSE_FILE} start coordinator-cluster-c 429 } 430 431 function test_fanout_warnings { 432 test_fanout_warning_fetch 433 test_fanout_warning_fetch_instantaneous 434 test_fanout_warning_search 435 test_fanout_warning_match 436 test_fanout_warning_labels 437 test_fanout_warning_label_values 438 test_fanout_warning_fetch_id_mismatch 439 export GRAPHITE="foo.bar.$t" 440 test_fanout_warning_graphite 441 test_fanout_warning_range 442 test_fanout_warning_missing_zone 443 }