Skip to content

Instantly share code, notes, and snippets.

@autch
Created November 15, 2021 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save autch/252103df180bd7d7edeb276202033231 to your computer and use it in GitHub Desktop.
Save autch/252103df180bd7d7edeb276202033231 to your computer and use it in GitHub Desktop.
Mirakurun exporter for Prometheus
FROM alpine:3.11
LABEL maintainer "collelog <collelog.cavamin@gmail.com>"
EXPOSE 9684
WORKDIR /usr/local/
RUN set -eux && \
apk upgrade --update && \
apk add --no-cache python3 tzdata && \
\
# timezone
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
echo "Asia/Tokyo" > /etc/timezone && \
apk del tzdata && \
\
mkdir /usr/local/mirakurun && \
cd /usr/local/mirakurun && \
\
# install Python Package
pip3 install prometheus-client && \
pip3 install requests-unixsocket && \
\
# cleaning
rm -rf /tmp/* /var/cache/apk/*
COPY exec_mirakurun_exporter.py /usr/local/mirakurun/
WORKDIR /usr/local/mirakurun
ENTRYPOINT ["/usr/bin/python3", "-u", "/usr/local/mirakurun/exec_mirakurun_exporter.py"]
#!/usr/bin/python3
import requests_unixsocket
import requests
import socket
import time
import argparse
from prometheus_client import start_http_server, Summary, Gauge
requests_unixsocket.monkeypatch()
status_memory_usage = Gauge('mirakurun_memory_usage_bytes', 'Mirakurun Memory Usage', ['label'])
status_programs_db = Gauge('mirakurun_programs_db_events', 'Mirakurun Programs DB', ['label'])
status_stream_count= Gauge('mirakurun_stream_count', 'Mirakurun Stream Count', ['label'])
status_error_count = Gauge('mirakurun_error_count', 'Mirakurun Error Count', ['label'])
status_timer_accuracy = Gauge('mirakurun_timer_accuracy', 'Mirakurun Timer Accuracy', ['label'])
def process_request(address: str):
res = requests.get(address)
res_dict = res.json()
status_memory_usage.labels('rss').set(res_dict['process']['memoryUsage']['rss'])
status_memory_usage.labels('heapTotal').set(res_dict['process']['memoryUsage']['heapTotal'])
status_memory_usage.labels('heapUsed').set(res_dict['process']['memoryUsage']['heapUsed'])
status_programs_db.labels('storedEvents').set(res_dict['epg']['storedEvents'])
status_stream_count.labels('decoder').set(res_dict['streamCount']['decoder'])
status_stream_count.labels('tsFilter').set(res_dict['streamCount']['tsFilter'])
status_stream_count.labels('tunerDevice').set(res_dict['streamCount']['tunerDevice'])
status_error_count.labels('uncaughtException').set(res_dict['errorCount']['uncaughtException'])
status_error_count.labels('bufferOverflow').set(res_dict['errorCount']['bufferOverflow'])
status_error_count.labels('tunerDeviceRespawn').set(res_dict['errorCount']['tunerDeviceRespawn'])
status_timer_accuracy.labels('m1avg').set(res_dict['timerAccuracy']['m1']['avg'])
status_timer_accuracy.labels('m5avg').set(res_dict['timerAccuracy']['m5']['avg'])
status_timer_accuracy.labels('m15avg').set(res_dict['timerAccuracy']['m15']['avg'])
print('# %s' % (time.ctime()))
print('process.memoryUsage.rss: %s' % (res_dict['process']['memoryUsage']['rss']))
print('process.memoryUsage.heapTotal: %s' % (res_dict['process']['memoryUsage']['heapTotal']))
print('process.memoryUsage.heapUsed: %s' % (res_dict['process']['memoryUsage']['heapUsed']))
print('epg.storedEvents: %s' % (res_dict['epg']['storedEvents']))
print('res.streamCount.decoder: %s' % (res_dict['streamCount']['decoder']))
print('res.streamCount.tsFilter: %s' % (res_dict['streamCount']['tsFilter']))
print('res.streamCount.tunerDevice: %s' % (res_dict['streamCount']['tunerDevice']))
print('errorCount.uncaughtException: %s' % (res_dict['errorCount']['uncaughtException']))
print('errorCount.bufferOverflow: %s' % (res_dict['errorCount']['bufferOverflow']))
print('errorCount.tunerDeviceRespawn: %s' % (res_dict['errorCount']['tunerDeviceRespawn']))
print('timerAccuracy.m1.avg: %s' % (res_dict['timerAccuracy']['m1']['avg']))
print('timerAccuracy.m5.avg: %s' % (res_dict['timerAccuracy']['m5']['avg']))
print('timerAccuracy.m15.avg: %s' % (res_dict['timerAccuracy']['m15']['avg']))
def wait_next_period(interval: int, offset: int, exact: bool=False):
if not exact:
time.sleep(interval)
return
now = time.time()
inow = int(now)
next_1m = inow - (inow % interval) + interval + offset
wait = next_1m - now
time.sleep(wait)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--port', help='port number to listen (%(default)d)', type=int, default=9684)
parser.add_argument('-i', '--interval', help='polling interval in seconds (%(default)d)', type=int, default=60)
parser.add_argument('-e', '--exact', help='poll at specified OFFSET second in every INTERVAL seconds', action='store_true')
parser.add_argument('-o', '--offset', help='with --exact, offset seconds to every INTERVAL (%(default)d)', type=int, default=0)
parser.add_argument('-u', '--url', help='URL to connect (%(default)s)',
default='http+unix://%2Fvar%2Frun%2Fmirakurun%2Fmirakurun.sock/api/status')
args = parser.parse_args()
# Start up the server to expose the metrics.
start_http_server(args.port)
# Generate some requests.
while True:
try:
process_request(args.url)
wait_next_period(args.interval, args.offset, args.exact)
except TypeError:
print('TypeError returned from mirakurun-exporter server')
except requests.exceptions.ConnectionError:
print('requests.exceptions.ConnectionError returned from mirakurun-exporter server')
wait_next_period(args.interval, args.offset, args.exact)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment