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  }