Skip to content

Commit 568eb0a

Browse files
authored
Merge pull request #1488 from newrelic/merge-main-develop-11.0.0
Merge main into develop-11.0.0
2 parents da753c9 + e395151 commit 568eb0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1808
-143
lines changed

.github/workflows/deploy.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ jobs:
113113
persist-credentials: false
114114
fetch-depth: 0
115115

116-
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # 5.6.0
116+
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # 6.0.0
117117
with:
118118
python-version: "3.12"
119119

@@ -175,13 +175,15 @@ jobs:
175175
AWS_DEFAULT_REGION: us-west-2
176176

177177
- name: Upload Package
178-
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # 1.12.4
178+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # 1.13.0
179179

180180
- name: Attest
181-
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # 2.4.0
181+
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # 3.0.0
182182
id: attest
183183
with:
184-
subject-path: ./dist/*
184+
subject-path: |
185+
./dist/*.whl
186+
./dist/*.tar.gz
185187
186188
- name: Wait for release to be available
187189
id: wait

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282

8383
steps:
8484
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0
85-
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # 5.6.0
85+
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # 6.0.0
8686
with:
8787
python-version: "3.10"
8888
architecture: x64
@@ -100,7 +100,7 @@ jobs:
100100
coverage xml
101101
102102
- name: Upload Coverage to Codecov
103-
uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # 5.5.0
103+
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # 5.5.1
104104
with:
105105
files: coverage.xml
106106
fail_ci_if_error: true

.github/workflows/trivy.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939

4040
- name: Run Trivy vulnerability scanner in repo mode
4141
if: ${{ github.event_name == 'pull_request' }}
42-
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # v0.32.0
42+
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1
4343
with:
4444
scan-type: "fs"
4545
ignore-unfixed: true
@@ -50,7 +50,7 @@ jobs:
5050

5151
- name: Run Trivy vulnerability scanner in repo mode
5252
if: ${{ github.event_name == 'schedule' }}
53-
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # v0.32.0
53+
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1
5454
with:
5555
scan-type: "fs"
5656
ignore-unfixed: true
@@ -61,6 +61,6 @@ jobs:
6161

6262
- name: Upload Trivy scan results to GitHub Security tab
6363
if: ${{ github.event_name == 'schedule' }}
64-
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.11
64+
uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.30.1
6565
with:
6666
sarif_file: "trivy-results.sarif"

newrelic/api/datastore_trace.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from newrelic.api.time_trace import TimeTrace, current_trace
1818
from newrelic.common.async_wrapper import async_wrapper as get_async_wrapper
1919
from newrelic.common.object_wrapper import FunctionWrapper, wrap_object
20+
from newrelic.core.config import global_settings
2021
from newrelic.core.datastore_node import DatastoreNode
2122

2223

@@ -86,7 +87,8 @@ def __enter__(self):
8687
self.port_path_or_id = transaction._intern_string(self.port_path_or_id)
8788
self.database_name = transaction._intern_string(self.database_name)
8889

89-
datastore_tracer_settings = transaction.settings.datastore_tracer
90+
settings = transaction.settings or global_settings()
91+
datastore_tracer_settings = settings.datastore_tracer
9092
self.instance_reporting_enabled = datastore_tracer_settings.instance_reporting.enabled
9193
self.database_name_enabled = datastore_tracer_settings.database_name_reporting.enabled
9294
return result

newrelic/api/graphql_trace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from newrelic.api.transaction import current_transaction
1919
from newrelic.common.async_wrapper import async_wrapper as get_async_wrapper
2020
from newrelic.common.object_wrapper import FunctionWrapper, wrap_object
21+
from newrelic.core.config import global_settings
2122
from newrelic.core.graphql_node import GraphQLOperationNode, GraphQLResolverNode
2223

2324

@@ -49,7 +50,7 @@ def formatted(self):
4950
transaction = current_transaction(active_only=False)
5051

5152
# Record SQL settings
52-
settings = transaction.settings
53+
settings = transaction.settings or global_settings()
5354
tt = settings.transaction_tracer
5455
self.graphql_format = tt.record_sql
5556

newrelic/api/transaction.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ def __init__(self, application, enabled=None, source=None):
285285
self.tracestate = ""
286286
self._priority = None
287287
self._sampled = None
288+
self._traceparent_sampled = None
288289

289290
self._distributed_trace_state = 0
290291

@@ -1003,16 +1004,36 @@ def _update_agent_attributes(self):
10031004
def user_attributes(self):
10041005
return create_attributes(self._custom_params, DST_ALL, self.attribute_filter)
10051006

1006-
def _compute_sampled_and_priority(self):
1007+
def sampling_algo_compute_sampled_and_priority(self):
10071008
if self._priority is None:
1008-
# truncate priority field to 6 digits past the decimal
1009+
# Truncate priority field to 6 digits past the decimal.
10091010
self._priority = float(f"{random.random():.6f}") # noqa: S311
1010-
10111011
if self._sampled is None:
10121012
self._sampled = self._application.compute_sampled()
10131013
if self._sampled:
10141014
self._priority += 1
10151015

1016+
def _compute_sampled_and_priority(self):
1017+
if self._traceparent_sampled is None:
1018+
config = "default" # Use sampling algo.
1019+
elif self._traceparent_sampled:
1020+
setting_path = "distributed_tracing.sampler.remote_parent_sampled"
1021+
config = self.settings.distributed_tracing.sampler.remote_parent_sampled
1022+
else: # self._traceparent_sampled is False.
1023+
setting_path = "distributed_tracing.sampler.remote_parent_not_sampled"
1024+
config = self.settings.distributed_tracing.sampler.remote_parent_not_sampled
1025+
1026+
if config == "always_on":
1027+
self._sampled = True
1028+
self._priority = 2.0
1029+
elif config == "always_off":
1030+
self._sampled = False
1031+
self._priority = 0
1032+
else:
1033+
if config != "default":
1034+
_logger.warning("%s=%s is not a recognized value. Using 'default' instead.", setting_path, config)
1035+
self.sampling_algo_compute_sampled_and_priority()
1036+
10161037
def _freeze_path(self):
10171038
if self._frozen_path is None:
10181039
self._name_priority = None
@@ -1311,6 +1332,7 @@ def accept_distributed_trace_headers(self, headers, transport_type="HTTP"):
13111332
else:
13121333
self._record_supportability("Supportability/TraceContext/TraceState/NoNrEntry")
13131334

1335+
self._traceparent_sampled = data.get("sa")
13141336
self._accept_distributed_trace_data(data, transport_type)
13151337
self._record_supportability("Supportability/TraceContext/Accept/Success")
13161338
return True

newrelic/common/encoding_utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
DELIMITER_FORMAT_RE = re.compile("[ \t]*,[ \t]*")
3535
PARENT_TYPE = {"0": "App", "1": "Browser", "2": "Mobile"}
3636
BASE64_DECODE_STR = getattr(base64, "decodestring", None)
37+
FLAG_SAMPLED = 1
3738

3839

3940
# Functions for encoding/decoding JSON. These wrappers are used in order
@@ -455,7 +456,10 @@ def decode(cls, payload):
455456
if parent_id == "0" * 16 or trace_id == "0" * 32:
456457
return None
457458

458-
return cls(tr=trace_id, id=parent_id)
459+
# Sampled flag
460+
sa = bool(int(fields[3], 2) & FLAG_SAMPLED)
461+
462+
return cls(tr=trace_id, id=parent_id, sa=sa)
459463

460464

461465
class W3CTraceState(OrderedDict):

newrelic/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ def _process_configuration(section):
401401
_process_setting(section, "ml_insights_events.enabled", "getboolean", None)
402402
_process_setting(section, "distributed_tracing.enabled", "getboolean", None)
403403
_process_setting(section, "distributed_tracing.exclude_newrelic_header", "getboolean", None)
404+
_process_setting(section, "distributed_tracing.sampler.remote_parent_sampled", "get", None)
405+
_process_setting(section, "distributed_tracing.sampler.remote_parent_not_sampled", "get", None)
404406
_process_setting(section, "span_events.enabled", "getboolean", None)
405407
_process_setting(section, "span_events.max_samples_stored", "getint", None)
406408
_process_setting(section, "span_events.attributes.enabled", "getboolean", None)

newrelic/core/config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ class DistributedTracingSettings(Settings):
332332
pass
333333

334334

335+
class DistributedTracingSamplerSettings(Settings):
336+
pass
337+
338+
335339
class ServerlessModeSettings(Settings):
336340
pass
337341

@@ -501,6 +505,7 @@ class EventHarvestConfigHarvestLimitSettings(Settings):
501505
_settings.datastore_tracer.instance_reporting = DatastoreTracerInstanceReportingSettings()
502506
_settings.debug = DebugSettings()
503507
_settings.distributed_tracing = DistributedTracingSettings()
508+
_settings.distributed_tracing.sampler = DistributedTracingSamplerSettings()
504509
_settings.error_collector = ErrorCollectorSettings()
505510
_settings.error_collector.attributes = ErrorCollectorAttributesSettings()
506511
_settings.event_harvest_config = EventHarvestConfigSettings()
@@ -825,6 +830,12 @@ def default_otlp_host(host):
825830
_settings.ml_insights_events.enabled = False
826831

827832
_settings.distributed_tracing.enabled = _environ_as_bool("NEW_RELIC_DISTRIBUTED_TRACING_ENABLED", default=True)
833+
_settings.distributed_tracing.sampler.remote_parent_sampled = os.environ.get(
834+
"NEW_RELIC_DISTRIBUTED_TRACING_SAMPLER_REMOTE_PARENT_SAMPLED", "default"
835+
)
836+
_settings.distributed_tracing.sampler.remote_parent_not_sampled = os.environ.get(
837+
"NEW_RELIC_DISTRIBUTED_TRACING_SAMPLER_REMOTE_PARENT_NOT_SAMPLED", "default"
838+
)
828839
_settings.distributed_tracing.exclude_newrelic_header = False
829840
_settings.span_events.enabled = _environ_as_bool("NEW_RELIC_SPAN_EVENTS_ENABLED", default=True)
830841
_settings.span_events.attributes.enabled = True

newrelic/hooks/datastore_elasticsearch.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from newrelic.api.transaction import current_transaction
1717
from newrelic.common.object_wrapper import function_wrapper, wrap_function_wrapper
1818
from newrelic.common.package_version_utils import get_package_version_tuple
19+
from newrelic.core.config import global_settings
1920

2021
# An index name can be a string, None or a sequence. In the case of None
2122
# an empty string or '*', it is the same as using '_all'. When a string
@@ -139,7 +140,8 @@ def _nr_wrapper_Elasticsearch_method_(wrapped, instance, args, kwargs):
139140
with trace:
140141
result = wrapped(*args, **kwargs)
141142

142-
tracer_settings = trace.settings.datastore_tracer
143+
settings = trace.settings or global_settings()
144+
tracer_settings = settings.datastore_tracer
143145

144146
if tracer_settings.instance_reporting.enabled:
145147
try:
@@ -182,7 +184,8 @@ async def _nr_wrapper_AsyncElasticsearch_method_(wrapped, instance, args, kwargs
182184
with trace:
183185
result = await wrapped(*args, **kwargs)
184186

185-
tracer_settings = trace.settings.datastore_tracer
187+
settings = trace.settings or global_settings()
188+
tracer_settings = settings.datastore_tracer
186189

187190
if tracer_settings.instance_reporting.enabled:
188191
try:
@@ -267,7 +270,6 @@ async def _nr_wrapper_AsyncElasticsearch_method_(wrapped, instance, args, kwargs
267270
("msearch_template", _extract_args_search_templates_index),
268271
("mtermvectors", _extract_args_index),
269272
("open_point_in_time", _extract_args_index),
270-
("options", None),
271273
("ping", None),
272274
("put_script", None),
273275
("rank_eval", _extract_args_requests_index),
@@ -783,7 +785,8 @@ def _nr_get_connection_wrapper(wrapped, instance, args, kwargs):
783785

784786
host = port_path_or_id = "unknown"
785787
try:
786-
tracer_settings = trace.settings.datastore_tracer
788+
settings = trace.settings or global_settings()
789+
tracer_settings = settings.datastore_tracer
787790

788791
if tracer_settings.instance_reporting.enabled:
789792
host, port_path_or_id = conn._nr_host_port

0 commit comments

Comments
 (0)