This article provides a guide on creating a custom Python exporter for Prometheus to monitor the number of .txt files in a specified directory.
Abstract
The article titled "Create Your Python’s Custom Prometheus Exporter" is a tutorial aimed at developers who need to design custom metrics exporters for Prometheus. It explains the necessity of a custom exporter in certain scenarios despite the availability of various existing exporters provided by the Prometheus community. The author guides readers through the process of building a simple exporter using Python, which monitors the count of .txt files within a user-defined folder. The article emphasizes the use of the Python Prometheus client library, the importance of naming conventions for metrics, and the implementation of an endpoint to expose the metrics for scraping by Prometheus. The code example demonstrates the use of a few Python modules such as logging, argparse, os, time, and prometheus_client. It includes a class that uses a dictionary to store metrics and a gauge to represent the count, which is updated in an infinite loop. The article also touches on the future possibility of deploying such exporters on AWS EC2 instances and integrating them with an EKS cluster using AWS services like EventBridge and Lambda.
Opinions
The author suggests that building a custom Prometheus exporter in Python is straightforward and encourages the use of the Python Prometheus client library.
Reading the Prometheus naming conventions documentation is highly recommended by the author for creating properly named metrics.
The author expresses a preference for using a dictionary to store metrics in the context of an infinite loop to maintain the same metric and update its gauge counter.
The use of list comprehension in Python is encouraged for making the code more "pythonic."
The article concludes with an encouragement for readers to explore the Prometheus documentation to understand different metric types and their use cases.
The author plans to elaborate on deploying custom exporters in AWS environments in a follow-up article, hinting at the use of AWS EventBridge and Lambda for automatic discovery by Prometheus nodes in an EKS cluster.
Despite all the exporters (https://prometheus.io/docs/instrumenting/exporters/) that Prometheus and its community can offer, in some particular use cases, you may want to design your own exporter to run your custom checks. No worries, Prometheus has got you covered!
If you check this GitHub repository, you will find a Python Prometheus client that you can use and abuse to build up your exporter.
Through this article, we will build a simple exporter to monitor the number of .txt files inside a folder and return a custom metric over the classic /metrics endpoint.
Before we discuss the code, let’s quickly look at how Prometheus works and how you can expose your metrics to have them scrapped by the tool.
Nothing complicated here. We will expose an endpoint that is accessible by another instance.
I also highly suggest reading this documentation that can help to create a proper naming convention for our metrics. Note that this is just a convention, meaning you can create metrics with the name you want.
Speaking about the code itself, I will use very few modules to keep it simple:
logging module to add some logs to our exporter
argparse, to pass our folder/extension arguments
os, time (no description is needed for these two)
prometheus_client, specifically two methods: start_http_server (start up our endpoint) and Gauge.
A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
This code creates a super simple class that we will use a dictionary (metric_dict) to store our metrics. You can store as many metrics as you want in a dict.
I’m using a dictionary here because the main program is an infinite loop. I want to keep the same metric and just update the Gauge counter by the current value.
The class contains two arguments, the folder to watch and the file extension to count.
The custom function (count_file_in_folder) is in charge of counting our metric value
That function is pretty straightforward; we just create a list of matching files in a folder and return its length. We use list comprehension here to make it a little bit more pythonic.
The exporter metric part is really easy to go through.
1) We create a new Gauge into our dict if the metric does not exists (basically, first run of the loop)
defcreate_gauge_for_metric(self, metric_name):
if self.metric_dict.get(metric_name) isNone:
self.metric_dict[metric_name] = Gauge(metric_name, f"number of *{self.ext} files in {self.folder}")
2) We set a value for our Gauge based on the count_file_in_folder result.
The main program is an infinite loop on top of a web server
The main function uses the start_http_server method from the Prometheus client, which takes a port as an argument to start.
The while True loop is running our two metrics functions (create_gauge_for_metric and set_value). For this example, I put a sleep of ten seconds to refresh more often. This value can be adapted based on your use case.
As you can see on the above capture, we have three different terminals opened:
1. On the left, I’m just creating a new file to increment our metric counter
2. The exporter's output log is in the middle of the screen. Note that the number of files increased from 1 to 2.
3. On the right, the metrics endpoint is accessible over port 9877/metrics. The value also increases from 1 to 2.
And, that’s it. As you’ve noticed, creating some metrics and exposing them using the Prometheus client package is really easy.
Nevertheless, I highly encourage you to read the documentation to understand the different metrics types you can use to fit your needs.
In the next article, I will explain how you can have those exporters running into AWS EC2 instances and have the exporter automatically discovered by a Prometheus node running in an EKS cluster located in a different account.
Spoiler, we will use event bridge and lambda.
Let me know if you have any questions regarding this solution!