Import data from a file and export it to Prometheus

1,107 views
Skip to first unread message

David Lorente Moldes

unread,
Nov 15, 2019, 9:56:54 AM11/15/19
to Prometheus Users
I want to know how I could get to import data from a text file and then export it to Prometheus. I've done a piece of code that it works but at the moment I try to display the values in Prometheus, it only shows one value and not all of them as I would like. Next, I just posted my code and attached some pictures about what Prometheus do and another one to show you what I want to get (Overall and Download Throughput graphics). I don't really know what is wrong to not obtain what I want. The problem is like Prometheus was not able to process such amount information in short amount of time. It only plots the first value. Besides, collect function is called more than once and it keeps plotting the same value again and again.

import os, time

from prometheus_client import start_http_server
from prometheus_client.core import GaugeMetricFamily, REGISTRY

class getParameters(object): # read some parameters from a given file and store them in a Gauge 
    def __init__(self, param):
        self.param = param

    def _readSheet(self):
        thgpt = GaugeMetricFamily('TFM_throughpt', 'Throughpt Measure', labels=['IP','module'])
        for file in os.listdir("."):
            if os.path.isfile(file) and file.startswith("test_", 0, 5):
                try:
                    with open(file,'r',encoding = 'utf-8') as f:
                        line = f.readline()
                        while line:
                            if line:
                                aux = line.split(" ")
                                if ('Thgptup:' in line):
                                    thgpt.add_metric([self.param, 'Upload'],float(aux[1]))
                                elif ('Thgptdown' in line):
                                    thgpt.add_metric([self.param, 'Download'],float(aux[1]))
                                elif ('Thgpt' in line):
                                    thgpt.add_metric([self.param, 'Overall'],float(aux[1]))
                                line = f.readline()

                        yield thgpt

                except Exception as f:
                    print(f)

    def _getParam(self): #just read the sample which has been stored in the  Gauge above
        for data in self._readSheet():
            yield data

    def collect(self):
        for x in self._getParam():
            yield x

        yield GaugeMetricFamily('my_gauge', 'Help text', value=7)

param = 'localhost'
REGISTRY.register(getParameters(param))
print ('Reading is Done!')
start_http_server(8000)

try:
    wait_time = 20.0
    while True:
        time.sleep(wait_time)
except KeyboardInterrupt:
    pass
Does anyone help me out with this task, please? I really appreciate your help.
Thanks in advance guys.
Captura de pantalla 2019-11-14 a las 22.28.33.png
Captura de pantalla 2019-11-14 a las 22.28.51.png
Captura de pantalla 2019-11-14 a las 22.33.02.png

Christian Hoffmann

unread,
Nov 17, 2019, 8:33:33 AM11/17/19
to David Lorente Moldes, Prometheus Users
On 11/15/19 3:56 PM, David Lorente Moldes wrote:
> I want to know how I could get to import data from a text file and then
> export it to Prometheus. I've done a piece of code that it works but at
> the moment I try to display the values in Prometheus, it only shows one
> value and not all of them as I would like. Next, I just posted my code
> and attached some pictures about what Prometheus do and another one to
> show you what I want to get (Overall and Download Throughput graphics).

As far as I understand, you are writing an exporter for a custom
application metric format in order to make Prometheus able to ingest
them, correct?

I see that you are looping over several files in the current directory.
What kind of files are they?

Is there some qualitative difference in the
area/content/partition/whatever they provide? If so, you will have to
add this information as a label to your metric. The simplest form would
be adding a filename="..." label which contains the source file name.

Your current output looks like this:
TFM_throughpt{IP="localhost",module="Overall"} 13.0
TFM_throughpt{IP="localhost",module="Download"} 30.0
TFM_throughpt{IP="localhost",module="Overall"} 43.0


With the change, it could look like this:

TFM_throughpt{IP="localhost",module="Overall",filename="test_foo"} 13.0
TFM_throughpt{IP="localhost",module="Download",filename="test_foo"} 30.0
TFM_throughpt{IP="localhost",module="Overall",filename="test_foo"} 43.0
TFM_throughpt{IP="localhost",module="Overall",filename="test_bar"} 3.0
TFM_throughpt{IP="localhost",module="Download",filename="test_bar"} 0.0
TFM_throughpt{IP="localhost",module="Overall",filename="test_bar"} 3.0

If the difference is rather a temporal one such as "measurements for
hour 4, measurements for hour 5" etc., you will have to think about
other ways for ingestion. Prometheus will always scrape the most recent
data and this is what exporters are supposed to provide.
The temporal/historical dimension simply comes from Prometheus
repeatedly scraping the same address.
If this is the case for you, one solution would be simply dropping the
loop and always opening the "test_current" file (or whatever the file is
called which provides the most-recent measurements).

Some additional notes:
- You may want to have a look at the docs regarding metric naming. For
example, I suggest adding the unit to your metric such as
tfm_throughput_bytes.
- You should also verify that the IP= label is a good idea. If this is a
one-to-one mapping per instance, you might as well use the instance
label [2]. If it contains lots of target IPs, you may run into
cardinality problems [1].
- If "Overall" is just the sum of "Download" and "Upload", you could
also skip this as this could easily be calculated in PromQL.
- If you can control what the files look like, there may be an easier
way to go: node_exporter already has a textfile collector which simply
exposes the metrics from static files in a specific directory [3].
However, you cannot do any format transformations there. In other words:
The files must contain valid data in the Prometheus exposition format.
Also, node_exporter is mainly targeted at instance-level data.


[1] https://prometheus.io/docs/practices/naming/
[2] https://www.robustperception.io/controlling-the-instance-label
[3] https://github.com/prometheus/node_exporter#textfile-collector

Kind regards,
Christian
Reply all
Reply to author
Forward
0 new messages