def test_third_party_instrumentor(self, telemetry: TelemetryFixture):
        import requests
        from telemetry.api.listeners.span import LabelAttributes, InstrumentorSpanListener

        RequestsInstrumentor().instrument()

        telemetry.initialize()
        telemetry.add_span_processor(InstrumentorSpanListener(
            LabelAttributes('component', 'http.status_code', 'http.method'), 'requests'))

        responses.add_passthru('http://localhost:1234/does_not_exist')

        with telemetry.span('test_category', 'span1', attributes={TestAttributes.LABEL1: 'l1'}) as span:
            try:
                with requests.get('http://localhost:1234/does_not_exist') as response:
                    pass
            except:
                pass

        telemetry.collect()

        assert telemetry.get_value_recorder(name='trace.duration',
                                            labels={'component': 'http',
                                                    'http.method': 'GET',
                                                    TestAttributes.LABEL1.name: 'l1',
                                                    Attributes.TRACE_CATEGORY.name: 'requests',
                                                    Attributes.TRACE_NAME.name: 'requests.HTTP GET',
                                                    Attributes.TRACE_STATUS.name: 'ERROR'}).count == 1
    def test_environment_attributes(self, monkeypatch,
                                    telemetry: TelemetryFixture):
        monkeypatch.setenv('METRICS_LABEL_label1', 'label1_value')
        monkeypatch.setenv('METRICS_LABEL_label2', 'label2_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB1', 'attrib1_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB2', 'attrib2_value')

        # need to initialize again after environment is updated
        telemetry.initialize()

        with telemetry.span("category1", 'span1') as span:
            logging.info("In span")

        telemetry.collect()

        assert len(
            telemetry.get_finished_spans(
                name_filter=lambda name: name == 'category1.span1',
                attribute_filter=lambda a: a.get('attrib1') == 'attrib1_value'
                and a.get('attrib2') == 'attrib2_value')) == 1

        assert telemetry.get_value_recorder('trace.duration',
                                            labels={
                                                Attributes.TRACE_CATEGORY.name:
                                                'category1',
                                                Attributes.TRACE_NAME.name:
                                                'category1.span1',
                                                Attributes.TRACE_STATUS.name:
                                                'OK',
                                                'label1': 'label1_value',
                                                'label2': 'label2_value'
                                            }).count == 1
    def test_environment_attributes_override(self, monkeypatch,
                                             telemetry: TelemetryFixture):
        monkeypatch.setenv('METRICS_LABEL_label1', 'label1_value')
        monkeypatch.setenv('METRICS_LABEL_label2', 'label2_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB1', 'attrib1_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB2', 'attrib2_value')

        # need to initialize again after environment is updated
        telemetry.initialize()

        # environment labels should win over any locally-specified labels to preserve ops behavior
        with telemetry.span("category1",
                            'span1',
                            attributes={
                                TestAttributes.ATTRIB1: 'attrib1_override',
                                TestAttributes.LABEL1: 'label1_value'
                            }) as span:
            pass

        telemetry.collect()

        spans = telemetry.get_finished_spans()
        assert len(
            telemetry.get_finished_spans(
                name_filter=lambda name: name == 'category1.span1',
                attribute_filter=lambda a: a.get('attrib1'
                                                 ) == 'attrib1_override')) == 1

        assert telemetry.get_value_recorder('trace.duration',
                                            labels={
                                                Attributes.TRACE_CATEGORY.name:
                                                'category1',
                                                Attributes.TRACE_NAME.name:
                                                'category1.span1',
                                                Attributes.TRACE_STATUS.name:
                                                'OK',
                                                TestAttributes.LABEL1.name:
                                                'label1_value',
                                                TestAttributes.LABEL2.name:
                                                'label2_value'
                                            }).count == 1

        Environment._clear()
    def test_labelger_empty(self, monkeypatch, telemetry: TelemetryFixture):
        # need to initialize again after environment is updated
        telemetry.initialize()

        with telemetry.span("category1", 'span1') as span:
            pass

        telemetry.collect()

        assert telemetry.get_value_recorder('trace.duration',
                                            labels={
                                                Attributes.TRACE_CATEGORY.name:
                                                'category1',
                                                Attributes.TRACE_NAME.name:
                                                'category1.span1',
                                                Attributes.TRACE_STATUS.name:
                                                'OK'
                                            }).count == 1

        Environment._clear()
    def test_metrics_labelged_without_span(self, monkeypatch,
                                           telemetry: TelemetryFixture):
        monkeypatch.setenv('METRICS_LABEL_label1', 'label1_value')
        monkeypatch.setenv('METRICS_LABEL_label2', 'label2_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB1', 'attrib1_value')
        monkeypatch.setenv('METRICS_ATTRIBUTE_ATTRIB2', 'attrib2_value')

        # test that we include the environment labelger by default
        telemetry.initialize()

        # environment labels should win over any locally-specified labels to preserve ops behavior
        telemetry.counter('category1',
                          'counter1',
                          1,
                          labels={'label1': 'label1_override'})
        telemetry.collect()

        assert telemetry.get_counter('category1.counter1',
                                     labels={
                                         'label1': 'label1_value',
                                         'label2': 'label2_value'
                                     }).value == 1

        Environment._clear()
Exemple #6
0
    def test_http_server(self, monkeypatch, telemetry: TelemetryFixture):
        address = 'localhost:19102'
        monkeypatch.setenv('METRICS_EXPORTERS', 'prometheus')
        monkeypatch.setenv('METRICS_PROMETHEUS_PREFIX', 'test_prefix')
        monkeypatch.setenv('METRICS_INTERVAL', '5')
        monkeypatch.setenv('METRICS_PROMETHEUS_BIND_ADDRESS', address)

        telemetry.initialize()

        http = urllib3.PoolManager()

        with telemetry.span("category1",
                            "span1",
                            attributes={
                                TestAttributes.ATTRIB1: "attrib1",
                                TestAttributes.LABEL1: 'label1'
                            }) as span:
            time.sleep(.5)

        telemetry.counter("category1", "counter1", 2.0)

        def gauge(obv: Observer):
            obv.observe(1, {Attributes.ENV: 'test'})

        telemetry.gauge("category1", "gauge", gauge)

        # wait for Prometheus collection interval to pass (METRICS_INTERVAL)
        time.sleep(5)

        telemetry.collect()

        response = http.request('GET', 'http://localhost:19102/metrics')

        def fetch_metric(name: str, labels: dict = {}):
            response = http.request('GET', 'http://localhost:19102/metrics')
            lines = response.data.decode('utf8').split('\n')

            matches = list(
                filter(lambda line: not line.startswith("#") and name in line,
                       lines))
            if len(matches) == 0:
                pytest.fail(f"Metric not found: {name}")
            elif len(matches) == 1:
                return float(matches[0].split(' ')[1])
            else:
                pytest.fail(f"More than one match for metric: {name}")

        assert fetch_metric('test_prefix_trace_duration_count') == 1.0
        assert fetch_metric('test_prefix_trace_duration_sum') >= 500

        assert fetch_metric('test_prefix_category1_gauge') == 1.0

        # double-check that metrics continue to be returned on duplicate fetches
        assert fetch_metric('test_prefix_trace_duration_count') == 1.0
        assert fetch_metric('test_prefix_trace_duration_sum') >= 500

        with telemetry.span("category1",
                            "span1",
                            attributes={
                                TestAttributes.ATTRIB1: "attrib1",
                                TestAttributes.LABEL1: 'label1'
                            }) as span:
            time.sleep(.5)

        # wait for Prometheus collection interval to pass (METRICS_INTERVAL)
        time.sleep(2)

        telemetry.collect()

        assert fetch_metric('test_prefix_trace_duration_count') == 2.0
        assert fetch_metric('test_prefix_trace_duration_sum') >= 1000

        telemetry.shutdown()