...

Text file src/github.com/emissary-ingress/emissary/v3/python/tests/kat/t_stats.py

Documentation: github.com/emissary-ingress/emissary/v3/python/tests/kat

     1from typing import Generator, Tuple, Union
     2
     3from abstract_tests import DEV, HTTP, AmbassadorTest, Node, ServiceType, StatsDSink
     4from kat.harness import Query
     5
     6STATSD_TEST_CLUSTER = "statsdtest_http"
     7ALT_STATSD_TEST_CLUSTER = "short-stats-name"
     8DOGSTATSD_TEST_CLUSTER = "dogstatsdtest_http"
     9
    10
    11class StatsdTest(AmbassadorTest):
    12    sink: ServiceType
    13
    14    def init(self):
    15        self.target = HTTP()
    16        self.target2 = HTTP(name="alt-statsd")
    17        self.sink = StatsDSink(target_cluster=f"{STATSD_TEST_CLUSTER}:{ALT_STATSD_TEST_CLUSTER}")
    18        self.stats_name = ALT_STATSD_TEST_CLUSTER
    19        if DEV:
    20            self.skip_node = True
    21
    22    def manifests(self) -> str:
    23        self.manifest_envs += f"""
    24    - name: STATSD_ENABLED
    25      value: 'true'
    26    - name: STATSD_HOST
    27      value: {self.sink.path.fqdn}
    28"""
    29        return super().manifests()
    30
    31    def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]:
    32        yield self.target, self.format(
    33            """
    34---
    35apiVersion: getambassador.io/v3alpha1
    36kind: Mapping
    37name:  {self.name}
    38hostname: "*"
    39prefix: /{self.name}/
    40service: http://{self.target.path.fqdn}
    41---
    42apiVersion: getambassador.io/v3alpha1
    43kind: Mapping
    44name:  {self.name}-alt
    45hostname: "*"
    46prefix: /{self.name}-alt/
    47stats_name: {self.stats_name}
    48service: http://{self.target2.path.fqdn}
    49---
    50apiVersion: getambassador.io/v3alpha1
    51kind: Mapping
    52name:  {self.name}-reset
    53hostname: "*"
    54case_sensitive: false
    55prefix: /reset/
    56rewrite: /RESET/
    57service: {self.sink.path.fqdn}
    58---
    59apiVersion: getambassador.io/v3alpha1
    60kind: Mapping
    61name:  metrics
    62hostname: "*"
    63prefix: /metrics
    64rewrite: /metrics
    65service: http://127.0.0.1:8877
    66"""
    67        )
    68
    69    def requirements(self):
    70        yield from super().requirements()
    71        yield ("url", Query(self.url("RESET/")))
    72
    73    def queries(self):
    74        for i in range(1000):
    75            yield Query(self.url(self.name + "/"), phase=1)
    76            yield Query(self.url(self.name + "-alt/"), phase=1)
    77
    78        yield Query(f"http://{self.sink.path.fqdn}/DUMP/", phase=2)
    79        yield Query(self.url("metrics"), phase=2)
    80
    81    def check(self):
    82        # self.results[-2] is the JSON dump from our test self.sink service.
    83        stats = self.results[-2].json or {}
    84
    85        cluster_stats = stats.get(STATSD_TEST_CLUSTER, {})
    86        rq_total = cluster_stats.get("upstream_rq_total", -1)
    87        rq_200 = cluster_stats.get("upstream_rq_200", -1)
    88
    89        assert rq_total == 1000, f"{STATSD_TEST_CLUSTER}: expected 1000 total calls, got {rq_total}"
    90        assert rq_200 > 990, f"{STATSD_TEST_CLUSTER}: expected 1000 successful calls, got {rq_200}"
    91
    92        cluster_stats = stats.get(ALT_STATSD_TEST_CLUSTER, {})
    93        rq_total = cluster_stats.get("upstream_rq_total", -1)
    94        rq_200 = cluster_stats.get("upstream_rq_200", -1)
    95
    96        assert (
    97            rq_total == 1000
    98        ), f"{ALT_STATSD_TEST_CLUSTER}: expected 1000 total calls, got {rq_total}"
    99        assert (
   100            rq_200 > 990
   101        ), f"{ALT_STATSD_TEST_CLUSTER}: expected 1000 successful calls, got {rq_200}"
   102
   103        # self.results[-1] is the text dump from Envoy's '/metrics' endpoint.
   104        metrics = self.results[-1].text
   105
   106        # Somewhere in here, we want to see a metric explicitly for both our "real"
   107        # cluster and our alt cluster, returning a 200. Are they there?
   108        wanted_metric = "envoy_cluster_internal_upstream_rq"
   109        wanted_status = 'envoy_response_code="200"'
   110        wanted_cluster_name = f'envoy_cluster_name="{STATSD_TEST_CLUSTER}"'
   111        alt_wanted_cluster_name = f'envoy_cluster_name="{ALT_STATSD_TEST_CLUSTER}"'
   112
   113        found_normal = False
   114        found_alt = False
   115
   116        for line in metrics.split("\n"):
   117            if wanted_metric in line and wanted_status in line and wanted_cluster_name in line:
   118                print(f"line '{line}'")
   119                found_normal = True
   120
   121            if wanted_metric in line and wanted_status in line and alt_wanted_cluster_name in line:
   122                print(f"line '{line}'")
   123                found_alt = True
   124
   125        assert (
   126            found_normal
   127        ), f"wanted {STATSD_TEST_CLUSTER} in Prometheus metrics, but didn't find it"
   128        assert (
   129            found_alt
   130        ), f"wanted {ALT_STATSD_TEST_CLUSTER} in Prometheus metrics, but didn't find it"
   131
   132
   133class DogstatsdTest(AmbassadorTest):
   134    dogstatsd: ServiceType
   135
   136    def init(self):
   137        self.target = HTTP()
   138        self.sink = StatsDSink(target_cluster=DOGSTATSD_TEST_CLUSTER)
   139        if DEV:
   140            self.skip_node = True
   141
   142    def manifests(self) -> str:
   143        self.manifest_envs += f"""
   144    - name: STATSD_ENABLED
   145      value: 'true'
   146    - name: STATSD_HOST
   147      value: {self.sink.path.fqdn}
   148    - name: DOGSTATSD
   149      value: 'true'
   150"""
   151        return super().manifests()
   152
   153    def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]:
   154        yield self.target, self.format(
   155            """
   156---
   157apiVersion: getambassador.io/v3alpha1
   158kind: Mapping
   159name:  {self.name}
   160hostname: "*"
   161prefix: /{self.name}/
   162service: http://{self.target.path.fqdn}
   163---
   164apiVersion: getambassador.io/v3alpha1
   165kind: Mapping
   166name:  {self.name}-reset
   167case_sensitive: false
   168hostname: "*"
   169prefix: /reset/
   170rewrite: /RESET/
   171service: {self.sink.path.fqdn}
   172"""
   173        )
   174
   175    def requirements(self):
   176        yield from super().requirements()
   177        yield ("url", Query(self.url("RESET/")))
   178
   179    def queries(self):
   180        for i in range(1000):
   181            yield Query(self.url(self.name + "/"), phase=1)
   182
   183        yield Query(f"http://{self.sink.path.fqdn}/DUMP/", phase=2)
   184
   185    def check(self):
   186        stats = self.results[-1].json or {}
   187
   188        cluster_stats = stats.get(DOGSTATSD_TEST_CLUSTER, {})
   189        rq_total = cluster_stats.get("upstream_rq_total", -1)
   190        rq_200 = cluster_stats.get("upstream_rq_200", -1)
   191
   192        assert rq_total == 1000, f"expected 1000 total calls, got {rq_total}"
   193        assert rq_200 > 990, f"expected 1000 successful calls, got {rq_200}"

View as plain text