def run(): api = dbApi.dbApi() while True: print("Calculating complex measurements, time: ", datetime.now()) complexEntries = api.getCpxDefinitions() measDefs = [MeasurementDef.fromDict(v) for v in complexEntries] for measDef in measDefs: cpxCalculator = CpxCalculator(measDef) sessionIds = api.getSessionIds(measDef.getFilter()) nowTime = datetime.now() for sessionId in sessionIds: simpleMeasurements = api.getMeasurements( sessionId, measDef.parent_id, measDef.lastCalcTime, nowTime, ) cpxValues = cpxCalculator.calculate(simpleMeasurements, nowTime) print(sessionId, measDef.metric_id, cpxValues) if len(cpxValues) > 0: api.insertMeasurements(sessionId, measDef.metric_id, cpxValues) measDef.lastCalcTime = nowTime api.updateMeasDefinition(measDef.hostname, measDef.metric_id, measDef.parent_id, measDef.movingWindow, measDef.interval, measDef.description, measDef.lastCalcTime, measDef.owner) time.sleep(60)
def delete_metric(metric_id, hostname): # noqa: E501 """Delete complex metric # noqa: E501 :param metric_id: Metric identyfier. It has the same form as `metric_id` field of `Metric` model :type metric_id: str :param hostname: Target host (domain name) :type hostname: str :rtype: object """ api = dbApi.dbApi() ids = api.getSessionIds({ api.HOSTNAME_KEY: hostname, api.METRIC_PATH: metric_id }) if len(ids) <= 0: return "Uknown metric or hostname", 404 cpxDef = api.getCpxDefinitions({api.METRIC_ID_KEY: metric_id}) if cpxDef: if cpxDef[api.OWNER_KEY] == get_jwt_identity(): api.deleteComplexMetric(hostname, metric_id) api.deleteMetric(hostname, metric_id) else: return "You aren't creator of complex metric", 403 else: return "Uknown metric, hostname or internal problem", 404 return "Success", 200
def post_metric(hostname, payload): # noqa: E501 """Add complex metric # noqa: E501 :param hostname: Target host (domain name) :type hostname: str :param payload: Complex mertic payload :type payload: dict | bytes :rtype: InlineResponse201 """ api = dbApi.dbApi() if connexion.request.is_json: payload = Payload.from_dict(connexion.request.get_json()) # noqa: E501 parent_id = payload.parent_id moving_window = payload.moving_window_duration interval = payload.interval if interval <= 0: return "Interval has to be greather than 0", 400 if moving_window <= 0: return "Moving window has to be greater than 0", 400 description = payload.description metric_id = ("cpx_" + str(parent_id) + "_" + str(moving_window) + "_" + str(interval)) metrics = api.getAllMetrics({dbApi.dbApi.HOSTNAME_KEY: hostname}) if metric_id in metrics: return "Metric id already exists", 409 print(metrics) if parent_id not in metrics: return "Unknown parent_id", 404 hostnames = api.getHosts(None) if hostname not in hostnames: return "Unknown hostname", 404 unit = api.updateMetricInMetadata(hostname, metric_id, parent_id, description) if unit == "": unit = "Unknown Unit" api.insertMeasDefinition( hostname, metric_id, parent_id, moving_window, interval, description, get_jwt_identity(), ) response = InlineResponse201(metric_id, unit) return response.to_dict(), 201
def get_metrics(): # noqa: E501 """List of metrics # noqa: E501 :rtype: List[Metric] """ api = dbApi.dbApi() metrics = api.getAllMetrics() response = [] for metric in metrics.keys(): interval = None moving_window = None parent_id = None hosts = api.getHostnameByMetric(metric) print("getCpxDefinitions, metric: ", metric) cpxDef = api.getCpxDefinitions({api.METRIC_ID_KEY: metric}) if cpxDef: print("cpxDef not none") hosts.append(cpxDef[api.HOSTNAME_KEY]) interval = cpxDef[api.INTERVAL_KEY] moving_window = cpxDef[api.MOVING_WINDOW_KEY] parent_id = cpxDef[api.PARENT_ID_KEY] print(parent_id) metric_object = Metric( id=metric, interval=interval, moving_window_duration=moving_window, description=metrics[metric][0], unit=metrics[metric][1], hosts=hosts, parent_id=parent_id, ) response.append(metric_object.to_dict()) return response
def get_hosts(q=None): # noqa: E501 """Get list of hosts # noqa: E501 :param q: Filters out used metrics and hosts according to provided keys. String needs to match the following schema: `KEY1:VAL1,KEY2:VAL2;KEY3:VAL4...`. Comma is used to indicate `AND` operation while semicolon relates to `OR`. When `VAL` paramater is wrapped into slashes then regex mode is activated. For example when we query for `metric_id:cpu,os:/.*nix.*/;metric_id:cpu,os:/.*win.*/` we should receive cpu metric measurements for hosts containing either nix or win as substring in `os` metadata. Note that `AND` operation has higher priority than `OR`. Allowed keys: `metric_id`, `description`, `complex` (metric parameters) and all available host metadata fields. When not provided: No filtering performed - all available metrics and hosts are taken :type q: str :rtype: List[Host] """ api = dbApi.dbApi() if q: hosts = [] filters = QueryResolver.QueryResolver(q).getFilters() for f in filters: hosts.extend(api.getHosts(query=f)) else: hosts = api.getHosts(query="") response = [] for host in hosts: metrics = get_metrics() metric_objects = [] for metric in metrics: cpxDef = api.getCpxDefinitions({api.METRIC_ID_KEY: metric["id"]}) if cpxDef: currentUser = get_jwt_identity() isRemovableByCurrentUser = cpxDef[api.OWNER_KEY] == currentUser metric["removable"] = isRemovableByCurrentUser metric_objects.append(Metric.from_dict(metric)) metrics = [] metrics = [m for m in metric_objects if host in m.hosts] metadatas = [ Metadata.from_dict(metadata) for metadata in api.getMetadataByHost(host) ] response.append((Host(hostname=host, metrics=metrics, metadata=metadatas)).to_dict()) return response
def get_measurements(start=None, end=None, q=None, limit=None, last=None): # noqa: E501 """Selected measurements # noqa: E501 :param start: ISO 8601 datetime format with 1s accuracy. Default value is current time subtracted by 1 day :type start: str :param end: ISO 8601 datetime format with 1s accuracy. Default value is current time. :type end: str :param q: Filters out used metrics and hosts according to provided keys. String needs to match the following schema: `KEY1:VAL1,KEY2:VAL2;KEY3:VAL4...`. Comma is used to indicate `AND` operation while semicolon relates to `OR`. When `VAL` paramater is wrapped into slashes then regex mode is activated. For example when we query for `metric_id:cpu,os:/.*nix.*/;metric_id:cpu,os:/.*win.*/` we should receive cpu metric measurements for hosts containing either nix or win as substring in `os` metadata. Note that `AND` operation has higher priority than `OR`. Allowed keys: `metric_id`, `description`, `complex` (metric parameters) and all available host metadata fields. When not provided: No filtering performed - all available metrics and hosts are taken :type q: str :param limit: Number of maximal amount of measurements given as a result of the query :type limit: :param last: If it is set as `TRUE` then the only last measurement meeting the criteria from `q` parameter is returned :type last: bool :rtype: List[Measurement] """ api = dbApi.dbApi() if not end: end = datetime.datetime.now() else: end = util.deserialize_datetime(end) if not start: start = datetime.datetime.now() - datetime.timedelta(days=1) else: start = util.deserialize_datetime(start) filters = [] if not q: filters.append(None) else: resolver = QueryResolver.QueryResolver(q) if resolver.validateQuery() == 0: return "Bad request", 400 else: filters = resolver.getFilters() print("start: " + str(start)) print("end: " + str(end)) print("q: " + str(q)) measurements = [] for metaFilter in filters: print("metaFilter: " + str(metaFilter)) for sessionId in api.getSessionIds(metaFilter): print("sessionId: " + str(sessionId)) metrics = list() if metaFilter and "metric_id" in metaFilter: metricFilter = metaFilter["metric_id"] print("Metrics filtering with filter: " + str(metricFilter)) metrics = api.getMetrics(sessionId, metricFilter) else: print("No metrics filtering, take all metrics") metrics = api.getMetrics(sessionId) for metric in metrics: print(sessionId) print(metric) print(start) print(end) dataPoints = api.getMeasurements(sessionId, metric, start, end) points = [ Point(point[VALUE_IND], point[TIME_IND]) for point in dataPoints ] measurement = Measurement(metric, api.getHostname(sessionId), points) measurements.append(measurement.to_dict()) return measurements