|
| 1 | +# Copyright 2010 New Relic, Inc. |
| 2 | +# |
| 3 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +# you may not use this file except in compliance with the License. |
| 5 | +# You may obtain a copy of the License at |
| 6 | +# |
| 7 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +# |
| 9 | +# Unless required by applicable law or agreed to in writing, software |
| 10 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +# See the License for the specific language governing permissions and |
| 13 | +# limitations under the License. |
| 14 | + |
| 15 | +from opentelemetry import trace as otel_api_trace |
| 16 | + |
| 17 | +from newrelic.api.application import application_instance |
| 18 | +from newrelic.api.transaction import current_transaction |
| 19 | +from newrelic.api.time_trace import current_trace |
| 20 | +from newrelic.api.background_task import BackgroundTask |
| 21 | +from newrelic.api.function_trace import FunctionTrace |
| 22 | +from newrelic.api.external_trace import ExternalTrace |
| 23 | + |
| 24 | +from testing_support.validators.validate_transaction_count import validate_transaction_count |
| 25 | +from testing_support.validators.validate_transaction_metrics import validate_transaction_metrics |
| 26 | +from testing_support.validators.validate_span_events import validate_span_events |
| 27 | +from testing_support.validators.validate_error_event_attributes import validate_error_event_attributes |
| 28 | + |
| 29 | +tracer = otel_api_trace.get_tracer(__name__) |
| 30 | + |
| 31 | + |
| 32 | +# Does not create segment without a transaction |
| 33 | +@validate_transaction_count(0) |
| 34 | +def test_Does_not_create_segment_without_a_transaction(): |
| 35 | + with tracer.start_as_current_span(name="Bar", kind=otel_api_trace.SpanKind.INTERNAL): |
| 36 | + # The OpenTelmetry span should not be created |
| 37 | + assert otel_api_trace.get_current_span() == otel_api_trace.INVALID_SPAN |
| 38 | + |
| 39 | + # There should be no transaction |
| 40 | + assert not current_transaction() |
| 41 | + |
| 42 | + |
| 43 | +# Creates OpenTelemetry segment in a transaction |
| 44 | +@validate_transaction_metrics(name="Foo", background_task=True) |
| 45 | +@validate_span_events( |
| 46 | + exact_intrinsics={ |
| 47 | + "name": "Function/Bar", |
| 48 | + "category": "generic", |
| 49 | + }, |
| 50 | + expected_intrinsics=("parentId",) |
| 51 | +) |
| 52 | +@validate_span_events( |
| 53 | + exact_intrinsics={ |
| 54 | + "name": "Function/Foo", |
| 55 | + "category": "generic", |
| 56 | + "nr.entryPoint": True |
| 57 | + }, |
| 58 | +) |
| 59 | +def test_Creates_OpenTelemetry_segment_in_a_transaction(): |
| 60 | + application = application_instance(activate=False) |
| 61 | + |
| 62 | + with BackgroundTask(application, name="Foo"): |
| 63 | + with tracer.start_as_current_span(name="Bar", kind=otel_api_trace.SpanKind.INTERNAL): |
| 64 | + # OpenTelemetry API and New Relic API report the same traceId |
| 65 | + assert otel_api_trace.get_current_span().get_span_context().trace_id == int(current_transaction()._trace_id, 16) |
| 66 | + |
| 67 | + # OpenTelemetry API and New Relic API report the same spanId |
| 68 | + assert otel_api_trace.get_current_span().get_span_context().span_id == int(current_trace().guid, 16) |
| 69 | + |
| 70 | + |
| 71 | +# Creates New Relic span as child of OpenTelemetry span |
| 72 | +@validate_transaction_metrics(name="Foo", background_task=True) |
| 73 | +@validate_span_events( |
| 74 | + exact_intrinsics={ |
| 75 | + "name": "Function/Baz", |
| 76 | + "category": "generic", |
| 77 | + }, |
| 78 | + expected_intrinsics=("parentId",) |
| 79 | +) |
| 80 | +@validate_span_events( |
| 81 | + exact_intrinsics={ |
| 82 | + "name": "Function/Bar", |
| 83 | + "category": "generic", |
| 84 | + }, |
| 85 | + expected_intrinsics=("parentId",) |
| 86 | +) |
| 87 | +@validate_span_events( |
| 88 | + exact_intrinsics={ |
| 89 | + "name": "Function/Foo", |
| 90 | + "category": "generic", |
| 91 | + }, |
| 92 | +) |
| 93 | +def test_Creates_New_Relic_span_as_child_of_OpenTelemetry_span(): |
| 94 | + application = application_instance(activate=False) |
| 95 | + |
| 96 | + with BackgroundTask(application, name="Foo"): |
| 97 | + with tracer.start_as_current_span(name="Bar", kind=otel_api_trace.SpanKind.INTERNAL): |
| 98 | + with FunctionTrace(name="Baz"): |
| 99 | + # OpenTelemetry API and New Relic API report the same traceId |
| 100 | + assert otel_api_trace.get_current_span().get_span_context().trace_id == int(current_transaction()._trace_id, 16) |
| 101 | + |
| 102 | + # OpenTelemetry API and New Relic API report the same spanId |
| 103 | + assert otel_api_trace.get_current_span().get_span_context().span_id == int(current_trace().guid, 16) |
| 104 | + |
| 105 | + |
| 106 | +# OpenTelemetry API can add custom attributes to spans |
| 107 | +@validate_transaction_metrics(name="Foo", background_task=True) |
| 108 | +@validate_span_events( |
| 109 | + exact_intrinsics={ |
| 110 | + "name": "Function/Baz", |
| 111 | + }, |
| 112 | + exact_users={"spanNumber": 2} |
| 113 | +) |
| 114 | +@validate_span_events( |
| 115 | + exact_intrinsics={ |
| 116 | + "name": "Function/Bar", |
| 117 | + }, |
| 118 | + exact_users={"spanNumber": 1} |
| 119 | +) |
| 120 | +def test_OpenTelemetry_API_can_add_custom_attributes_to_spans(): |
| 121 | + application = application_instance(activate=False) |
| 122 | + |
| 123 | + with BackgroundTask(application, name="Foo"): |
| 124 | + with tracer.start_as_current_span(name="Bar", kind=otel_api_trace.SpanKind.INTERNAL): |
| 125 | + with FunctionTrace(name="Baz"): |
| 126 | + otel_api_trace.get_current_span().set_attribute("spanNumber", 2) |
| 127 | + |
| 128 | + otel_api_trace.get_current_span().set_attribute("spanNumber", 1) |
| 129 | + |
| 130 | + |
| 131 | +# OpenTelemetry API can record errors |
| 132 | +@validate_transaction_metrics(name="Foo", background_task=True) |
| 133 | +@validate_error_event_attributes( |
| 134 | + exact_attrs={ |
| 135 | + "agent": {}, |
| 136 | + "intrinsic": { |
| 137 | + "error.message": "Test exception message" |
| 138 | + }, |
| 139 | + "user": {}, |
| 140 | + }, |
| 141 | +) |
| 142 | +@validate_span_events( |
| 143 | + exact_intrinsics={ |
| 144 | + "name": "Function/Bar", |
| 145 | + }, |
| 146 | +) |
| 147 | +def test_OpenTelemetry_API_can_record_errors(): |
| 148 | + application = application_instance(activate=False) |
| 149 | + |
| 150 | + with BackgroundTask(application, name="Foo"): |
| 151 | + with tracer.start_as_current_span(name="Bar", kind=otel_api_trace.SpanKind.INTERNAL): |
| 152 | + try: |
| 153 | + raise Exception("Test exception message") |
| 154 | + except Exception as e: |
| 155 | + otel_api_trace.get_current_span().record_exception(e) |
| 156 | + |
| 157 | + |
0 commit comments