Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a512254

Browse files
authoredJan 14, 2021
Merge branch 'master' into grpc-streaming-bugfix
2 parents 863a003 + d12f67f commit a512254

File tree

35 files changed

+254
-63
lines changed

35 files changed

+254
-63
lines changed
 

‎.github/workflows/codeql-analysis.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: CodeQL Analysis
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
# ┌───────────── minute (0 - 59)
7+
# │ ┌───────────── hour (0 - 23)
8+
# │ │ ┌───────────── day of the month (1 - 31)
9+
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
10+
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
11+
# │ │ │ │ │
12+
# │ │ │ │ │
13+
# │ │ │ │ │
14+
# * * * * *
15+
- cron: '30 1 * * *'
16+
17+
jobs:
18+
CodeQL-Build:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v2
24+
25+
# Initializes the CodeQL tools for scanning.
26+
- name: Initialize CodeQL
27+
uses: github/codeql-action/init@v1
28+
with:
29+
languages: python
30+
31+
- name: Autobuild
32+
uses: github/codeql-action/autobuild@v1
33+
34+
- name: Perform CodeQL Analysis
35+
uses: github/codeql-action/analyze@v1

‎.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
- 'release/*'
77
pull_request:
88
env:
9-
CORE_REPO_SHA: master
9+
CORE_REPO_SHA: 2b188b9a43dfaa74c1a0a4514b91d1cb07d3075d
1010

1111
jobs:
1212
build:

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ __pycache__
2323
venv*/
2424
.venv*/
2525
opentelemetry-python-core*/
26+
/opentelemetry-python-core
2627

2728
# Installer logs
2829
pip-log.txt

‎.isort.cfg

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ include_trailing_comma=True
33
force_grid_wrap=0
44
use_parentheses=True
55
line_length=79
6+
profile=black
67

78
; 3 stands for Vertical Hanging Indent, e.g.
89
; from third_party import (
@@ -13,6 +14,6 @@ line_length=79
1314
; docs: https://github.com/timothycrosley/isort#multi-line-output-modes
1415
multi_line_output=3
1516
skip=target
16-
skip_glob=**/gen/*,.venv*/*,venv*/*,reference*/*,opentelemetry-python-core/*
17+
skip_glob=**/gen/*,.venv*/*,venv*/*,reference*/*,opentelemetry-python-core/*,.tox/*
1718
known_first_party=opentelemetry
1819
known_third_party=psutil,pytest,redis,redis_opentracing

‎.pylintrc

+10-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ disable=missing-docstring,
7070
wrong-import-order, # Leave this up to isort
7171
bad-continuation, # Leave this up to black
7272
line-too-long, # Leave this up to black
73-
exec-used
73+
exec-used,
74+
super-with-arguments, # temp-pylint-upgrade
75+
isinstance-second-argument-not-valid-type, # temp-pylint-upgrade
76+
raise-missing-from, # temp-pylint-upgrade
77+
unused-argument, # temp-pylint-upgrade
78+
protected-access, # temp-pylint-upgrade
79+
super-init-not-called, # temp-pylint-upgrade
80+
invalid-overridden-method, # temp-pylint-upgrade
81+
missing-module-docstring, # temp-pylint-upgrad, # temp-pylint-upgradee
7482

7583
# Enable the message, report, category or checker with the given id(s). You can
7684
# either give multiple identifier separated by comma (,) or put this option
@@ -165,7 +173,7 @@ contextmanager-decorators=contextlib.contextmanager
165173
# List of members which are set dynamically and missed by pylint inference
166174
# system, and so shouldn't trigger E1101 when accessed. Python regular
167175
# expressions are accepted.
168-
generated-members=*_pb2.py
176+
generated-members=types_pb2.*
169177

170178
# Tells whether missing members accessed in mixin class should be ignored. A
171179
# mixin class is detected if its name ends with "mixin" (case insensitive).

‎CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python-contrib/compare/v0.16b1...HEAD)
88

99
### Added
10+
- `opentelemetry-instrumentation-sqlalchemy` Ensure spans have kind set to "CLIENT"
11+
([#278](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/278))
1012
- `opentelemetry-instrumentation-celery` Add support for Celery version 5.x
1113
([#266](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/266))
1214
- `opentelemetry-instrumentation-urllib` Add urllib instrumentation
@@ -33,6 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3335
([#236](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/236))
3436
- Add README and example app for Prometheus Remote Write Exporter
3537
([#227](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/227]))
38+
- `opentelemetry-instrumentation-botocore` Adds a field to report the number of retries it take to complete an API call
39+
([#275](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/275))
40+
- `opentelemetry-instrumentation-requests` Use instanceof to check if responses are valid Response objects
41+
([#273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/273))
3642

3743
### Changed
3844
- `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-wsgi` Return `None` for `CarrierGetter` if key not found
@@ -47,6 +53,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4753
([#259](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/259))
4854
- `opentelemetry-instrumentation-grpc` Fix issue tracking child spans in streaming responses
4955
([#260](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/260))
56+
- `opentelemetry-exporter-datadog` Fix unintentional type change of span trace flags
57+
([#261](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/261))
58+
- `opentelemetry-instrumentation-aiopg` Fix AttributeError `__aexit__` when `aiopg.connect` and `aio[g].create_pool` used with async context manager
59+
([#235](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/235))
60+
- `opentelemetry-exporter-datadog` `opentelemetry-sdk-extension-aws` Fix reference to ids_generator in sdk
61+
([#235](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/235))
5062

5163
## [0.16b1](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.16b1) - 2020-11-26
5264

‎dev-requirements.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
pylint==2.4.4
1+
pylint~=2.6
22
flake8~=3.7
3-
isort~=4.3
3+
isort~=5.6
44
black>=19.3b0,==19.*
5-
mypy==0.740
5+
httpretty~=1.0
6+
mypy==0.790
67
sphinx~=2.1
78
sphinx-rtd-theme~=0.4
89
sphinx-autodoc-typehints~=1.10.2

‎exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@
2121
from ddtrace.span import Span as DatadogSpan
2222

2323
import opentelemetry.trace as trace_api
24-
from opentelemetry.sdk.trace import sampling
25-
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
26-
27-
# pylint:disable=relative-beyond-top-level
28-
from .constants import (
24+
from opentelemetry.exporter.datadog.constants import (
2925
DD_ORIGIN,
3026
ENV_KEY,
3127
SAMPLE_RATE_METRIC_KEY,
3228
SERVICE_NAME_TAG,
3329
VERSION_KEY,
3430
)
31+
from opentelemetry.sdk.trace import sampling
32+
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
3533

3634
logger = logging.getLogger(__name__)
3735

‎exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from opentelemetry import trace
1818
from opentelemetry.context import Context
19+
from opentelemetry.exporter.datadog import constants
1920
from opentelemetry.trace import get_current_span, set_span_in_context
2021
from opentelemetry.trace.propagation.textmap import (
2122
Getter,
@@ -24,9 +25,6 @@
2425
TextMapPropagatorT,
2526
)
2627

27-
# pylint:disable=relative-beyond-top-level
28-
from . import constants
29-
3028

3129
class DatadogFormat(TextMapPropagator):
3230
"""Propagator for the Datadog HTTP header format.
@@ -62,7 +60,7 @@ def extract(
6260
constants.AUTO_KEEP,
6361
constants.USER_KEEP,
6462
):
65-
trace_flags |= trace.TraceFlags.SAMPLED
63+
trace_flags = trace.TraceFlags(trace.TraceFlags.SAMPLED)
6664

6765
if trace_id is None or span_id is None:
6866
return set_span_in_context(trace.INVALID_SPAN, context)

‎exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from opentelemetry import trace as trace_api
1919
from opentelemetry.exporter.datadog import constants, propagator
2020
from opentelemetry.sdk import trace
21+
from opentelemetry.sdk.trace.ids_generator import RandomIdsGenerator
2122
from opentelemetry.trace import get_current_span, set_span_in_context
2223
from opentelemetry.trace.propagation.textmap import DictGetter
2324

@@ -29,7 +30,7 @@
2930
class TestDatadogFormat(unittest.TestCase):
3031
@classmethod
3132
def setUpClass(cls):
32-
ids_generator = trace_api.RandomIdsGenerator()
33+
ids_generator = RandomIdsGenerator()
3334
cls.serialized_trace_id = propagator.format_trace_id(
3435
ids_generator.generate_trace_id()
3536
)
@@ -107,7 +108,7 @@ def test_context_propagation(self):
107108
"child",
108109
trace_api.SpanContext(
109110
parent_span_context.trace_id,
110-
trace_api.RandomIdsGenerator().generate_span_id(),
111+
RandomIdsGenerator().generate_span_id(),
111112
is_remote=False,
112113
trace_flags=parent_span_context.trace_flags,
113114
trace_state=parent_span_context.trace_state,
@@ -154,7 +155,7 @@ def test_sampling_priority_auto_reject(self):
154155
"child",
155156
trace_api.SpanContext(
156157
parent_span_context.trace_id,
157-
trace_api.RandomIdsGenerator().generate_span_id(),
158+
RandomIdsGenerator().generate_span_id(),
158159
is_remote=False,
159160
trace_flags=parent_span_context.trace_flags,
160161
trace_state=parent_span_context.trace_state,

‎exporter/opentelemetry-exporter-prometheus-remote-write/setup.cfg

+3-4
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,12 @@ package_dir=
3939
=src
4040
packages=find_namespace:
4141
install_requires =
42+
snappy >= 2.8
4243
protobuf >= 3.13.0
4344
requests == 2.25.0
4445
opentelemetry-api == 0.17.dev0
4546
opentelemetry-sdk == 0.17.dev0
4647
python-snappy >= 0.5.4
47-
[options.packages.find]
48-
where = src
4948

50-
[options.extras_require]
51-
test =
49+
[options.packages.find]
50+
where = src

‎exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def _convert_from_quantile(
268268
) -> Sequence[TimeSeries]:
269269
raise NotImplementedError()
270270

271-
# pylint: disable=no-member
271+
# pylint: disable=no-member,no-self-use
272272
def _create_timeseries(
273273
self,
274274
export_record: ExportRecord,
@@ -317,6 +317,7 @@ def add_label(label_name: str, label_value: str):
317317
timeseries.samples.append(sample)
318318
return timeseries
319319

320+
# pylint: disable=no-member,no-self-use
320321
def _build_message(self, timeseries: Sequence[TimeSeries]) -> bytes:
321322
write_request = WriteRequest()
322323
write_request.timeseries.extend(timeseries)
@@ -370,7 +371,7 @@ def _send_message(
370371
)
371372
if not response.ok:
372373
response.raise_for_status()
373-
except requests.exceptions.RequestException as e:
374-
logger.error("Export POST request failed with reason: %s", e)
374+
except requests.exceptions.RequestException as err:
375+
logger.error("Export POST request failed with reason: %s", err)
375376
return MetricsExportResult.FAILURE
376377
return MetricsExportResult.SUCCESS

‎exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@
1313
# limitations under the License.
1414

1515
import unittest
16-
from logging import Logger
17-
from unittest.mock import MagicMock, Mock, patch
16+
from unittest.mock import patch
1817

1918
from opentelemetry.exporter.prometheus_remote_write import (
2019
PrometheusRemoteWriteMetricsExporter,
2120
)
2221
from opentelemetry.exporter.prometheus_remote_write.gen.types_pb2 import (
2322
Label,
24-
Sample,
2523
TimeSeries,
2624
)
2725
from opentelemetry.sdk.metrics import Counter
@@ -339,15 +337,17 @@ def create_label(name, value):
339337
)
340338

341339
expected_timeseries = TimeSeries()
342-
expected_timeseries.labels.append(create_label("__name__", "testname"))
343-
expected_timeseries.labels.append(
340+
expected_timeseries.labels.append( # pylint:disable=E1101
341+
create_label("__name__", "testname")
342+
)
343+
expected_timeseries.labels.append( # pylint:disable=E1101
344344
create_label("resource_name", "resource_value")
345345
)
346-
expected_timeseries.labels.append(
346+
expected_timeseries.labels.append( # pylint:disable=E1101
347347
create_label("record_name", "record_value")
348348
)
349349

350-
sample = expected_timeseries.samples.add()
350+
sample = expected_timeseries.samples.add() # pylint:disable=E1101
351351
sample.timestamp = int(sum_aggregator.last_update_timestamp / 1000000)
352352
sample.value = 5.0
353353

‎instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import aiopg
3636
import wrapt
37+
from aiopg.utils import _ContextManager, _PoolContextManager
3738

3839
from opentelemetry.instrumentation.aiopg.aiopg_integration import (
3940
AiopgIntegration,
@@ -99,7 +100,7 @@ def wrap_connect(
99100
"""
100101

101102
# pylint: disable=unused-argument
102-
async def wrap_connect_(
103+
def wrap_connect_(
103104
wrapped: typing.Callable[..., typing.Any],
104105
instance: typing.Any,
105106
args: typing.Tuple[typing.Any, typing.Any],
@@ -113,7 +114,9 @@ async def wrap_connect_(
113114
version=version,
114115
tracer_provider=tracer_provider,
115116
)
116-
return await db_integration.wrapped_connection(wrapped, args, kwargs)
117+
return _ContextManager(
118+
db_integration.wrapped_connection(wrapped, args, kwargs)
119+
)
117120

118121
try:
119122
wrapt.wrap_function_wrapper(aiopg, "connect", wrap_connect_)
@@ -191,7 +194,7 @@ def wrap_create_pool(
191194
tracer_provider: typing.Optional[TracerProvider] = None,
192195
):
193196
# pylint: disable=unused-argument
194-
async def wrap_create_pool_(
197+
def wrap_create_pool_(
195198
wrapped: typing.Callable[..., typing.Any],
196199
instance: typing.Any,
197200
args: typing.Tuple[typing.Any, typing.Any],
@@ -205,7 +208,9 @@ async def wrap_create_pool_(
205208
version=version,
206209
tracer_provider=tracer_provider,
207210
)
208-
return await db_integration.wrapped_pool(wrapped, args, kwargs)
211+
return _PoolContextManager(
212+
db_integration.wrapped_pool(wrapped, args, kwargs)
213+
)
209214

210215
try:
211216
wrapt.wrap_function_wrapper(aiopg, "create_pool", wrap_create_pool_)

‎instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py

+50
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,26 @@ def test_instrumentor_connect(self):
7979
spans_list = self.memory_exporter.get_finished_spans()
8080
self.assertEqual(len(spans_list), 1)
8181

82+
def test_instrumentor_connect_ctx_manager(self):
83+
async def _ctx_manager_connect():
84+
AiopgInstrumentor().instrument()
85+
86+
async with aiopg.connect(database="test") as cnx:
87+
async with cnx.cursor() as cursor:
88+
query = "SELECT * FROM test"
89+
await cursor.execute(query)
90+
91+
spans_list = self.memory_exporter.get_finished_spans()
92+
self.assertEqual(len(spans_list), 1)
93+
span = spans_list[0]
94+
95+
# Check version and name in span's instrumentation info
96+
self.check_span_instrumentation_info(
97+
span, opentelemetry.instrumentation.aiopg
98+
)
99+
100+
async_call(_ctx_manager_connect())
101+
82102
def test_instrumentor_create_pool(self):
83103
AiopgInstrumentor().instrument()
84104

@@ -110,6 +130,27 @@ def test_instrumentor_create_pool(self):
110130
spans_list = self.memory_exporter.get_finished_spans()
111131
self.assertEqual(len(spans_list), 1)
112132

133+
def test_instrumentor_create_pool_ctx_manager(self):
134+
async def _ctx_manager_pool():
135+
AiopgInstrumentor().instrument()
136+
137+
async with aiopg.create_pool(database="test") as pool:
138+
async with pool.acquire() as cnx:
139+
async with cnx.cursor() as cursor:
140+
query = "SELECT * FROM test"
141+
await cursor.execute(query)
142+
143+
spans_list = self.memory_exporter.get_finished_spans()
144+
self.assertEqual(len(spans_list), 1)
145+
span = spans_list[0]
146+
147+
# Check version and name in span's instrumentation info
148+
self.check_span_instrumentation_info(
149+
span, opentelemetry.instrumentation.aiopg
150+
)
151+
152+
async_call(_ctx_manager_pool())
153+
113154
def test_custom_tracer_provider_connect(self):
114155
resource = resources.Resource.create({})
115156
result = self.create_tracer_provider(resource=resource)
@@ -428,6 +469,12 @@ async def _acquire(self):
428469
)
429470
return connect
430471

472+
def close(self):
473+
pass
474+
475+
async def wait_closed(self):
476+
pass
477+
431478

432479
class MockPsycopg2Connection:
433480
def __init__(self, database, server_port, server_host, user):
@@ -471,6 +518,9 @@ async def callproc(self, query, params=None, throw_exception=False):
471518
if throw_exception:
472519
raise Exception("Test Exception")
473520

521+
def close(self):
522+
pass
523+
474524

475525
class AiopgConnectionMock:
476526
_conn = MagicMock()

‎instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ def _patched_api_call(self, original_func, instance, args, kwargs):
153153
"aws.request_id", req_id,
154154
)
155155

156+
if "RetryAttempts" in metadata:
157+
span.set_attribute(
158+
"retry_attempts", metadata["RetryAttempts"],
159+
)
160+
156161
if "HTTPStatusCode" in metadata:
157162
span.set_attribute(
158163
"http.status_code", metadata["HTTPStatusCode"],

‎instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py

+16
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def test_traced_client(self):
6969
"aws.region": "us-west-2",
7070
"aws.request_id": "fdcdcab1-ae5c-489e-9c33-4637c5dda355",
7171
"aws.service": "ec2",
72+
"retry_attempts": 0,
7273
"http.status_code": 200,
7374
},
7475
)
@@ -116,6 +117,7 @@ def test_s3_client(self):
116117
"aws.operation": "ListBuckets",
117118
"aws.region": "us-west-2",
118119
"aws.service": "s3",
120+
"retry_attempts": 0,
119121
"http.status_code": 200,
120122
},
121123
)
@@ -159,6 +161,7 @@ def test_s3_put(self):
159161
"aws.operation": "CreateBucket",
160162
"aws.region": "us-west-2",
161163
"aws.service": "s3",
164+
"retry_attempts": 0,
162165
"http.status_code": 200,
163166
},
164167
)
@@ -169,6 +172,7 @@ def test_s3_put(self):
169172
"aws.operation": "PutObject",
170173
"aws.region": "us-west-2",
171174
"aws.service": "s3",
175+
"retry_attempts": 0,
172176
"http.status_code": 200,
173177
},
174178
)
@@ -180,6 +184,7 @@ def test_s3_put(self):
180184
"aws.operation": "GetObject",
181185
"aws.region": "us-west-2",
182186
"aws.service": "s3",
187+
"retry_attempts": 0,
183188
"http.status_code": 200,
184189
},
185190
)
@@ -203,6 +208,7 @@ def test_sqs_client(self):
203208
"aws.operation": "ListQueues",
204209
"aws.region": "us-east-1",
205210
"aws.service": "sqs",
211+
"retry_attempts": 0,
206212
"http.status_code": 200,
207213
},
208214
)
@@ -233,6 +239,7 @@ def test_sqs_send_message(self):
233239
"aws.operation": "CreateQueue",
234240
"aws.region": "us-east-1",
235241
"aws.service": "sqs",
242+
"retry_attempts": 0,
236243
"http.status_code": 200,
237244
},
238245
)
@@ -248,6 +255,7 @@ def test_sqs_send_message(self):
248255
"aws.queue_url": response["QueueUrl"],
249256
"aws.region": "us-east-1",
250257
"aws.service": "sqs",
258+
"retry_attempts": 0,
251259
"http.status_code": 200,
252260
},
253261
)
@@ -270,6 +278,7 @@ def test_kinesis_client(self):
270278
"aws.operation": "ListStreams",
271279
"aws.region": "us-east-1",
272280
"aws.service": "kinesis",
281+
"retry_attempts": 0,
273282
"http.status_code": 200,
274283
},
275284
)
@@ -315,6 +324,7 @@ def test_lambda_client(self):
315324
"aws.operation": "ListFunctions",
316325
"aws.region": "us-east-1",
317326
"aws.service": "lambda",
327+
"retry_attempts": 0,
318328
"http.status_code": 200,
319329
},
320330
)
@@ -335,6 +345,7 @@ def test_kms_client(self):
335345
"aws.operation": "ListKeys",
336346
"aws.region": "us-east-1",
337347
"aws.service": "kms",
348+
"retry_attempts": 0,
338349
"http.status_code": 200,
339350
},
340351
)
@@ -359,6 +370,7 @@ def test_sts_client(self):
359370
"aws.region": "us-east-1",
360371
"aws.request_id": "c6104cbe-af31-11e0-8154-cbc7ccf896c7",
361372
"aws.service": "sts",
373+
"retry_attempts": 0,
362374
"http.status_code": 200,
363375
},
364376
)
@@ -395,6 +407,7 @@ def check_headers(**kwargs):
395407
"aws.region": "us-west-2",
396408
"aws.request_id": "fdcdcab1-ae5c-489e-9c33-4637c5dda355",
397409
"aws.service": "ec2",
410+
"retry_attempts": 0,
398411
"http.status_code": 200,
399412
},
400413
)
@@ -463,6 +476,7 @@ def test_dynamodb_client(self):
463476
"aws.region": "us-west-2",
464477
"aws.service": "dynamodb",
465478
"aws.table_name": "test_table_name",
479+
"retry_attempts": 0,
466480
"http.status_code": 200,
467481
},
468482
)
@@ -478,6 +492,7 @@ def test_dynamodb_client(self):
478492
"aws.region": "us-west-2",
479493
"aws.service": "dynamodb",
480494
"aws.table_name": "test_table_name",
495+
"retry_attempts": 0,
481496
"http.status_code": 200,
482497
},
483498
)
@@ -493,6 +508,7 @@ def test_dynamodb_client(self):
493508
"aws.region": "us-west-2",
494509
"aws.service": "dynamodb",
495510
"aws.table_name": "test_table_name",
511+
"retry_attempts": 0,
496512
"http.status_code": 200,
497513
},
498514
)

‎instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131

3232
try:
3333
from django.core.urlresolvers import ( # pylint: disable=no-name-in-module
34-
resolve,
3534
Resolver404,
35+
resolve,
3636
)
3737
except ImportError:
38-
from django.urls import resolve, Resolver404
38+
from django.urls import Resolver404, resolve
3939

4040
try:
4141
from django.utils.deprecation import MiddlewareMixin

‎instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ async def _(param: str):
9898
return {"message": param}
9999

100100
@app.get("/healthzz")
101-
async def health():
101+
async def _():
102102
return {"message": "ok"}
103103

104104
return app

‎instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def serve():
130130
"""
131131
from functools import partial
132132

133-
import grpc
133+
import grpc # pylint:disable=import-self
134134
from wrapt import wrap_function_wrapper as _wrap
135135

136136
from opentelemetry import trace
@@ -142,7 +142,6 @@ def serve():
142142
# pylint:disable=import-outside-toplevel
143143
# pylint:disable=import-self
144144
# pylint:disable=unused-argument
145-
# isort:skip
146145

147146

148147
class GrpcInstrumentorServer(BaseInstrumentor):
@@ -156,7 +155,7 @@ class GrpcInstrumentorServer(BaseInstrumentor):
156155
157156
"""
158157

159-
# pylint:disable=attribute-defined-outside-init
158+
# pylint:disable=attribute-defined-outside-init, redefined-outer-name
160159

161160
def _instrument(self, **kwargs):
162161
self._original_func = grpc.server

‎instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
import grpc
2626

2727
from opentelemetry import metrics, propagators, trace
28+
from opentelemetry.instrumentation.grpc import grpcext
29+
from opentelemetry.instrumentation.grpc._utilities import (
30+
RpcInfo,
31+
TimedMetricRecorder,
32+
)
2833
from opentelemetry.sdk.metrics.export.controller import PushController
2934
from opentelemetry.trace.status import Status, StatusCode
3035

31-
from . import grpcext
32-
from ._utilities import RpcInfo, TimedMetricRecorder
33-
3436

3537
class _GuardedSpan:
3638
def __init__(self, span):

‎instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_utilities.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,13 @@ def record_bytes_out(self, bytes_out, method):
8383
@contextmanager
8484
def record_latency(self, method):
8585
start_time = time()
86-
labels = {"method": method, "status_code": grpc.StatusCode.OK}
86+
labels = {
87+
"method": method,
88+
"status_code": grpc.StatusCode.OK, # pylint:disable=no-member
89+
}
8790
try:
8891
yield labels
89-
except grpc.RpcError as exc:
92+
except grpc.RpcError as exc: # pylint:disable=no-member
9093
if self._meter:
9194
# pylint: disable=no-member
9295
labels["status_code"] = exc.code()

‎instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/_interceptor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import grpc
2626

27-
from .. import grpcext
27+
from opentelemetry.instrumentation.grpc import grpcext
2828

2929

3030
class _UnaryClientInfo(

‎instrumentation/opentelemetry-instrumentation-grpc/tests/protobuf/test_server_pb2_grpc.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
22
import grpc
3-
43
from tests.protobuf import test_server_pb2 as test__server__pb2
54

65

‎instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import grpc
16+
from tests.protobuf import test_server_pb2_grpc
1617

1718
import opentelemetry.instrumentation.grpc
1819
from opentelemetry import trace
@@ -22,7 +23,6 @@
2223
SumAggregator,
2324
)
2425
from opentelemetry.test.test_base import TestBase
25-
from tests.protobuf import test_server_pb2_grpc
2626

2727
from ._client import (
2828
bidirectional_streaming_method,

‎instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from requests import Timeout, URLRequired
4040
from requests.exceptions import InvalidSchema, InvalidURL, MissingSchema
41+
from requests.models import Response
4142
from requests.sessions import Session
4243
from requests.structures import CaseInsensitiveDict
4344

@@ -158,7 +159,7 @@ def _instrumented_requests_call(
158159
finally:
159160
context.detach(token)
160161

161-
if result is not None:
162+
if isinstance(result, Response):
162163
if span.is_recording():
163164
span.set_attribute(
164165
"http.status_code", result.status_code

‎instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py

+42
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
from opentelemetry.trace.status import StatusCode
2929

3030

31+
class InvalidResponseObjectException(Exception):
32+
def __init__(self):
33+
super().__init__()
34+
self.response = {}
35+
36+
3137
class RequestsIntegrationTestBase(abc.ABC):
3238
# pylint: disable=no-member
3339

@@ -307,6 +313,42 @@ def test_requests_exception_without_response(self, *_, **__):
307313
mocked_response.status_code = 500
308314
mocked_response.reason = "Internal Server Error"
309315

316+
@mock.patch(
317+
"requests.adapters.HTTPAdapter.send",
318+
side_effect=InvalidResponseObjectException,
319+
)
320+
def test_requests_exception_without_proper_response_type(self, *_, **__):
321+
with self.assertRaises(InvalidResponseObjectException):
322+
self.perform_request(self.URL)
323+
324+
span = self.assert_span()
325+
self.assertEqual(
326+
span.attributes,
327+
{"component": "http", "http.method": "GET", "http.url": self.URL},
328+
)
329+
self.assertEqual(span.status.status_code, StatusCode.ERROR)
330+
331+
self.assertIsNotNone(RequestsInstrumentor().meter)
332+
self.assertEqual(len(RequestsInstrumentor().meter.instruments), 1)
333+
recorder = list(RequestsInstrumentor().meter.instruments.values())[0]
334+
match_key = get_dict_as_key(
335+
{
336+
"http.method": "GET",
337+
"http.url": "http://httpbin.org/status/200",
338+
}
339+
)
340+
for key in recorder.bound_instruments.keys():
341+
self.assertEqual(key, match_key)
342+
# pylint: disable=protected-access
343+
bound = recorder.bound_instruments.get(key)
344+
for view_data in bound.view_datas:
345+
self.assertEqual(view_data.labels, key)
346+
self.assertEqual(view_data.aggregator.current.count, 1)
347+
348+
mocked_response = requests.Response()
349+
mocked_response.status_code = 500
350+
mocked_response.reason = "Internal Server Error"
351+
310352
@mock.patch(
311353
"requests.adapters.HTTPAdapter.send",
312354
side_effect=requests.RequestException(response=mocked_response),

‎instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ def __init__(self, tracer, engine):
7474

7575
# pylint: disable=unused-argument
7676
def _before_cur_exec(self, conn, cursor, statement, *args):
77-
self.current_span = self.tracer.start_span(statement)
77+
self.current_span = self.tracer.start_span(
78+
statement, kind=trace.SpanKind.CLIENT
79+
)
7880
with self.tracer.use_span(self.current_span, end_on_exit=False):
7981
if self.current_span.is_recording():
8082
self.current_span.set_attribute(_STMT, statement)

‎instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from sqlalchemy import create_engine
1717

18+
from opentelemetry import trace
1819
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
1920
from opentelemetry.test.test_base import TestBase
2021

@@ -35,6 +36,7 @@ def test_trace_integration(self):
3536

3637
self.assertEqual(len(spans), 1)
3738
self.assertEqual(spans[0].name, "SELECT 1 + 1;")
39+
self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)
3840

3941
def test_not_recording(self):
4042
mock_tracer = mock.Mock()
@@ -67,3 +69,4 @@ def test_create_engine_wrapper(self):
6769

6870
self.assertEqual(len(spans), 1)
6971
self.assertEqual(spans[0].name, "SELECT 1 + 1;")
72+
self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)

‎instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
HTTPMetricType,
5151
MetricMixin,
5252
)
53-
from opentelemetry.instrumentation.urllib.version import __version__
53+
from opentelemetry.instrumentation.urllib.version import ( # pylint: disable=no-name-in-module,import-error
54+
__version__,
55+
)
5456
from opentelemetry.instrumentation.utils import http_status_to_status_code
5557
from opentelemetry.trace import SpanKind, get_tracer
5658
from opentelemetry.trace.status import Status, StatusCode
@@ -98,6 +100,7 @@ def _uninstrument(self, **kwargs):
98100
def uninstrument_opener(
99101
self, opener: OpenerDirector
100102
): # pylint: disable=no-self-use
103+
"""uninstrument_opener a specific instance of urllib.request.OpenerDirector"""
101104
_uninstrument_from(opener, restore_as_bound_func=True)
102105

103106

@@ -131,7 +134,7 @@ def call_wrapped():
131134
)
132135

133136
def _instrumented_open_call(
134-
opener, request, call_wrapped, get_or_create_headers
137+
_, request, call_wrapped, get_or_create_headers
135138
): # pylint: disable=too-many-locals
136139
if context.get_value("suppress_instrumentation") or context.get_value(
137140
_SUPPRESS_URLLIB_INSTRUMENTATION_KEY

‎instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323

2424
import httpretty
2525

26-
import opentelemetry.instrumentation.urllib
26+
import opentelemetry.instrumentation.urllib # pylint: disable=no-name-in-module,import-error
2727
from opentelemetry import context, propagators, trace
28-
from opentelemetry.instrumentation.urllib import URLLibInstrumentor
28+
from opentelemetry.instrumentation.urllib import ( # pylint: disable=no-name-in-module,import-error
29+
URLLibInstrumentor,
30+
)
2931
from opentelemetry.sdk import resources
3032
from opentelemetry.sdk.util import get_dict_as_key
3133
from opentelemetry.test.mock_textmap import MockTextMapPropagator

‎instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from unittest import TestCase, mock
15+
from unittest import TestCase
1616

1717
from opentelemetry.instrumentation.wsgi import CarrierGetter
1818

‎scripts/eachdist.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ def lint_args(args):
509509
)
510510
runsubprocess(
511511
args.dry_run,
512-
("isort", "--recursive", ".")
512+
("isort", ".")
513513
+ (("--diff", "--check-only") if args.check_only else ()),
514514
cwd=rootdir,
515515
check=True,

‎sdk-extension/opentelemetry-sdk-extension-aws/src/opentelemetry/sdk/extension/aws/trace/aws_xray_ids_generator.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
import random
1616
import time
1717

18-
from opentelemetry import trace
18+
from opentelemetry.sdk.trace.ids_generator import (
19+
IdsGenerator,
20+
RandomIdsGenerator,
21+
)
1922

2023

21-
class AwsXRayIdsGenerator(trace.IdsGenerator):
24+
class AwsXRayIdsGenerator(IdsGenerator):
2225
"""Generates tracing IDs compatible with the AWS X-Ray tracing service. In
2326
the X-Ray system, the first 32 bits of the `TraceId` are the Unix epoch time
2427
in seconds. Since spans (AWS calls them segments) with an embedded timestamp
@@ -28,7 +31,7 @@ class AwsXRayIdsGenerator(trace.IdsGenerator):
2831
See: https://docs.aws.amazon.com/xray/latest/devguide/xray-api-sendingdata.html#xray-api-traceids
2932
"""
3033

31-
random_ids_generator = trace.RandomIdsGenerator()
34+
random_ids_generator = RandomIdsGenerator()
3235

3336
def generate_span_id(self) -> int:
3437
return self.random_ids_generator.generate_span_id()

‎tox.ini

+2-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ commands =
283283

284284
[testenv:lint]
285285
basepython: python3.8
286-
recreate = True
286+
recreate = False
287287
deps =
288288
-c dev-requirements.txt
289289
flaky
@@ -341,6 +341,7 @@ commands =
341341

342342
[testenv:docker-tests]
343343
deps =
344+
pip >= 20.3.3
344345
pytest
345346
asyncpg==0.20.1
346347
docker-compose >= 1.25.2

0 commit comments

Comments
 (0)
Please sign in to comment.