Repository: ansible/awx
File: awx/main/analytics/subsystem_metrics.py (Python)

Code before:
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(settings.METRICS_SERVICE_DISPATCHER, *args, **kwargs)


class CallbackReceiverMetrics(Metrics):
    METRICSLIST = [
        SetIntM('callback_receiver_events_queue_size_redis', 'Current number of events in redis queue'),
        IntM('callback_receiver_events_popped_redis', 'Number of events popped from redis'),
        IntM('callback_receiver_events_in_memory', 'Current number of events in memory (in transfer from redis to db)'),
        IntM('callback_receiver_batch_events_errors', 'Number of times batch insertion failed'),
        FloatM('callback_receiver_events_insert_db_seconds', 'Total time spent saving events to database'),
        IntM('callback_receiver_events_insert_db', 'Number of events batch inserted into database'),
        IntM('callback_receiver_events_broadcast', 'Number of events broadcast to other control plane nodes'),
        HistogramM(
            'callback_receiver_batch_events_insert_db', 'Number of events batch inserted into database', settings.SUBSYSTEM_METRICS_BATCH_INSERT_BUCKETS
        ),
        SetFloatM('callback_receiver_event_processing_avg_seconds', 'Average processing time per event per callback receiver batch'),
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(settings.METRICS_SERVICE_CALLBACK_RECEIVER, *args, **kwargs)


def _get_dispatcherd_metrics(request):
    metrics_cfg = settings.METRICS_SUBSYSTEM_CONFIG.get('server', {}).get(settings.METRICS_SERVICE_DISPATCHER, {})
    host = metrics_cfg.get('host', 'localhost')
    port = metrics_cfg.get('port', 8015)
    metrics_filter = []
    if request is not None and hasattr(request, "query_params"):
        try:
            nodes_filter = request.query_params.getlist("node")
        except Exception:
            nodes_filter = []
        if nodes_filter and settings.CLUSTER_HOST_ID not in nodes_filter:
            return ''
        try:
            metrics_filter = request.query_params.getlist("metric")
        except Exception:
            metrics_filter = []
    if metrics_filter:
        dispatcher_metrics = {metric.field for metric in DispatcherMetrics.METRICSLIST}
        if not dispatcher_metrics.intersection(metrics_filter):
            return ''
    url = f"http://{host}:{port}/metrics"
    try:
        with urllib.request.urlopen(url, timeout=1.0) as response:
            payload = response.read()
            if not payload:
                return ''

Review comment (suggestion):
given this code doesn't really use anything in subsystem metrics, and has it's own mechanisms of retreiving metric data, you may consider putting this code into a new file and just concatenate the metrics here https://github.com/ansible/awx/blob/82cb52d64830c6831aa42913ecfce011d3d2c7ce/awx/api/views/metrics.py#L48

Code after:
        super().__init__(settings.METRICS_SERVICE_DISPATCHER, *args, **kwargs)


class CallbackReceiverMetrics(Metrics):
    METRICSLIST = [
        SetIntM('callback_receiver_events_queue_size_redis', 'Current number of events in redis queue'),
        IntM('callback_receiver_events_popped_redis', 'Number of events popped from redis'),
        IntM('callback_receiver_events_in_memory', 'Current number of events in memory (in transfer from redis to db)'),
        IntM('callback_receiver_batch_events_errors', 'Number of times batch insertion failed'),
        FloatM('callback_receiver_events_insert_db_seconds', 'Total time spent saving events to database'),
        IntM('callback_receiver_events_insert_db', 'Number of events batch inserted into database'),
        IntM('callback_receiver_events_broadcast', 'Number of events broadcast to other control plane nodes'),
        HistogramM(
            'callback_receiver_batch_events_insert_db', 'Number of events batch inserted into database', settings.SUBSYSTEM_METRICS_BATCH_INSERT_BUCKETS
        ),
        SetFloatM('callback_receiver_event_processing_avg_seconds', 'Average processing time per event per callback receiver batch'),
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(settings.METRICS_SERVICE_CALLBACK_RECEIVER, *args, **kwargs)


def metrics(request):
    output_text = ''
    output_text += DispatcherMetrics().generate_metrics(request)
    output_text += CallbackReceiverMetrics().generate_metrics(request)

    dispatcherd_metrics = get_dispatcherd_metrics(request)
    if dispatcherd_metrics:
        output_text += dispatcherd_metrics
    return output_text


class CustomToPrometheusMetricsCollector(prometheus_client.registry.Collector):
    """
    Takes the metric data from redis -> our custom metric fields -> prometheus
    library metric fields.

    The plan is to get rid of the use of redis, our custom metric fields, and
    to switch fully to the prometheus library. At that point, this translation
    code will be deleted.
    """

    def __init__(self, metrics_obj, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._metrics = metrics_obj

    def collect(self):
        my_hostname = settings.CLUSTER_HOST_ID

        instance_data = self._metrics.load_other_metrics(Request(HttpRequest()))