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

SNOW-1063081 Bump opentelemetry-python dependencies to 1.23.0 #19

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions anaconda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ requirements:
- setuptools >=40.0.0
run:
- python
- opentelemetry-api ==1.12.0
- opentelemetry-sdk ==1.12.0
- opentelemetry-exporter-otlp ==1.12.0
- opentelemetry-api ==1.23.0
- opentelemetry-exporter-otlp-proto-common ==1.23.0
- opentelemetry-sdk ==1.23.0

about:
home: https://www.snowflake.com/
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
long_description=LONG_DESCRIPTION,
install_requires=[
"setuptools >= 40.0.0, < 66.0.0",
"opentelemetry-api == 1.12.0",
"opentelemetry-exporter-otlp == 1.12.0",
"opentelemetry-sdk == 1.12.0",
"opentelemetry-api == 1.23.0",
"opentelemetry-exporter-otlp-proto-common == 1.23.0",
"opentelemetry-sdk == 1.23.0",
],
packages=find_namespace_packages(
where='src'
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
import threading
import typing
import opentelemetry.sdk.util.instrumentation as otel_instrumentation
import opentelemetry.sdk._logs._internal as _logs_internal

from opentelemetry.exporter.otlp.proto.common._log_encoder import (
encode_logs,
)
from opentelemetry.proto.logs.v1.logs_pb2 import LogsData
from opentelemetry.sdk import resources
from opentelemetry.sdk._logs import export
from opentelemetry.sdk import _logs
from opentelemetry.util import types
from snowflake.telemetry._internal.encoder.otlp.proto.common.log_encoder import (
_encode_logs,
)


# pylint: disable=too-few-public-methods
Expand Down Expand Up @@ -69,7 +70,7 @@ def _serialize_logs_data(batch: typing.Sequence[_logs.LogData]) -> bytes:
# pylint gets confused by protobuf-generated code, that's why we must
# disable the no-member check below.
return LogsData(
resource_logs=_encode_logs(batch).resource_logs # pylint: disable=no-member
resource_logs=encode_logs(batch).resource_logs # pylint: disable=no-member
).SerializeToString()

def shutdown(self):
Expand All @@ -82,19 +83,18 @@ class SnowflakeLoggingHandler(_logs.LoggingHandler):
discarded by the original implementation.
"""

_FILEPATH_ATTRIBUTE = "code.filepath"
_FUNCTION_NAME_ATTRIBUTE = "code.function"
LOGGER_NAME_TEMP_ATTRIBUTE = "__snow.logging.temp.logger_name"

def __init__(
self,
log_writer: LogWriter,
):
provider = _SnowflakeTelemetryLogEmitterProvider()
_logs.set_log_emitter_provider(provider)
exporter = _ProtoLogExporter(log_writer)
provider.add_log_processor(export.SimpleLogProcessor(exporter))
super().__init__()
provider = _SnowflakeTelemetryLoggerProvider()
provider.add_log_record_processor(
export.SimpleLogRecordProcessor(exporter)
)
super().__init__(logger_provider=provider)

@staticmethod
def _get_snowflake_log_level_name(py_level_name):
Expand All @@ -114,17 +114,11 @@ def _get_snowflake_log_level_name(py_level_name):
def _get_attributes(record: logging.LogRecord) -> types.Attributes:
attributes = _logs.LoggingHandler._get_attributes(record) # pylint: disable=protected-access

# Adding attributes that were discarded by the base class's
# _get_attributes() method
# TODO (SNOW-1210317) Remove these when upgrading to opentelemetry-python 1.23
attributes[SnowflakeLoggingHandler._FILEPATH_ATTRIBUTE] = record.pathname
attributes[SnowflakeLoggingHandler._FUNCTION_NAME_ATTRIBUTE] = record.funcName

# Temporarily storing logger's name in record's attributes.
# This attribute will be removed by the emitter.
# This attribute will be removed by the logger.
#
# TODO(SNOW-1210317): Upgrade to OpenTelemetry 1.20.0 or later
# and use OpenTelemetry's LoggerProvider.
# TODO (SNOW-1235374): opentelemetry-python issue #2485: Record logger
# name as the instrumentation scope name
attributes[SnowflakeLoggingHandler.LOGGER_NAME_TEMP_ATTRIBUTE] = record.name
return attributes

Expand All @@ -136,21 +130,22 @@ def _translate(self, record: logging.LogRecord) -> _logs.LogRecord:
return otel_record


class _SnowflakeTelemetryLogEmitter(_logs.LogEmitter):
sfc-gh-tmonk marked this conversation as resolved.
Show resolved Hide resolved
class _SnowflakeTelemetryLogger(_logs.Logger):
"""
A log emitter which creates an InstrumentationScope for each logger name it
encounters.
An Open Telemetry Logger which creates an InstrumentationScope for each
logger name it encounters.
"""

def __init__(
self,
resource: resources.Resource,
multi_log_processor: typing.Union[
_logs.SynchronousMultiLogProcessor, _logs.ConcurrentMultiLogProcessor
],
instrumentation_scope: otel_instrumentation.InstrumentationScope,
self,
resource: resources.Resource,
multi_log_record_processor: typing.Union[
_logs_internal.SynchronousMultiLogRecordProcessor,
_logs_internal.ConcurrentMultiLogRecordProcessor,
],
instrumentation_scope: otel_instrumentation.InstrumentationScope,
):
super().__init__(resource, multi_log_processor, instrumentation_scope)
super().__init__(resource, multi_log_record_processor, instrumentation_scope)
self._lock = threading.Lock()
self.cached_scopes = {}

Expand All @@ -175,28 +170,31 @@ def emit(self, record: _logs.LogRecord):

# Emitting a record with a scope that corresponds to the logger
# that logged it. NOT calling the superclass here for two reasons:
# 1. LogEmitter.emit takes a LogRecord, not LogData.
# 1. Logger.emit takes a LogRecord, not LogData.
# 2. It would emit a log record with the default instrumentation scope,
# not with the scope we want.
log_data = _logs.LogData(record, current_scope)
self._multi_log_processor.emit(log_data)
self._multi_log_record_processor.emit(log_data)


class _SnowflakeTelemetryLogEmitterProvider(_logs.LogEmitterProvider):
class _SnowflakeTelemetryLoggerProvider(_logs.LoggerProvider):
"""
A log emitter provider that creates SnowflakeTelemetryLogEmitters
A LoggerProvider that creates SnowflakeTelemetryLoggers
"""

def get_log_emitter(
self,
instrumenting_module_name: str,
instrumenting_module_version: str = "",
) -> _logs.LogEmitter:
return _SnowflakeTelemetryLogEmitter(
def get_logger(
self,
name: str,
version: types.Optional[str] = None,
schema_url: types.Optional[str] = None,
) -> _logs.Logger:
return _SnowflakeTelemetryLogger(
self._resource,
self._multi_log_processor,
self._multi_log_record_processor,
otel_instrumentation.InstrumentationScope(
instrumenting_module_name, instrumenting_module_version
name,
version,
schema_url,
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
from typing import Dict

import opentelemetry
from opentelemetry.exporter.otlp.proto.common.metrics_encoder import (
encode_metrics,
)
from opentelemetry.proto.metrics.v1.metrics_pb2 import MetricsData as PB2MetricsData
from opentelemetry.sdk.metrics.export import (
AggregationTemporality,
MetricExportResult,
MetricExporter,
MetricsData,
)
from snowflake.telemetry._internal.encoder.otlp.proto.common.metrics_encoder import (
_encode_metrics,
)


# pylint: disable=too-few-public-methods
Expand All @@ -39,7 +39,8 @@ class MetricWriter(abc.ABC):
def write_metrics(self, serialized_metrics: bytes) -> None:
"""
Implement this method to write the serialized protobuf message to your
preferred location.
preferred location. For an example implementation, see
InMemoryMetricWriter in the tests folder.
"""


Expand Down Expand Up @@ -82,7 +83,7 @@ def _serialize_metrics_data(data: MetricsData) -> bytes:
# pylint gets confused by protobuf-generated code, that's why we must
# disable the no-member check below.
return PB2MetricsData(
resource_metrics=_encode_metrics(data).resource_metrics # pylint: disable=no-member
resource_metrics=encode_metrics(data).resource_metrics # pylint: disable=no-member
).SerializeToString()

def force_flush(self, timeout_millis: float = 10_000) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
import abc
import typing

from opentelemetry.exporter.otlp.proto.common.trace_encoder import (
encode_spans,
)
from opentelemetry.proto.trace.v1.trace_pb2 import TracesData
from opentelemetry.sdk.trace import ReadableSpan
from opentelemetry.sdk.trace.export import (
SpanExportResult,
SpanExporter,
)
from snowflake.telemetry._internal.encoder.otlp.proto.common.trace_encoder import (
_encode_spans,
)


# pylint: disable=too-few-public-methods
Expand All @@ -37,7 +37,8 @@ class SpanWriter(abc.ABC):
def write_span(self, serialized_spans: bytes) -> None:
"""
Implement this method to write the serialized protobuf message to your
preferred location.
preferred location. For an example implementation, see
InMemorySpanWriter in the tests folder.
"""


Expand Down Expand Up @@ -72,7 +73,7 @@ def _serialize_traces_data(
# pylint gets confused by protobuf-generated code, that's why we must
# disable the no-member check below.
return TracesData(
resource_spans=_encode_spans(sdk_spans).resource_spans # pylint: disable=no-member
resource_spans=encode_spans(sdk_spans).resource_spans # pylint: disable=no-member
).SerializeToString()

def shutdown(self) -> None:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#
# Copyright (c) 2012-2024 Snowflake Computing Inc. All rights reserved.
#

import typing

from opentelemetry.proto.logs.v1.logs_pb2 import (
LogsData,
)
from snowflake.telemetry._internal.exporter.otlp.proto.logs import (
LogWriter,
)


class InMemoryLogWriter(LogWriter):
"""Implementation of :class:`.LogWriter` that stores protobufs in memory.

This class is intended for testing purposes. It stores the deserialized
protobuf messages in a list in memory that can be retrieved using the
:func:`.get_finished_protos` method.
"""

def __init__(self):
self._protos = []

def write_logs(self, serialized_logs: bytes) -> None:
message = LogsData()
message.ParseFromString(serialized_logs)
self._protos.append(message)

def get_finished_protos(self) -> typing.Tuple[LogsData, ...]:
return tuple(self._protos)

def clear(self):
self._protos.clear()
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# Copyright (c) 2012-2024 Snowflake Computing Inc. All rights reserved.
#

import typing

from opentelemetry.proto.metrics.v1.metrics_pb2 import (
MetricsData,
)
from snowflake.telemetry._internal.exporter.otlp.proto.metrics import (
MetricWriter,
)


class InMemoryMetricWriter(MetricWriter):
"""Implementation of :class:`.MetricWriter` that stores protobufs in
memory.

This class is intended for testing purposes. It stores the deserialized
protobuf messages in a list in memory that can be retrieved using the
:func:`.get_finished_protos` method.
"""

def __init__(self):
self._protos = []

def write_metrics(self, serialized_metrics: bytes) -> None:
message = MetricsData()
message.ParseFromString(serialized_metrics)
self._protos.append(message)

def get_finished_protos(self) -> typing.Tuple[MetricsData, ...]:
return tuple(self._protos)

def clear(self):
self._protos.clear()
Loading
Loading