-
Notifications
You must be signed in to change notification settings - Fork 647
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
Prometheus Remote Write Exporter (5/6) #216
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# This Cortex Config is copied from the Cortex Project documentation | ||
# Source: https://github.com/cortexproject/cortex/blob/master/docs/configuration/single-process-config.yaml | ||
|
||
# Configuration for running Cortex in single-process mode. | ||
# This configuration should not be used in production. | ||
# It is only for getting started and development. | ||
|
||
# Disable the requirement that every request to Cortex has a | ||
# X-Scope-OrgID header. `fake` will be substituted in instead. | ||
auth_enabled: false | ||
|
||
server: | ||
http_listen_port: 9009 | ||
|
||
# Configure the server to allow messages up to 100MB. | ||
grpc_server_max_recv_msg_size: 104857600 | ||
grpc_server_max_send_msg_size: 104857600 | ||
grpc_server_max_concurrent_streams: 1000 | ||
|
||
distributor: | ||
shard_by_all_labels: true | ||
pool: | ||
health_check_ingesters: true | ||
|
||
ingester_client: | ||
grpc_client_config: | ||
# Configure the client to allow messages up to 100MB. | ||
max_recv_msg_size: 104857600 | ||
max_send_msg_size: 104857600 | ||
use_gzip_compression: true | ||
|
||
ingester: | ||
# We want our ingesters to flush chunks at the same time to optimise | ||
# deduplication opportunities. | ||
spread_flushes: true | ||
chunk_age_jitter: 0 | ||
|
||
walconfig: | ||
wal_enabled: true | ||
recover_from_wal: true | ||
wal_dir: /tmp/cortex/wal | ||
|
||
lifecycler: | ||
# The address to advertise for this ingester. Will be autodiscovered by | ||
# looking up address on eth0 or en0; can be specified if this fails. | ||
# address: 127.0.0.1 | ||
|
||
# We want to start immediately and flush on shutdown. | ||
join_after: 0 | ||
min_ready_duration: 0s | ||
final_sleep: 0s | ||
num_tokens: 512 | ||
tokens_file_path: /tmp/cortex/wal/tokens | ||
|
||
# Use an in memory ring store, so we don't need to launch a Consul. | ||
ring: | ||
kvstore: | ||
store: inmemory | ||
replication_factor: 1 | ||
|
||
# Use local storage - BoltDB for the index, and the filesystem | ||
# for the chunks. | ||
schema: | ||
configs: | ||
- from: 2019-07-29 | ||
store: boltdb | ||
object_store: filesystem | ||
schema: v10 | ||
index: | ||
prefix: index_ | ||
period: 1w | ||
|
||
storage: | ||
boltdb: | ||
directory: /tmp/cortex/index | ||
|
||
filesystem: | ||
directory: /tmp/cortex/chunks | ||
|
||
delete_store: | ||
store: boltdb | ||
|
||
purger: | ||
object_store_type: filesystem | ||
|
||
frontend_worker: | ||
# Configure the frontend worker in the querier to match worker count | ||
# to max_concurrent on the queriers. | ||
match_max_concurrent: true | ||
|
||
# Configure the ruler to scan the /tmp/cortex/rules directory for prometheus | ||
# rules: https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules | ||
ruler: | ||
enable_api: true | ||
enable_sharding: false | ||
storage: | ||
type: local | ||
local: | ||
directory: /tmp/cortex/rules | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# 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 opentelemetry import metrics | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. file should have the copyright at the top There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops, just added! |
||
from opentelemetry.exporter.prometheus_remote_write import ( | ||
PrometheusRemoteWriteMetricsExporter, | ||
) | ||
from opentelemetry.test.test_base import TestBase | ||
|
||
|
||
def observer_callback(observer): | ||
array = [1.0, 15.0, 25.0, 26.0] | ||
for (index, usage) in enumerate(array): | ||
labels = {"test_label": str(index)} | ||
observer.observe(usage, labels) | ||
|
||
|
||
class TestPrometheusRemoteWriteExporterCortex(TestBase): | ||
def setUp(self): | ||
super().setUp | ||
self.exporter = PrometheusRemoteWriteMetricsExporter( | ||
endpoint="http://localhost:9009/api/prom/push", | ||
headers={"X-Scope-Org-ID": "5"}, | ||
) | ||
self.labels = {"environment": "testing"} | ||
self.meter = self.meter_provider.get_meter(__name__) | ||
metrics.get_meter_provider().start_pipeline( | ||
self.meter, self.exporter, 1, | ||
) | ||
|
||
def test_export_counter(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We originally had the pattern you linked but were recommended internally to let the test Error out naturally since that fails as well. The main issue we found with catch ExceptionType was it only handled one Exception type. Is this wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is wrong. Every test case must have at least one assertion, since that indicates what is the intention of the test case. Even if your intention is test that this code does not raise an exception then that must be made obvious by using an assertion. It is not the same thing when a test case fails because, let's say, an For example, imagine you are testing the performance of a server. As every test case, it begins with a criteria that must be met for the test to pass. Let's say, the server must be able to reply back to 100 requests in a second. So, your test case basically consists in this:
If your test case fails with an This makes sense because a tester can't report back to a developer any other result than a pass or a failure with an So, to summarize, it is perfectly fine that your testing criteria is this code must run without raising any exception. Even so, you must assert that, so that it is obvious to anyone that reads your test case what the intention of the test case is. Something else, Python allows you to catch multiple exceptions types. Also keep in mind that what except does is pretty much the same as class Parent(Exception):
pass
class Child0(Parent):
pass
class Child1(Parent):
pass
try:
raise Child0()
except Parent:
print("Caught a Child0")
try:
raise Child1()
except Parent:
print("Caught a Child1")
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By the way, pytest makes it confusing because every exception raised in a test case is reported as a failure. In my opinion, any non- from pytest import fixture
@fixture
def preparation():
1 / 0
def test_case(preparation):
assert 1 > 0
As you can see here, the result of the run is Maybe someday I'll write a pytest plugin that will make every non There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ahh okay, thanks for the detailed answer! I will fix it rn :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although I am not the one making the fix, just wanted to say thanks for the detailed response. It was very insightful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My pleasure, fantastic job on getting all these PRs done @AzfaarQureshi @shovnik 💪 |
||
try: | ||
requests_counter = self.meter.create_counter( | ||
name="counter", | ||
description="test_export_counter", | ||
unit="1", | ||
value_type=int, | ||
) | ||
requests_counter.add(25, self.labels) | ||
except Exception as e: | ||
self.fail( | ||
"Export counter failed with unexpected error {}".format(e) | ||
) | ||
|
||
def test_export_valuerecorder(self): | ||
try: | ||
requests_size = self.meter.create_valuerecorder( | ||
name="valuerecorder", | ||
description="test_export_valuerecorder", | ||
unit="1", | ||
value_type=int, | ||
) | ||
requests_size.record(25, self.labels) | ||
except Exception as e: | ||
self.fail( | ||
"Export valuerecorder failed with unexpected error {}".format( | ||
e | ||
) | ||
) | ||
|
||
def test_export_updowncounter(self): | ||
try: | ||
requests_size = self.meter.create_updowncounter( | ||
name="updowncounter", | ||
description="test_export_updowncounter", | ||
unit="1", | ||
value_type=int, | ||
) | ||
requests_size.add(-25, self.labels) | ||
except Exception as e: | ||
self.fail( | ||
"Export updowncounter failed with unexpected error {}".format( | ||
e | ||
) | ||
) | ||
|
||
def test_export_sumobserver(self): | ||
try: | ||
self.meter.register_sumobserver( | ||
callback=observer_callback, | ||
name="sumobserver", | ||
description="test_export_sumobserver", | ||
unit="1", | ||
value_type=float, | ||
) | ||
except Exception as e: | ||
self.fail( | ||
"Export sumobserver failed with unexpected error {}".format(e) | ||
) | ||
|
||
def test_export_updownsumobserver(self): | ||
try: | ||
self.meter.register_updownsumobserver( | ||
callback=observer_callback, | ||
name="updownsumobserver", | ||
description="test_export_updownsumobserver", | ||
unit="1", | ||
value_type=float, | ||
) | ||
except Exception as e: | ||
self.fail( | ||
"Export updownsumobserver failed with unexpected error {}".format( | ||
e | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed that the markdown was incorrect for some of the previous Remote Write Exporter links
(text)[url]
instead of[text](url)
. Also took the opportunity to specify changes were to the Prometheus RW Exporter.