From 31b910de67504247875ff99214a0c7edee1a0dce Mon Sep 17 00:00:00 2001 From: Shovnik Bhattacharya Date: Thu, 12 Nov 2020 15:25:28 -0500 Subject: [PATCH] Setup Prometheus Remote Write Exporter --- .../CHANGELOG.md | 3 + .../README.rst | 23 +++ .../setup.cfg | 50 +++++++ .../setup.py | 32 +++++ .../prometheus_remote_write/__init__.py | 132 ++++++++++++++++++ .../prometheus_remote_write/version.py | 15 ++ .../tests/__init__.py | 13 ++ .../tests/test_config.py | 74 ++++++++++ .../test_prometheus_remote_write_exporter.py | 69 +++++++++ 9 files changed, 411 insertions(+) create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/CHANGELOG.md create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/README.rst create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/setup.cfg create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/setup.py create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/version.py create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/tests/__init__.py create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_config.py create mode 100644 exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/CHANGELOG.md b/exporter/opentelemetry-exporter-prometheus-remote-write/CHANGELOG.md new file mode 100644 index 0000000000..1512c42162 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## Unreleased diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/README.rst b/exporter/opentelemetry-exporter-prometheus-remote-write/README.rst new file mode 100644 index 0000000000..1969eff12b --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/README.rst @@ -0,0 +1,23 @@ +OpenTelemetry Prometheus Remote Write Exporter +============================================== + +This library allows exporting metric data to `Prometheus Write Integrated Backends +`_. Development is currently in progress. + +Installation +------------ + +:: + + pip install opentelemetry-exporter-prometheus-remote-write + + +.. _Prometheus: https://prometheus.io/ +.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ + + +References +---------- + +* `Datadog `_ +* `OpenTelemetry Project `_ diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/setup.cfg b/exporter/opentelemetry-exporter-prometheus-remote-write/setup.cfg new file mode 100644 index 0000000000..ee7cb81e02 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/setup.cfg @@ -0,0 +1,50 @@ +# 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. +# +[metadata] +name = opentelemetry-exporter-prometheus-remote-write +description = Prometheus Remote Write Metrics Exporter for OpenTelemetry +long_description = file: README.rst +long_description_content_type = text/x-rst +author = OpenTelemetry Authors +author_email = cncf-opentelemetry-contributors@lists.cncf.io +url = https://github.com/open-telemetry/opentelemetry-python/exporter/opentelemetry-exporter-datadog +platforms = any +license = Apache-2.0 +classifiers = + Development Status :: 4 - Beta + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + +[options] +python_requires = >=3.5 +package_dir= + =src +packages=find_namespace: +install_requires = + ddtrace>=0.34.0 + opentelemetry-api == 0.16.dev0 + opentelemetry-sdk == 0.16.dev0 + +[options.packages.find] +where = src + +[options.extras_require] +test = diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/setup.py b/exporter/opentelemetry-exporter-prometheus-remote-write/setup.py new file mode 100644 index 0000000000..b2d9a5a47c --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/setup.py @@ -0,0 +1,32 @@ +# 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. + +import os + +import setuptools + +BASE_DIR = os.path.dirname(__file__) +VERSION_FILENAME = os.path.join( + BASE_DIR, + "src", + "opentelemetry", + "exporter", + "prometheus_remote_write", + "version.py", +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py new file mode 100644 index 0000000000..78e5f2c717 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py @@ -0,0 +1,132 @@ +# 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 typing import Dict, Sequence + +from opentelemetry.sdk.metrics.export import ( + MetricRecord, + MetricsExporter, + MetricsExportResult, +) + + +class TimeSeries: + """ + TimeSeries class used to store timeseries labels and samples that need to be sent + Args: + labels: timeseries labels + samples: timeseries samples + """ + + def __init__(self): + pass + + +class Config: + """ + Configuration containing all necessary information to make remote write requests + + Args: + endpoint: url where data will be sent + basic_auth: username and password for authentication (Optional) + bearer_token: token used for authentication (Optional) + bearer_token_file: filepath to file containing authentication token (Optional) + headers: additional headers for remote write request (Optional) + """ + + def __init__( + self, + endpoint: str, + basic_auth: Dict = None, + bearer_token: str = None, + bearer_token_file: str = None, + headers: Dict = None, + ): + pass + + def validate(self): + pass + + +class PrometheusRemoteWriteMetricsExporter(MetricsExporter): + """ + Prometheus remote write metric exporter for OpenTelemetry. + + Args: + config: configuration containing all necessary information to make remote write requests + """ + + def __init__(self, config: Config): + pass + + def export( + self, metric_records: Sequence[MetricRecord] + ) -> MetricsExportResult: + pass + + def shutdown(self) -> None: + pass + + def convert_to_timeseries( + self, metric_records: Sequence[MetricRecord] + ) -> Sequence[TimeSeries]: + pass + + def convert_from_sum(self, sum_record: MetricRecord) -> TimeSeries: + pass + + def convert_from_min_max_sum_count( + self, min_max_sum_count_record: MetricRecord + ) -> TimeSeries: + pass + + def convert_from_histogram( + self, histogram_record: MetricRecord + ) -> TimeSeries: + pass + + def convert_from_last_value( + self, last_value_record: MetricRecord + ) -> TimeSeries: + pass + + def convert_from_value_observer( + self, value_observer_record: MetricRecord + ) -> TimeSeries: + pass + + def convert_from_summary(self, summary_record: MetricRecord) -> TimeSeries: + pass + + def sanitize_label(self, label: str) -> str: + pass + + def build_message(self, data: Sequence[TimeSeries]) -> str: + pass + + def get_headers(self) -> Dict: + pass + + def send_message(self, message: str, headers: Dict) -> int: + pass + + +def parse_config() -> Config: + """ + Method that parses yaml file to generate a valid remote write exporter config + + Args: + path: filepath to yaml configuration file + """ diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/version.py b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/version.py new file mode 100644 index 0000000000..1f98d44fa8 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/version.py @@ -0,0 +1,15 @@ +# 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. + +__version__ = "0.16.dev0" diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/tests/__init__.py b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/__init__.py new file mode 100644 index 0000000000..b0a6f42841 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/__init__.py @@ -0,0 +1,13 @@ +# 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. diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_config.py b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_config.py new file mode 100644 index 0000000000..58947f93e2 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_config.py @@ -0,0 +1,74 @@ +# 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. + +import unittest + + +# Series of test cases to ensure config validation works as intended +class TestConfig(unittest.TestCase): + def test_valid_standard_config(self): + pass + + def test_valid_basic_auth_config(self): + pass + + def test_valid_bearer_token_config(self): + pass + + def test_valid_quantiles_config(self): + pass + + def test_valid_histogram_boundaries_config(self): + pass + + def test_valid_tls_config(self): + pass + + def test_invalid_no_url_config(self): + pass + + def test_invalid_no_name_config(self): + pass + + def test_invalid_no_remote_timeout_config(self): + pass + + def test_invalid_no_username_config(self): + pass + + def test_invalid_no_password_config(self): + pass + + def test_invalid_conflicting_passwords_config(self): + pass + + def test_invalid_conflicting_bearer_tokens_config(self): + pass + + def test_invalid_conflicting_auth_config(self): + pass + + def test_invalid_quantiles_config(self): + pass + + def test_invalid_histogram_boundaries_config(self): + pass + + # Verifies that valid yaml file is parsed correctly + def test_valid_yaml_file(self): + pass + + # Ensures invalid filepath raises error when parsing + def test_invalid_yaml_file(self): + pass diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py new file mode 100644 index 0000000000..902ae83cd2 --- /dev/null +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py @@ -0,0 +1,69 @@ +# 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. + +import unittest + + +class TestPrometheusRemoteWriteMetricExporter(unittest.TestCase): + # Initializes test data that is reused across tests + def setUp(self): + pass + + # Ensures export is successful with valid metric_records and config + def test_export(self): + pass + + # Ensures sum aggregator is correctly converted to timeseries + def test_convert_from_sum(self): + pass + + # Ensures sum min_max_count aggregator is correctly converted to timeseries + def test_convert_from_min_max_sum_count(self): + pass + + # Ensures histogram aggregator is correctly converted to timeseries + def test_convert_from_histogram(self): + pass + + # Ensures last value aggregator is correctly converted to timeseries + def test_convert_from_last_value(self): + pass + + # Ensures value observer aggregator is correctly converted to timeseries + def test_convert_from_value_observer(self): + pass + + # Ensures summary aggregator is correctly converted to timeseries + def test_convert_from_summary(self): + pass + + # Ensures conversion to timeseries function as expected for different aggregation types + def test_convert_to_timeseries(self): + pass + + # Verifies that build_message calls snappy.compress and returns SerializedString + def test_build_message(self, mock_compress): + pass + + # Ensure correct headers are added when valid config is provided + def test_get_headers(self): + pass + + # Ensures valid message gets sent succesfully + def test_send_message(self): + pass + + # Ensures non alphanumberic label characters gets replaced with underscore + def test_sanitize_label(self): + pass