Fix sqlalchemy for postgres Unix sockets (#761)

* Fix sqlalchemy for postgres unix sockets

The following bit of replaced code contained a type inconsistency:

```py
attrs[SpanAttributes.NET_PEER_PORT] = int(data.get("port"))
```

`data.get` returns `Optional[str]` but `int(None)` throws a `TypeError`.

When using postgresql via unix socket `dsn` looks something like this:

```py
'user=postgres host=/tmp/socket dbname=postgres'
```

The `parse_dsn` function returns this:

```py
{'user': 'postgres', 'dbname': 'postgres', 'host': '/tmp/socket'}
```

* Update CHANGELOG

* Conditionally set net.transport for psql tcp/unix

* Use .value properties of enums

* Improve postgresql attribute detection from cursor

* Fix formatting

Co-authored-by: Matt Oberle <mattoberle@users.noreply.github.com>
Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
Matt Oberle
2021-11-11 07:35:55 -05:00
committed by GitHub
parent 2dd9bd12ea
commit 10d8e26a78
2 changed files with 25 additions and 10 deletions

View File

@ -40,6 +40,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.6.2-0.25b2](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.6.2-0.25b2) - 2021-10-19
- `opentelemetry-instrumentation-sqlalchemy` Fix PostgreSQL instrumentation for Unix sockets
([#761](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/761))
### Changed
- `opentelemetry-sdk-extension-aws` & `opentelemetry-propagator-aws` Release AWS Python SDK Extension as 2.0.1 and AWS Propagator as 1.0.1

View File

@ -11,12 +11,13 @@
# 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.
import os
from sqlalchemy.event import listen # pylint: disable=no-name-in-module
from opentelemetry import trace
from opentelemetry.instrumentation.sqlalchemy.version import __version__
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv.trace import NetTransportValues, SpanAttributes
from opentelemetry.trace.status import Status, StatusCode
@ -157,14 +158,25 @@ def _get_attributes_from_url(url):
def _get_attributes_from_cursor(vendor, cursor, attrs):
"""Attempt to set db connection attributes by introspecting the cursor."""
if vendor == "postgresql":
# pylint: disable=import-outside-toplevel
from psycopg2.extensions import parse_dsn
if hasattr(cursor, "connection") and hasattr(cursor.connection, "dsn"):
dsn = getattr(cursor.connection, "dsn", None)
if dsn:
data = parse_dsn(dsn)
attrs[SpanAttributes.DB_NAME] = data.get("dbname")
attrs[SpanAttributes.NET_PEER_NAME] = data.get("host")
attrs[SpanAttributes.NET_PEER_PORT] = int(data.get("port"))
info = getattr(getattr(cursor, "connection", None), "info", None)
if not info:
return attrs
attrs[SpanAttributes.DB_NAME] = info.dbname
is_unix_socket = info.host and info.host.startswith("/")
if is_unix_socket:
attrs[SpanAttributes.NET_TRANSPORT] = NetTransportValues.UNIX.value
if info.port:
# postgresql enforces this pattern on all socket names
attrs[SpanAttributes.NET_PEER_NAME] = os.path.join(
info.host, f".s.PGSQL.{info.port}"
)
else:
attrs[
SpanAttributes.NET_TRANSPORT
] = NetTransportValues.IP_TCP.value
attrs[SpanAttributes.NET_PEER_NAME] = info.host
if info.port:
attrs[SpanAttributes.NET_PEER_PORT] = int(info.port)
return attrs