I was figuring out the same thing, and the solution was as simple as you would imagine.
Updated your example code to work:
from multiprocessing import Process
import shutil
import time, os
from prometheus_client import start_http_server, multiprocess, CollectorRegistry, Counter
COUNTER1 = Counter('counter1', 'Incremented by the first child process')
COUNTER2 = Counter('counter2', 'Incremented by the second child process')
COUNTER3 = Counter('counter3', 'Incremented by both child processes')
def f1():
while True:
time.sleep(1)
print("Child process 1")
COUNTER1.inc()
COUNTER3.inc()
def f2():
while True:
time.sleep(1)
print("Child process 2")
COUNTER2.inc()
COUNTER3.inc()
if __name__ == '__main__':
# ensure variable exists, and ensure defined folder is clean on start
prome_stats = os.environ["PROMETHEUS_MULTIPROC_DIR"]
if os.path.exists(prome_stats):
shutil.rmtree(prome_stats)
os.mkdir(prome_stats)
# pass the registry to server
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
start_http_server(8000, registry=registry)
p = Process(target=f1, args=())
a = p.start()
p2 = Process(target=f2, args=())
p2.start()
print("collect")
while True:
time.sleep(1)
localhost:8000/metrics
# HELP counter1_total Incremented by the first child process
# TYPE counter1_total counter
counter1_total 9.0
# HELP counter2_total Incremented by the second child process
# TYPE counter2_total counter
counter2_total 9.0
# HELP counter3_total Incremented by both child processes
# TYPE counter3_total counter
counter3_total 18.0
Answer from potato_cannon on Stack OverflowPrometheus's Python -prometheus_client-. "start_http_server" question/issue
python - Prometheus how to expose metrics in multiprocess app with start_http_server - Stack Overflow
start_http_server dual stack and IPv6 literals
python - Is there an arg to set other endpoint in start_http_server (prometheus_client) instead of /? - Stack Overflow
Hi all,
I'm using Python prometheus_client's start_http_server, when I set up a service file for the script, I get a broken pipe error:
self.RequestHandlerClass(request, client_address, self) File "/usr/lib64/python2.7/SocketServer.py", line 651, in __init__ self.finish() File "/usr/lib64/python2.7/SocketServer.py", line 710, in finish self.wfile.close() File "/usr/lib64/python2.7/socket.py", line 279, in close self.flush() File "/usr/lib64/python2.7/socket.py", line 303, in flush self._sock.sendall(view[write_offset:write_offset+buffer_size]) error: [Errno 32] Broken pipe
I'm posting it here as it comes from the start_http_server, since thats what I use to start the server, otherwise I would have checked the "/usr/lib64/python2.7/socket.py".
Here is my service's unit systemctl file:
[Unit] Description=Dead Exporter After=local-fs.target network-online.target network.target Wants=local-fs.target network-online.target network.target [Service] WorkingDirectory=/net/systems/tools/deadExporter #User=blah Type=simple Restart=on-failure RestartSec=30 ExecStart=/net/systems/tools/deadExporter/dead.py [Install] WantedBy=multi-user.target
I'll show my code and I'm pretty much sure its related to how I build the name == "main": but I cant put my finger on it.
I added the time.sleep(1) as without the while loop, I cant keep the server up, I"m guessing its the right way to do so!??
I learned the the Metrics build in to be in the file scope. So I hope thats fine.
Can anyone tell me if you see something wrong?
Code:
import sys
import time
from prometheus_client import Counter
from prometheus_client import start_http_server
from prometheus_client import CounterMetricFamily
from prometheus_client import REGISTRY
class DeadCollector(object):
def collect(self):
print('FIRE!')
c = CounterMetricFamily("woohoo", 'Woohoo is the greatest', labels=['stat'])
c.add_metric(['statVal'], 0.0)
yield c
timer = time.time()
REGISTRY.register(DeadCollector())
print('\nFinished dead in {:.2f}sec'.format(time.time() - timer))
if __name__ == '__main__':
# start the server
start_http_server(9366)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print('\nYou killed Kenny, you bastard!\n')
sys.exit()One last thing, The serer runs, the error comes only from the systemctl service unit, however... you see that "FIRE!" print, when I run this locally, just a simple (shell)
clear;python dead.py
everytime I refresh the browser, I get the FIRE twice! once as I press reload and once when its done.
I am missing something again? Shouldn't it run just once?
Any help will do, Thank you!
When flask's debug mode is set to True, the code reloads after the flask server is up, and a bind to the prometheus server is been called a second time
Set flask app debug argument to False to solve it
Some other process is utilizing the port (8000). To kill the process that is running on the port (8000), simply find the process_id [pid] of the process.
lsof -i :8000
This will show you the processes running on the port 8000 like this:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 21271 hashed 3u IPv4 1430288 0t0 TCP *:8000 (LISTEN)
You can kill the process using the kill command like this:
sudo kill -9 21271
Recheck if the process is killed using the same command
lsof -i :8000
There should be nothing on the stdout.