Skip to content

Commit a47a89e

Browse files
author
Azfaar Qureshi
committed
Adding param validation
fix lint changes
1 parent 9b71f8b commit a47a89e

File tree

3 files changed

+178
-23
lines changed

3 files changed

+178
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changelog
22

33
## Unreleased
4-
- Setup for Prometheus Remote Write Exporter
5-
((#180)[https://github.com/open-telemetry/opentelemetry-python-contrib/pull/180])
4+
- Prometheus Remote Write Exporter Setup
5+
((#180)[https://github.com/open-telemetry/opentelemetry-python-contrib/pull/180])
6+
- Add Exporter constructor validation methods
7+
((#206)[https://github.com/open-telemetry/opentelemetry-python-contrib/pull/206])

exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py

+92-6
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,106 @@ class PrometheusRemoteWriteMetricsExporter(MetricsExporter):
3333
Args:
3434
endpoint: url where data will be sent (Required)
3535
basic_auth: username and password for authentication (Optional)
36-
bearer_token: token used for authentication (Optional)
37-
bearer_token_file: filepath to file containing authentication token (Optional)
38-
headers: additional headers for remote write request (Optional
36+
headers: additional headers for remote write request (Optional)
37+
timeout: timeout for requests to the remote write endpoint in seconds (Optional)
38+
proxies: dict mapping request proxy protocols to proxy urls (Optional)
39+
tls_config: configuration for remote write TLS settings (Optional)
3940
"""
4041

4142
def __init__(
4243
self,
4344
endpoint: str,
4445
basic_auth: Dict = None,
45-
bearer_token: str = None,
46-
bearer_token_file: str = None,
4746
headers: Dict = None,
47+
timeout: int = 30,
48+
tls_config: Dict = None,
49+
proxies: Dict = None,
4850
):
49-
raise NotImplementedError()
51+
self.endpoint = endpoint
52+
self.basic_auth = basic_auth
53+
self.headers = headers
54+
self.timeout = timeout
55+
self.tls_config = tls_config
56+
self.proxies = proxies
57+
58+
@property
59+
def endpoint(self):
60+
return self._endpoint
61+
62+
@endpoint.setter
63+
def endpoint(self, endpoint: str):
64+
if endpoint == "":
65+
raise ValueError("endpoint required")
66+
self._endpoint = endpoint
67+
68+
@property
69+
def basic_auth(self):
70+
return self._basic_auth
71+
72+
@basic_auth.setter
73+
def basic_auth(self, basic_auth: Dict):
74+
if basic_auth:
75+
if "username" not in basic_auth:
76+
raise ValueError("username required in basic_auth")
77+
if (
78+
"password" not in basic_auth
79+
and "password_file" not in basic_auth
80+
):
81+
raise ValueError("password required in basic_auth")
82+
if "password" in basic_auth and "password_file" in basic_auth:
83+
raise ValueError(
84+
"basic_auth cannot contain password and password_file"
85+
)
86+
self._basic_auth = basic_auth
87+
88+
@property
89+
def timeout(self):
90+
return self._timeout
91+
92+
@timeout.setter
93+
def timeout(self, timeout: int):
94+
if timeout <= 0:
95+
raise ValueError("timeout must be greater than 0")
96+
self._timeout = timeout
97+
98+
@property
99+
def tls_config(self):
100+
return self._tls_config
101+
102+
@tls_config.setter
103+
def tls_config(self, tls_config: Dict):
104+
if tls_config:
105+
new_config = {}
106+
if "ca_file" in tls_config:
107+
new_config["ca_file"] = tls_config["ca_file"]
108+
if "cert_file" in tls_config and "key_file" in tls_config:
109+
new_config["cert_file"] = tls_config["cert_file"]
110+
new_config["key_file"] = tls_config["key_file"]
111+
elif "cert_file" in tls_config or "key_file" in tls_config:
112+
raise ValueError(
113+
"tls_config requires both cert_file and key_file"
114+
)
115+
if "insecure_skip_verify" in tls_config:
116+
new_config["insecure_skip_verify"] = tls_config[
117+
"insecure_skip_verify"
118+
]
119+
self._tls_config = tls_config
120+
121+
@property
122+
def proxies(self):
123+
return self._proxies
124+
125+
@proxies.setter
126+
def proxies(self, proxies: Dict):
127+
self._proxies = proxies
128+
129+
@property
130+
def headers(self):
131+
return self._headers
132+
133+
@headers.setter
134+
def headers(self, headers: Dict):
135+
self._headers = headers
50136

51137
def export(
52138
self, export_records: Sequence[ExportRecord]

exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py

+82-15
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,102 @@
1414

1515
import unittest
1616

17+
from opentelemetry.exporter.prometheus_remote_write import (
18+
PrometheusRemoteWriteMetricsExporter,
19+
)
20+
1721

1822
class TestValidation(unittest.TestCase):
1923
# Test cases to ensure exporter parameter validation works as intended
2024
def test_valid_standard_param(self):
21-
pass
25+
exporter = PrometheusRemoteWriteMetricsExporter(
26+
endpoint="/prom/test_endpoint",
27+
)
28+
self.assertEqual(exporter.endpoint, "/prom/test_endpoint")
2229

2330
def test_valid_basic_auth_param(self):
24-
pass
25-
26-
def test_valid_bearer_token_param(self):
27-
pass
31+
exporter = PrometheusRemoteWriteMetricsExporter(
32+
endpoint="/prom/test_endpoint",
33+
basic_auth={
34+
"username": "test_username",
35+
"password": "test_password",
36+
},
37+
)
38+
self.assertEqual(exporter.basic_auth["username"], "test_username")
39+
self.assertEqual(exporter.basic_auth["password"], "test_password")
2840

2941
def test_invalid_no_endpoint_param(self):
30-
pass
42+
with self.assertRaises(ValueError):
43+
PrometheusRemoteWriteMetricsExporter("")
3144

3245
def test_invalid_no_username_param(self):
33-
pass
46+
with self.assertRaises(ValueError):
47+
PrometheusRemoteWriteMetricsExporter(
48+
endpoint="/prom/test_endpoint",
49+
basic_auth={"password": "test_password"},
50+
)
3451

3552
def test_invalid_no_password_param(self):
36-
pass
53+
with self.assertRaises(ValueError):
54+
PrometheusRemoteWriteMetricsExporter(
55+
endpoint="/prom/test_endpoint",
56+
basic_auth={"username": "test_username"},
57+
)
3758

3859
def test_invalid_conflicting_passwords_param(self):
39-
pass
40-
41-
def test_invalid_conflicting_bearer_tokens_param(self):
42-
pass
43-
44-
def test_invalid_conflicting_auth_param(self):
45-
pass
60+
with self.assertRaises(ValueError):
61+
PrometheusRemoteWriteMetricsExporter(
62+
endpoint="/prom/test_endpoint",
63+
basic_auth={
64+
"username": "test_username",
65+
"password": "test_password",
66+
"password_file": "test_file",
67+
},
68+
)
69+
70+
def test_invalid_timeout_param(self):
71+
with self.assertRaises(ValueError):
72+
PrometheusRemoteWriteMetricsExporter(
73+
endpoint="/prom/test_endpoint", timeout=0
74+
)
75+
76+
def test_valid_tls_config_param(self):
77+
tls_config = {
78+
"ca_file": "test_ca_file",
79+
"cert_file": "test_cert_file",
80+
"key_file": "test_key_file",
81+
"insecure_skip_verify": True,
82+
}
83+
exporter = PrometheusRemoteWriteMetricsExporter(
84+
endpoint="/prom/test_endpoint", tls_config=tls_config
85+
)
86+
self.assertEqual(exporter.tls_config["ca_file"], tls_config["ca_file"])
87+
self.assertEqual(
88+
exporter.tls_config["cert_file"], tls_config["cert_file"]
89+
)
90+
self.assertEqual(
91+
exporter.tls_config["key_file"], tls_config["key_file"]
92+
)
93+
self.assertEqual(
94+
exporter.tls_config["insecure_skip_verify"],
95+
tls_config["insecure_skip_verify"],
96+
)
97+
98+
# if cert_file is provided, then key_file must also be provided
99+
def test_invalid_tls_config_cert_only_param(self):
100+
tls_config = {"cert_file": "value"}
101+
with self.assertRaises(ValueError):
102+
PrometheusRemoteWriteMetricsExporter(
103+
endpoint="/prom/test_endpoint", tls_config=tls_config
104+
)
105+
106+
# if cert_file is provided, then key_file must also be provided
107+
def test_invalid_tls_config_key_only_param(self):
108+
tls_config = {"cert_file": "value"}
109+
with self.assertRaises(ValueError):
110+
PrometheusRemoteWriteMetricsExporter(
111+
endpoint="/prom/test_endpoint", tls_config=tls_config
112+
)
46113

47114

48115
class TestConversion(unittest.TestCase):

0 commit comments

Comments
 (0)