Created
November 15, 2021 01:56
-
-
Save autch/252103df180bd7d7edeb276202033231 to your computer and use it in GitHub Desktop.
Mirakurun exporter for Prometheus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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