72 lines
2.1 KiB
Python
72 lines
2.1 KiB
Python
|
from typing import List
|
||
|
|
||
|
import json
|
||
|
from datetime import datetime
|
||
|
from urllib.error import HTTPError
|
||
|
import traceback
|
||
|
|
||
|
import bottle
|
||
|
from isodate import Duration
|
||
|
|
||
|
from icalendar_timeseries_server.config import get_config
|
||
|
from icalendar_timeseries_server.event import Event
|
||
|
from icalendar_timeseries_server.cal import scrape_calendar
|
||
|
from icalendar_timeseries_server.query import MetricQuery
|
||
|
|
||
|
|
||
|
@bottle.route('/api/v1/query')
|
||
|
@bottle.route('/api/v1/query_range')
|
||
|
def prometheus_api():
|
||
|
tz = get_config().tz
|
||
|
now: datetime = datetime.now(tz)
|
||
|
start_delta: Duration = get_config().start_delta
|
||
|
end_delta: Duration = get_config().end_delta
|
||
|
start: datetime = now + start_delta
|
||
|
end: datetime = now + end_delta
|
||
|
events: List[Event] = []
|
||
|
|
||
|
try:
|
||
|
q = MetricQuery(bottle.request.query['query'])
|
||
|
except ValueError as e:
|
||
|
response = {
|
||
|
'status': 'error',
|
||
|
'errorType': 'bad_data',
|
||
|
'error': str(e)
|
||
|
}
|
||
|
bottle.response.status = 400
|
||
|
traceback.print_exc()
|
||
|
bottle.response.add_header('Content-Type', 'application/json')
|
||
|
return json.dumps(response)
|
||
|
|
||
|
try:
|
||
|
for name, caldef in get_config().calendars.items():
|
||
|
events.extend(scrape_calendar(name, caldef, start, end))
|
||
|
events = list(filter(q, events))
|
||
|
events.sort(key=lambda e: e.start)
|
||
|
response = {
|
||
|
'status': 'success',
|
||
|
'data': {
|
||
|
'resultType': 'vector',
|
||
|
'result': [e.serialize() for e in events]
|
||
|
}
|
||
|
}
|
||
|
except HTTPError as e:
|
||
|
response = {
|
||
|
'status': 'error',
|
||
|
'errorType': 'internal',
|
||
|
'error': str(e)
|
||
|
}
|
||
|
bottle.response.status = 500
|
||
|
traceback.print_exc()
|
||
|
except BaseException:
|
||
|
response = {
|
||
|
'status': 'error',
|
||
|
'errorType': 'internal',
|
||
|
'error': 'An internal error occurred.'
|
||
|
}
|
||
|
bottle.response.status = 500
|
||
|
traceback.print_exc()
|
||
|
|
||
|
bottle.response.add_header('Content-Type', 'application/json')
|
||
|
return json.dumps(response)
|