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()
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()