Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Transaction API Tests #857

Merged
merged 13 commits into from
Jun 30, 2023
53 changes: 29 additions & 24 deletions newrelic/api/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,11 @@ def path(self):


class Transaction(object):

STATE_PENDING = 0
STATE_RUNNING = 1
STATE_STOPPED = 2

def __init__(self, application, enabled=None, source=None):

self._application = application

self._source = source
Expand Down Expand Up @@ -343,7 +341,6 @@ def __del__(self):
self.__exit__(None, None, None)

def __enter__(self):

assert self._state == self.STATE_PENDING

# Bail out if the transaction is not enabled.
Expand Down Expand Up @@ -403,7 +400,6 @@ def __enter__(self):
return self

def __exit__(self, exc, value, tb):

# Bail out if the transaction is not enabled.

if not self.enabled:
Expand Down Expand Up @@ -636,7 +632,6 @@ def __exit__(self, exc, value, tb):
# new samples can cause an error.

if not self.ignore_transaction:

self._application.record_transaction(node)

@property
Expand Down Expand Up @@ -929,9 +924,7 @@ def filter_request_parameters(self, params):
@property
def request_parameters(self):
if (self.capture_params is None) or self.capture_params:

if self._request_params:

r_attrs = {}

for k, v in self._request_params.items():
Expand Down Expand Up @@ -1095,7 +1088,6 @@ def _generate_distributed_trace_headers(self, data=None):
try:
data = data or self._create_distributed_trace_data()
if data:

traceparent = W3CTraceParent(data).text()
yield ("traceparent", traceparent)

Expand Down Expand Up @@ -1192,11 +1184,10 @@ def _accept_distributed_trace_payload(self, payload, transport_type="HTTP"):
except:
return False

if "pr" in data:
try:
data["pr"] = float(data["pr"])
except:
data["pr"] = None
try:
data["pr"] = float(data["pr"])
except:
TimPansino marked this conversation as resolved.
Show resolved Hide resolved
data["pr"] = None

self._accept_distributed_trace_data(data, transport_type)
self._record_supportability("Supportability/DistributedTrace/AcceptPayload/Success")
Expand Down Expand Up @@ -1382,7 +1373,6 @@ def _generate_response_headers(self, read_length=None):
# process web external calls.

if self.client_cross_process_id is not None:

# Need to work out queueing time and duration up to this
# point for inclusion in metrics and response header. If the
# recording of the transaction had been prematurely stopped
Expand Down Expand Up @@ -1426,11 +1416,17 @@ def _generate_response_headers(self, read_length=None):

return nr_headers

def get_response_metadata(self):
# This function is CAT related and has been deprecated.
# Eventually, this will be removed. Until then, coverage
# does not need to factor this function into its analysis.
def get_response_metadata(self): # pragma: no cover
nr_headers = dict(self._generate_response_headers())
return convert_to_cat_metadata_value(nr_headers)

def process_request_metadata(self, cat_linking_value):
# This function is CAT related and has been deprecated.
# Eventually, this will be removed. Until then, coverage
# does not need to factor this function into its analysis.
def process_request_metadata(self, cat_linking_value): # pragma: no cover
try:
payload = base64_decode(cat_linking_value)
except:
Expand All @@ -1447,7 +1443,6 @@ def process_request_metadata(self, cat_linking_value):
return self._process_incoming_cat_headers(encoded_cross_process_id, encoded_txn_header)

def set_transaction_name(self, name, group=None, priority=None):

# Always perform this operation even if the transaction
# is not active at the time as will be called from
# constructor. If path has been frozen do not allow
Expand Down Expand Up @@ -1517,7 +1512,9 @@ def record_log_event(self, message, level=None, timestamp=None, priority=None):

self._log_events.add(event, priority=priority)

def record_exception(self, exc=None, value=None, tb=None, params=None, ignore_errors=None):
# This function has been deprecated (and will be removed eventually)
# and therefore does not need to be included in coverage analysis
def record_exception(self, exc=None, value=None, tb=None, params=None, ignore_errors=None): # pragma: no cover
# Deprecation Warning
warnings.warn(
("The record_exception function is deprecated. Please use the new api named notice_error instead."),
Expand Down Expand Up @@ -1684,15 +1681,19 @@ def add_custom_attributes(self, items):

return result

def add_custom_parameter(self, name, value):
# This function has been deprecated (and will be removed eventually)
# and therefore does not need to be included in coverage analysis
def add_custom_parameter(self, name, value): # pragma: no cover
# Deprecation warning
warnings.warn(
("The add_custom_parameter API has been deprecated. " "Please use the add_custom_attribute API."),
DeprecationWarning,
)
return self.add_custom_attribute(name, value)

def add_custom_parameters(self, items):
# This function has been deprecated (and will be removed eventually)
# and therefore does not need to be included in coverage analysis
def add_custom_parameters(self, items): # pragma: no cover
# Deprecation warning
warnings.warn(
("The add_custom_parameters API has been deprecated. " "Please use the add_custom_attributes API."),
Expand Down Expand Up @@ -1796,19 +1797,23 @@ def add_custom_attributes(items):
return False


def add_custom_parameter(key, value):
# This function has been deprecated (and will be removed eventually)
# and therefore does not need to be included in coverage analysis
def add_custom_parameter(key, value): # pragma: no cover
# Deprecation warning
warnings.warn(
("The add_custom_parameter API has been deprecated. " "Please use the add_custom_attribute API."),
("The add_custom_parameter API has been deprecated. Please use the add_custom_attribute API."),
DeprecationWarning,
)
return add_custom_attribute(key, value)


def add_custom_parameters(items):
# This function has been deprecated (and will be removed eventually)
# and therefore does not need to be included in coverage analysis
def add_custom_parameters(items): # pragma: no cover
# Deprecation warning
warnings.warn(
("The add_custom_parameters API has been deprecated. " "Please use the add_custom_attributes API."),
("The add_custom_parameters API has been deprecated. Please use the add_custom_attributes API."),
DeprecationWarning,
)
return add_custom_attributes(items)
Expand Down
31 changes: 24 additions & 7 deletions tests/agent_features/test_apdex_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,41 @@
# limitations under the License.

import webtest

from testing_support.validators.validate_apdex_metrics import (
validate_apdex_metrics)
from testing_support.sample_applications import simple_app
from testing_support.validators.validate_apdex_metrics import validate_apdex_metrics

from newrelic.api.transaction import current_transaction, suppress_apdex_metric
from newrelic.api.wsgi_application import wsgi_application

normal_application = webtest.TestApp(simple_app)


# NOTE: This test validates that the server-side apdex_t is set to 0.5
# If the server-side configuration changes, this test will start to fail.


@validate_apdex_metrics(
name='',
group='Uri',
name="",
group="Uri",
apdex_t_min=0.5,
apdex_t_max=0.5,
)
def test_apdex():
normal_application.get('/')
normal_application.get("/")


# This has to be a Web Transaction.
# The apdex measurement only applies to Web Transactions
def test_apdex_suppression():
@wsgi_application()
def simple_apdex_supression_app(environ, start_response):
suppress_apdex_metric()

start_response(status="200 OK", response_headers=[])
transaction = current_transaction()

assert transaction.suppress_apdex
assert transaction.apdex == 0
return []

apdex_suppression_app = webtest.TestApp(simple_apdex_supression_app)
apdex_suppression_app.get("/")
62 changes: 62 additions & 0 deletions tests/agent_features/test_custom_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2010 New Relic, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from testing_support.fixtures import reset_core_stats_engine
from testing_support.validators.validate_custom_metrics_outside_transaction import (
validate_custom_metrics_outside_transaction,
)

from newrelic.api.application import application_instance as application
from newrelic.api.background_task import background_task
from newrelic.api.transaction import (
current_transaction,
record_custom_metric,
record_custom_metrics,
)


# Testing record_custom_metric
@reset_core_stats_engine()
@background_task()
def test_custom_metric_inside_transaction():
transaction = current_transaction()
record_custom_metric("CustomMetric/InsideTransaction/Count", 1)
for metric in transaction._custom_metrics.metrics():
assert metric == ("CustomMetric/InsideTransaction/Count", [1, 1, 1, 1, 1, 1])


@reset_core_stats_engine()
@validate_custom_metrics_outside_transaction([("CustomMetric/OutsideTransaction/Count", 1)])
@background_task()
def test_custom_metric_outside_transaction_with_app():
app = application()
record_custom_metric("CustomMetric/OutsideTransaction/Count", 1, application=app)


# Testing record_custom_metricS
@reset_core_stats_engine()
@background_task()
def test_custom_metrics_inside_transaction():
transaction = current_transaction()
record_custom_metrics([("CustomMetrics/InsideTransaction/Count", 1)])
for metric in transaction._custom_metrics.metrics():
assert metric == ("CustomMetrics/InsideTransaction/Count", [1, 1, 1, 1, 1, 1])


@reset_core_stats_engine()
@validate_custom_metrics_outside_transaction([("CustomMetrics/OutsideTransaction/Count", 1)])
@background_task()
def test_custom_metrics_outside_transaction_with_app():
app = application()
record_custom_metrics([("CustomMetrics/OutsideTransaction/Count", 1)], application=app)
11 changes: 6 additions & 5 deletions tests/agent_features/test_distributed_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
from newrelic.api.background_task import BackgroundTask, background_task
from newrelic.api.time_trace import current_trace
from newrelic.api.transaction import (
accept_distributed_trace_headers,
accept_distributed_trace_payload,
create_distributed_trace_payload,
current_span_id,
current_trace_id,
current_transaction,
Expand Down Expand Up @@ -185,10 +188,10 @@ def _test():
payload["d"]["pa"] = "5e5733a911cfbc73"

if accept_payload:
result = txn.accept_distributed_trace_payload(payload)
result = accept_distributed_trace_payload(payload)
assert result
else:
txn._create_distributed_trace_payload()
create_distributed_trace_payload()

try:
raise ValueError("cookies")
Expand Down Expand Up @@ -319,7 +322,6 @@ def _test():
)
@override_application_settings(_override_settings)
def test_distributed_tracing_backwards_compatibility(traceparent, tracestate, newrelic, metrics):

headers = []
if traceparent:
headers.append(("traceparent", TRACEPARENT))
Expand All @@ -333,8 +335,7 @@ def test_distributed_tracing_backwards_compatibility(traceparent, tracestate, ne
)
@background_task(name="test_distributed_tracing_backwards_compatibility")
def _test():
transaction = current_transaction()
transaction.accept_distributed_trace_headers(headers)
accept_distributed_trace_headers(headers)

_test()

Expand Down
Loading