Classifying Metrics Based on Request or Response

It’s useful to visualize telemetry based on the type of requests and responses handled by services in your mesh. For example, a bookseller tracks the number of times book reviews are requested. A book review request has this structure:

  1. GET /reviews/{review_id}

Counting the number of review requests must account for the unbounded element review_id. GET /reviews/1 followed by GET /reviews/2 should count as two requests to get reviews.

Istio lets you create classification rules using the AttributeGen plugin that groups requests into a fixed number of logical operations. For example, you can create an operation named GetReviews, which is a common way to identify operations using the Open API Spec operationId. This information is injected into request processing as istio_operationId attribute with value equal to GetReviews. You can use the attribute as a dimension in Istio standard metrics. Similarly, you can track metrics based on other operations like ListReviews and CreateReviews.

Classify metrics by request

You can classify requests based on their type, for example ListReview, GetReview, CreateReview.

  1. Create a file, for example attribute_gen_service.yaml, and save it with the following contents. This adds the istio.attributegen plugin. It also creates an attribute, istio_operationId and populates it with values for the categories to count as metrics.

    This configuration is service-specific since request paths are typically service-specific.

    1. apiVersion: extensions.istio.io/v1alpha1
    2. kind: WasmPlugin
    3. metadata:
    4. name: istio-attributegen-filter
    5. spec:
    6. selector:
    7. matchLabels:
    8. app: reviews
    9. url: https://storage.googleapis.com/istio-build/proxy/attributegen-359dcd3a19f109c50e97517fe6b1e2676e870c4d.wasm
    10. imagePullPolicy: Always
    11. phase: AUTHN
    12. pluginConfig:
    13. attributes:
    14. - output_attribute: "istio_operationId"
    15. match:
    16. - value: "ListReviews"
    17. condition: "request.url_path == '/reviews' && request.method == 'GET'"
    18. - value: "GetReview"
    19. condition: "request.url_path.matches('^/reviews/[[:alnum:]]*$') && request.method == 'GET'"
    20. - value: "CreateReview"
    21. condition: "request.url_path == '/reviews/' && request.method == 'POST'"
    22. ---
    23. apiVersion: telemetry.istio.io/v1alpha1
    24. kind: Telemetry
    25. metadata:
    26. name: custom-tags
    27. spec:
    28. metrics:
    29. - overrides:
    30. - match:
    31. metric: REQUEST_COUNT
    32. mode: CLIENT_AND_SERVER
    33. tagOverrides:
    34. request_operation:
    35. value: istio_operationId
    36. providers:
    37. - name: prometheus
  2. Apply your changes using the following command:

    1. $ kubectl -n istio-system apply -f attribute_gen_service.yaml
  3. After the changes take effect, visit Prometheus and look for the new or changed dimensions, for example istio_requests_total in reviews pods.

Classify metrics by response

You can classify responses using a similar process as requests. Do note that the response_code dimension already exists by default. The example below will change how it is populated.

  1. Create a file, for example attribute_gen_service.yaml, and save it with the following contents. This adds the istio.attributegen plugin and generates the istio_responseClass attribute used by the stats plugin.

    This example classifies various responses, such as grouping all response codes in the 200 range as a 2xx dimension.

    1. apiVersion: extensions.istio.io/v1alpha1
    2. kind: WasmPlugin
    3. metadata:
    4. name: istio-attributegen-filter
    5. spec:
    6. selector:
    7. matchLabels:
    8. app: productpage
    9. url: https://storage.googleapis.com/istio-build/proxy/attributegen-359dcd3a19f109c50e97517fe6b1e2676e870c4d.wasm
    10. imagePullPolicy: Always
    11. phase: AUTHN
    12. pluginConfig:
    13. attributes:
    14. - output_attribute: istio_responseClass
    15. match:
    16. - value: 2xx
    17. condition: response.code >= 200 && response.code <= 299
    18. - value: 3xx
    19. condition: response.code >= 300 && response.code <= 399
    20. - value: "404"
    21. condition: response.code == 404
    22. - value: "429"
    23. condition: response.code == 429
    24. - value: "503"
    25. condition: response.code == 503
    26. - value: 5xx
    27. condition: response.code >= 500 && response.code <= 599
    28. - value: 4xx
    29. condition: response.code >= 400 && response.code <= 499
    30. ---
    31. apiVersion: telemetry.istio.io/v1alpha1
    32. kind: Telemetry
    33. metadata:
    34. name: custom-tags
    35. spec:
    36. metrics:
    37. - overrides:
    38. - match:
    39. metric: REQUEST_COUNT
    40. mode: CLIENT_AND_SERVER
    41. tagOverrides:
    42. response_code:
    43. value: istio_responseClass
    44. providers:
    45. - name: prometheus
  2. Apply your changes using the following command:

    1. $ kubectl -n istio-system apply -f attribute_gen_service.yaml

Verify the results

  1. Generate metrics by sending traffic to your application.

  2. Visit Prometheus and look for the new or changed dimensions, for example 2xx. Alternatively, use the following command to verify that Istio generates the data for your new dimension:

    1. $ kubectl exec pod-name -c istio-proxy -- curl -sS 'localhost:15000/stats/prometheus' | grep istio_

    In the output, locate the metric (e.g. istio_requests_total) and verify the presence of the new or changed dimension.

Troubleshooting

If classification does not occur as expected, check the following potential causes and resolutions.

Review the Envoy proxy logs for the pod that has the service on which you applied the configuration change. Check that there are no errors reported by the service in the Envoy proxy logs on the pod, (pod-name), where you configured classification by using the following command:

  1. $ kubectl logs pod-name -c istio-proxy | grep -e "Config Error" -e "envoy wasm"

Additionally, ensure that there are no Envoy proxy crashes by looking for signs of restarts in the output of the following command:

  1. $ kubectl get pods pod-name