Skip to content

Commit 7e92dac

Browse files
committed
SNOW-1023673 Implement common encode and serialize methods using OTEL v0.12.0
1 parent 3d1dacb commit 7e92dac

File tree

15 files changed

+1649
-23
lines changed

15 files changed

+1649
-23
lines changed

.github/workflows/build-test.yml

+1
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ jobs:
4343
pip install .
4444
- name: Test with pytest
4545
run: |
46+
pip install ./tests/snowflake-telemetry-test-utils
4647
pytest

README.md

+20-8
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,27 @@ The package is a stub for the full functionality when running in Snowflake.
1111

1212
## Getting started
1313

14-
To install this package, run
14+
To install the latest release of this package as an end user, run
1515

1616
```bash
17-
$ git clone [email protected]:snowflakedb/snowflake-telemetry-python.git
18-
$ cd snowflake-telemetry-python
19-
20-
$ python3 -m venv venv
21-
$ source venv/bin/activate
22-
$ pip install --upgrade pip
23-
$ pip install .
17+
VERSION="0.2.0"
18+
curl -L "https://github.com/snowflakedb/snowflake-telemetry-python/archive/refs/tags/v${VERSION}.tar.gz" > "snowflake-telemetry-python-${VERSION}.tar.gz"
19+
tar -xvf "snowflake-telemetry-python-${VERSION}.tar.gz"
20+
cd "snowflake-telemetry-python-${VERSION}"
21+
python3 -m venv .venv
22+
source .venv/bin/activate
23+
pip install --upgrade pip
24+
pip install .
2425
```
2526

27+
To develop this package, run
28+
29+
```bash
30+
git clone [email protected]:snowflakedb/snowflake-telemetry-python.git
31+
cd snowflake-telemetry-python
32+
33+
python3 -m venv .venv
34+
source .venv/bin/activate
35+
pip install --upgrade pip
36+
pip install . ./tests/snowflake-telemetry-test-utils
37+
```

setup.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
2-
from setuptools import setup
3-
2+
from setuptools import (
3+
find_namespace_packages,
4+
setup,
5+
)
46

57
DESCRIPTION = 'Snowflake Telemetry Python'
68
LONG_DESCRIPTION = 'This package provides a set of telemetry APIs for use in Snowflake'
@@ -9,26 +11,24 @@
911
VERSION = None
1012
with open(os.path.join(SNOWFLAKE_TELEMETRY_SRC_DIR, "version.py"), encoding="utf-8") as f:
1113
exec(f.read())
12-
VERSION_STR = ".".join([str(v) for v in VERSION if v is not None])
1314

1415

1516
setup(
1617
name="snowflake-telemetry-python",
17-
version=VERSION_STR,
18+
version=VERSION,
1819
author="Snowflake, Inc",
1920
author_email="[email protected]",
2021
description=DESCRIPTION,
2122
long_description=LONG_DESCRIPTION,
2223
install_requires=[
23-
"setuptools >= 40.0.0",
24-
"opentelemetry-sdk == 1.12.0",
24+
"setuptools >= 40.0.0, < 66.0.0",
2525
"opentelemetry-api == 1.12.0",
2626
"opentelemetry-exporter-otlp == 1.12.0",
27+
"opentelemetry-sdk == 1.12.0",
2728
],
28-
namespace_packages=["snowflake"],
29-
packages=[
30-
"snowflake.telemetry",
31-
],
29+
packages=find_namespace_packages(
30+
where='src'
31+
),
3232
package_dir={
3333
"": "src",
3434
},

src/snowflake/telemetry/__init__.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,27 @@
1111
Stored Procedures.
1212
"""
1313

14-
from opentelemetry.util import types
14+
from opentelemetry.util.types import (
15+
AttributeValue,
16+
Attributes,
17+
)
1518

1619
from snowflake.telemetry.version import VERSION
1720

18-
__version__ = ".".join(str(x) for x in VERSION if x is not None)
21+
__version__ = VERSION
1922

2023

2124
def add_event(
2225
name: str,
23-
attributes: types.Attributes = None,
26+
attributes: Attributes = None,
2427
) -> None:
2528
"""Add an event to the Snowflake auto-instrumented span.
2629
2730
This is a stub for the full functionality when running in Snowflake.
2831
"""
2932

3033

31-
def set_span_attribute(key: str, value: types.AttributeValue) -> None:
34+
def set_span_attribute(key: str, value: AttributeValue) -> None:
3235
"""Set an attribute to the Snowflake auto-instrumented span.
3336
3437
This is a stub for the full functionality when running in Snowflake.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from logging import LogRecord
2+
3+
from typing import Sequence
4+
5+
from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import ExportLogsServiceRequest
6+
from opentelemetry.proto.logs.v1.logs_pb2 import LogsData
7+
8+
9+
def _encode_logs(batch: Sequence[LogRecord]) -> ExportLogsServiceRequest:
10+
# TODO fix this no-op implementation of encode_logs
11+
return ExportLogsServiceRequest(resource_logs=[])
12+
13+
def serialize_logs_data(batch: Sequence[LogRecord]) -> bytes:
14+
return LogsData(
15+
resource_logs=_encode_logs(batch).resource_logs
16+
).SerializeToString()
17+
18+
19+
__all__ = [
20+
"serialize_logs_data",
21+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
2+
from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ExportMetricsServiceRequest
3+
from opentelemetry.proto.metrics.v1.metrics_pb2 import MetricsData as PB2MetricsData
4+
from opentelemetry.sdk.metrics.export import MetricsData
5+
6+
7+
_exporter = OTLPMetricExporter()
8+
9+
def _encode_metrics(data: MetricsData) -> ExportMetricsServiceRequest:
10+
# Will no longer rely on _translate_data after we upgrade to v1.19.0 or later
11+
return _exporter._translate_data(data)
12+
13+
def serialize_metrics_data(data: MetricsData) -> bytes:
14+
return PB2MetricsData(
15+
resource_metrics=_encode_metrics(data).resource_metrics
16+
).SerializeToString()
17+
18+
19+
__all__ = [
20+
"serialize_metrics_data",
21+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from typing import Sequence
2+
3+
from opentelemetry.exporter.otlp.proto.http.trace_exporter.encoder import _ProtobufEncoder
4+
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ExportTraceServiceRequest as PB2ExportTraceServiceRequest
5+
from opentelemetry.proto.trace.v1.trace_pb2 import TracesData
6+
from opentelemetry.sdk.trace import ReadableSpan
7+
8+
9+
def _encode_spans(
10+
sdk_spans: Sequence[ReadableSpan],
11+
) -> PB2ExportTraceServiceRequest:
12+
# Will no longer rely on _ProtobufEncoder after we upgrade to v1.19.0 or later
13+
return _ProtobufEncoder.encode(sdk_spans)
14+
15+
def serialize_traces_data(
16+
sdk_spans: Sequence[ReadableSpan],
17+
) -> bytes:
18+
return TracesData(
19+
resource_spans=_encode_spans(sdk_spans).resource_spans
20+
).SerializeToString()
21+
22+
23+
__all__ = [
24+
"serialize_traces_data",
25+
]

src/snowflake/telemetry/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
#
55

66
"""Update this for the versions."""
7-
VERSION = (0, 2, 0)
7+
VERSION = "0.2.1.dev"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Snowflake Telemetry Test Utils
2+
3+
## About
4+
5+
`snowflake-telemetry-test-utils` is a utility module that supports the test written for the Snowflake Telemetry Python project.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import os
2+
from setuptools import (
3+
find_namespace_packages,
4+
setup,
5+
)
6+
7+
DESCRIPTION = 'Snowflake Telemetry Test Utils'
8+
LONG_DESCRIPTION = 'This package provides test utils for testing snowflake-telemetry-python'
9+
10+
11+
setup(
12+
name="snowflake-telemetry-test-utils",
13+
version="0.0.1.dev",
14+
author="Snowflake, Inc",
15+
author_email="[email protected]",
16+
description=DESCRIPTION,
17+
long_description=LONG_DESCRIPTION,
18+
install_requires=[
19+
"pytest >= 7.0.0",
20+
"snowflake-telemetry-python == 0.2.1.dev",
21+
],
22+
packages=find_namespace_packages(
23+
where='src'
24+
),
25+
package_dir={
26+
"": "src",
27+
},
28+
keywords="Snowflake db database cloud analytics warehouse",
29+
classifiers=[
30+
"Development Status :: 1 - Planning",
31+
"Environment :: Console",
32+
"Environment :: Other Environment",
33+
"Intended Audience :: Developers",
34+
"Intended Audience :: Education",
35+
"Intended Audience :: Information Technology",
36+
"Intended Audience :: System Administrators",
37+
"License :: OSI Approved :: Apache Software License",
38+
"Operating System :: OS Independent",
39+
"Programming Language :: SQL",
40+
"Programming Language :: Python :: 3.6",
41+
"Programming Language :: Python :: 3.7",
42+
"Programming Language :: Python :: 3.8",
43+
"Programming Language :: Python :: 3.9",
44+
"Programming Language :: Python :: 3.10",
45+
"Topic :: Database",
46+
"Topic :: Software Development",
47+
"Topic :: Software Development :: Libraries",
48+
"Topic :: Software Development :: Libraries :: Application Frameworks",
49+
"Topic :: Software Development :: Libraries :: Python Modules",
50+
"Topic :: Scientific/Engineering :: Information Analysis",
51+
],
52+
zip_safe=True,
53+
)

tests/snowflake-telemetry-test-utils/src/snowflake/telemetry/test/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
from opentelemetry.attributes import BoundedAttributes
17+
from opentelemetry.sdk.metrics.export import (
18+
AggregationTemporality,
19+
Gauge,
20+
Metric,
21+
NumberDataPoint,
22+
Sum,
23+
)
24+
25+
26+
def _generate_metric(
27+
name, data, attributes=None, description=None, unit=None
28+
) -> Metric:
29+
if description is None:
30+
description = "foo"
31+
if unit is None:
32+
unit = "s"
33+
return Metric(
34+
name=name,
35+
description=description,
36+
unit=unit,
37+
data=data,
38+
)
39+
40+
41+
def _generate_sum(
42+
name,
43+
value,
44+
attributes=None,
45+
description=None,
46+
unit=None,
47+
is_monotonic=True,
48+
) -> Metric:
49+
if attributes is None:
50+
attributes = BoundedAttributes(attributes={"a": 1, "b": True})
51+
return _generate_metric(
52+
name,
53+
Sum(
54+
data_points=[
55+
NumberDataPoint(
56+
attributes=attributes,
57+
start_time_unix_nano=1641946015139533244,
58+
time_unix_nano=1641946016139533244,
59+
value=value,
60+
)
61+
],
62+
aggregation_temporality=AggregationTemporality.CUMULATIVE,
63+
is_monotonic=is_monotonic,
64+
),
65+
description=description,
66+
unit=unit,
67+
)
68+
69+
70+
def _generate_gauge(
71+
name, value, attributes=None, description=None, unit=None
72+
) -> Metric:
73+
if attributes is None:
74+
attributes = BoundedAttributes(attributes={"a": 1, "b": True})
75+
return _generate_metric(
76+
name,
77+
Gauge(
78+
data_points=[
79+
NumberDataPoint(
80+
attributes=attributes,
81+
start_time_unix_nano=1641946015139533244,
82+
time_unix_nano=1641946016139533244,
83+
value=value,
84+
)
85+
],
86+
),
87+
description=description,
88+
unit=unit,
89+
)
90+
91+
92+
def _generate_unsupported_metric(
93+
name, attributes=None, description=None, unit=None
94+
) -> Metric:
95+
return _generate_metric(
96+
name,
97+
None,
98+
description=description,
99+
unit=unit,
100+
)

0 commit comments

Comments
 (0)