def load_filtered_and_merged_tree(row: Row) -> Optional[StructuredDataNode]: """Load inventory tree from file, status data tree from row, merge these trees and returns the filtered tree""" hostname = row.get("host_name") inventory_tree = _load_structured_data_tree("inventory", hostname) status_data_tree = _create_tree_from_raw_tree(row.get("host_structured_status")) # If no data from livestatus could be fetched (CRE) try to load from cache # or status dir if status_data_tree is None: status_data_tree = _load_structured_data_tree("status_data", hostname) merged_tree = _merge_inventory_and_status_data_tree(inventory_tree, status_data_tree) return _filter_tree(merged_tree)
def metric_expression_to_graph_recipe_expression( expression: MetricExpression, translated_metrics: TranslatedMetrics, lq_row: Row, enforced_consolidation_function: Optional[GraphConsoldiationFunction], ) -> StackElement: """Convert 'user,util,+,2,*' into this: ('operator', '*', [('operator', '+', [('rrd', 'heute', u'heute', u'CPU utilization', ....""" rrd_base_element = ( "rrd", lq_row["site"], lq_row["host_name"], lq_row.get("service_description", "_HOST_"), ) expression = split_expression(expression)[0] atoms: List[RPNAtom] = [] # Break the RPN into parts and translate each part separately for part, cf in iter_rpn_expression(expression, enforced_consolidation_function): # Some parts are operators. We leave them. We are just interested in # names of metrics. if part in translated_metrics: # name of a variable that we know tme = translated_metrics[part] metric_names = tme.get("orig_name", [part]) # original name before translation # We do the replacement of special characters with _ right here. # Normally it should be a task of the core. But: We have variables # named "/" - which is very silly, but is due to the bogus perf names # of the df check. So the CMC could not really distinguish this from # the RPN operator /. for metric_name, scale in zip(metric_names, tme["scale"]): atoms.append(rrd_base_element + (pnp_cleanup(metric_name), cf, scale)) if len(metric_names) > 1: atoms.append(("operator", "MERGE")) else: try: atoms.append(("constant", float(part))) except ValueError: atoms.append(("operator", part)) return stack_resolver( atoms, is_operator=lambda x: x[0] == "operator", apply_operator=lambda op, a, b: (op + ([a, b], )), apply_element=lambda x: x, )
def _load_status_data_tree(hostname: Optional[HostName], row: Row) -> Optional[StructuredDataNode]: # If no data from livestatus could be fetched (CRE) try to load from cache # or status dir raw_status_data_tree = row.get("host_structured_status") if not raw_status_data_tree: return _load_structured_data_tree("status_data", hostname) return StructuredDataNode.deserialize( ast.literal_eval(raw_status_data_tree.decode("utf-8")))
def load_filtered_and_merged_tree(row: Row) -> Optional[StructuredDataNode]: """Load inventory tree from file, status data tree from row, merge these trees and returns the filtered tree""" hostname = row.get("host_name") inventory_tree = _load_structured_data_tree("inventory", hostname) status_data_tree = _load_status_data_tree(hostname, row) merged_tree = _merge_inventory_and_status_data_tree( inventory_tree, status_data_tree) return _filter_tree(merged_tree)
def render( self, what: str, row: Row, tags: List[TagID], custom_vars: Dict[str, str], ) -> Union[None, str, HTML, Tuple[str, str], Tuple[str, str, str]]: if row.get("service_check_command") != "check_mk-robotmk": return None return ( "robotmk", # TODO add icon _("Robotmk report of this service"), makeuri_contextless( request, [ ("site", row["site"]), ("host", row["host_name"]), ("service", row["service_description"]), ], filename="robotmk.py", ), )
def column_age_in_range(row: Row, column: str, bounds: MaybeBounds) -> bool: value = row.get(column) if not isinstance(value, (int, float)): return False return value_in_range(time.time() - value, bounds)