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)