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

Add missing to_json methods #2722

Merged
merged 5 commits into from
Jun 8, 2022
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.12.0rc1-0.31b0...HEAD)

- Add missing `to_json` methods
([#2722](https://github.com/open-telemetry/opentelemetry-python/pull/2722)
- Fix type hints for textmap `Getter` and `Setter`
([#2657](https://github.com/open-telemetry/opentelemetry-python/pull/2657))
- Fix LogEmitterProvider.force_flush hanging randomly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ def __init__(
self,
out: IO = stdout,
formatter: Callable[
["opentelemetry.sdk.metrics.export.Metric"], str
] = lambda metric: metric.to_json()
["opentelemetry.sdk.metrics.export.MetricsData"], str
] = lambda metrics_data: metrics_data.to_json()
+ linesep,
):
self.out = out
Expand Down
131 changes: 90 additions & 41 deletions opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# pylint: disable=unused-import

from dataclasses import asdict, dataclass
from json import dumps
from typing import Sequence, Union
from json import dumps, loads
from typing import Optional, Sequence, Union

# This kind of import is needed to avoid Sphinx errors.
import opentelemetry.sdk.metrics._internal
Expand All @@ -36,6 +36,29 @@ class NumberDataPoint:
time_unix_nano: int
value: Union[int, float]

def to_json(self, indent=4) -> str:
return dumps(asdict(self), indent=indent)


@dataclass(frozen=True)
class HistogramDataPoint:
"""Single data point in a timeseries that describes the time-varying scalar
value of a metric.
"""

attributes: Attributes
start_time_unix_nano: int
time_unix_nano: int
count: int
sum: Union[int, float]
bucket_counts: Sequence[int]
explicit_bounds: Sequence[float]
min: float
max: float

def to_json(self, indent=4) -> str:
return dumps(asdict(self), indent=indent)


@dataclass(frozen=True)
class Sum:
Expand All @@ -48,15 +71,17 @@ class Sum:
)
is_monotonic: bool

def to_json(self) -> str:
def to_json(self, indent=4) -> str:
return dumps(
{
"data_points": dumps(
[asdict(data_point) for data_point in self.data_points]
),
"data_points": [
loads(data_point.to_json(indent=indent))
for data_point in self.data_points
],
"aggregation_temporality": self.aggregation_temporality,
"is_monotonic": self.is_monotonic,
}
},
indent=indent,
)


Expand All @@ -68,33 +93,18 @@ class Gauge:

data_points: Sequence[NumberDataPoint]

def to_json(self) -> str:
def to_json(self, indent=4) -> str:
return dumps(
{
"data_points": dumps(
[asdict(data_point) for data_point in self.data_points]
)
}
"data_points": [
loads(data_point.to_json(indent=indent))
for data_point in self.data_points
],
},
indent=indent,
)


@dataclass(frozen=True)
class HistogramDataPoint:
"""Single data point in a timeseries that describes the time-varying scalar
value of a metric.
"""

attributes: Attributes
start_time_unix_nano: int
time_unix_nano: int
count: int
sum: Union[int, float]
bucket_counts: Sequence[int]
explicit_bounds: Sequence[float]
min: float
max: float


@dataclass(frozen=True)
class Histogram:
"""Represents the type of a metric that is calculated by aggregating as a
Expand All @@ -105,14 +115,16 @@ class Histogram:
"opentelemetry.sdk.metrics.export.AggregationTemporality"
)

def to_json(self) -> str:
def to_json(self, indent=4) -> str:
return dumps(
{
"data_points": dumps(
[asdict(data_point) for data_point in self.data_points]
),
"data_points": [
loads(data_point.to_json(indent=indent))
for data_point in self.data_points
],
"aggregation_temporality": self.aggregation_temporality,
}
},
indent=indent,
)


Expand All @@ -126,18 +138,19 @@ class Metric:
exported."""

name: str
description: str
unit: str
description: Optional[str]
unit: Optional[str]
data: DataT

def to_json(self) -> str:
def to_json(self, indent=4) -> str:
return dumps(
{
"name": self.name,
"description": self.description if self.description else "",
"unit": self.unit if self.unit else "",
"data": self.data.to_json(),
}
"description": self.description or "",
"unit": self.unit or "",
"data": loads(self.data.to_json(indent=indent)),
},
indent=indent,
)


Expand All @@ -149,6 +162,19 @@ class ScopeMetrics:
metrics: Sequence[Metric]
schema_url: str

def to_json(self, indent=4) -> str:
return dumps(
{
"scope": loads(self.scope.to_json(indent=indent)),
"metrics": [
loads(metric.to_json(indent=indent))
for metric in self.metrics
],
"schema_url": self.schema_url,
},
indent=indent,
)


@dataclass(frozen=True)
class ResourceMetrics:
Expand All @@ -158,9 +184,32 @@ class ResourceMetrics:
scope_metrics: Sequence[ScopeMetrics]
schema_url: str

def to_json(self, indent=4) -> str:
return dumps(
{
"resource": loads(self.resource.to_json(indent=indent)),
"scope_metrics": [
loads(scope_metrics.to_json(indent=indent))
for scope_metrics in self.scope_metrics
],
"schema_url": self.schema_url,
},
indent=indent,
)


@dataclass(frozen=True)
class MetricsData:
"""An array of ResourceMetrics"""

resource_metrics: Sequence[ResourceMetrics]

def to_json(self, indent=4) -> str:
return dumps(
{
"resource_metrics": [
loads(resource_metrics.to_json(indent=indent))
for resource_metrics in self.resource_metrics
]
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@ def __hash__(self):
f"{dumps(self._attributes.copy(), sort_keys=True)}|{self._schema_url}"
)

def to_json(self, indent=4) -> str:
return dumps(
{
"attributes": dict(self._attributes),
"schema_url": self._schema_url,
},
indent=indent,
)


_EMPTY_RESOURCE = Resource({})
_DEFAULT_RESOURCE = Resource(
Expand Down
29 changes: 20 additions & 9 deletions opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
# 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 typing
from json import dumps
from typing import Optional

from deprecated import deprecated

Expand All @@ -29,8 +30,8 @@ class InstrumentationInfo:
def __init__(
self,
name: str,
version: typing.Optional[str] = None,
schema_url: typing.Optional[str] = None,
version: Optional[str] = None,
schema_url: Optional[str] = None,
):
self._name = name
self._version = version
Expand Down Expand Up @@ -59,11 +60,11 @@ def __lt__(self, value):
)

@property
def schema_url(self) -> typing.Optional[str]:
def schema_url(self) -> Optional[str]:
return self._schema_url

@property
def version(self) -> typing.Optional[str]:
def version(self) -> Optional[str]:
return self._version

@property
Expand All @@ -84,8 +85,8 @@ class InstrumentationScope:
def __init__(
self,
name: str,
version: typing.Optional[str] = None,
schema_url: typing.Optional[str] = None,
version: Optional[str] = None,
schema_url: Optional[str] = None,
) -> None:
self._name = name
self._version = version
Expand Down Expand Up @@ -116,13 +117,23 @@ def __lt__(self, value: object) -> bool:
)

@property
def schema_url(self) -> typing.Optional[str]:
def schema_url(self) -> Optional[str]:
return self._schema_url

@property
def version(self) -> typing.Optional[str]:
def version(self) -> Optional[str]:
return self._version

@property
def name(self) -> str:
return self._name

def to_json(self, indent=4) -> str:
return dumps(
{
"name": self._name,
"version": self._version,
"schema_url": self._schema_url,
},
indent=indent,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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.

from unittest import TestCase

from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
ConsoleMetricExporter,
PeriodicExportingMetricReader,
)


class TestConsoleExporter(TestCase):
def test_console_exporter(self):

try:
exporter = ConsoleMetricExporter()
reader = PeriodicExportingMetricReader(exporter)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = metrics.get_meter(__name__)
counter = meter.create_counter("test")
counter.add(1)
except Exception as error:
self.fail(f"Unexpected exception {error} raised")
Loading