예제 #1
0
    def __init__(self,
                 liquidsoap: Liquidsoap,
                 bind_addr: str,
                 bind_port: int,
                 metrics_path: str = '/metrics',
                 loop: asyncio.AbstractEventLoop = None):
        self._liquidsoap = liquidsoap
        self._bind_addr = bind_addr
        self._bind_port = bind_port

        self._metrics_path = metrics_path

        if loop is None:
            loop = asyncio.get_event_loop()
        self._loop = loop

        self._sources = []  # type: [str]

        self.rms_gauge = Gauge('liquidsoap_rms',
                               'The current audio RMS volume of the source.',
                               ['source'])
        self.ls_startup_time = Gauge(
            'liquidsoap_start_time_seconds',
            'Start time of the liquidsoap process since unix epoch in seconds.'
        )

        self.ls_version = Info('liquidsoap', 'Liquidsoap version information')
class SystemInfoUpdater(ExporterPeriodicTask):
    def __init__(self, rpc):
        super(SystemInfoUpdater, self).__init__(rpc, 5 * 60)
        self._info = Info('polkadot_system', 'Polkadot system information')
        self._runtime_info = Info('polkadot_runtime',
                                  'Polkadot runtime information')

    def _perform_internal(self):
        self._info.info({
            'name':
            self._rpc.request('system_name')['result'],
            'version':
            self._rpc.request('system_version')['result'],
            'chain':
            self._rpc.request('system_chain')['result'],
        })

        runtime = self._rpc.request('state_getRuntimeVersion')['result']
        for key in list(runtime):
            if key not in ("authoringVersion", "implName", "implVersion",
                           "specName", "specVersion"):
                runtime.pop(key)
            else:
                runtime[key] = str(runtime[key])

        self._runtime_info.info(runtime)
예제 #3
0
    def __init__(self,
                 extractor_name: str,
                 extractor_version: str,
                 process_scrape_interval: float = 15):
        extractor_name = extractor_name.strip().replace(" ", "_")

        self.startup = Gauge(
            f"{extractor_name}_start_time",
            "Timestamp (seconds) of when the extractor last started")
        self.finish = Gauge(
            f"{extractor_name}_finish_time",
            "Timestamp (seconds) of then the extractor last finished cleanly")

        self._process = psutil.Process(os.getpid())

        self.process_num_threads = Gauge(f"{extractor_name}_num_threads",
                                         "Number of threads")
        self.process_memory_bytes = Gauge(f"{extractor_name}_memory_bytes",
                                          "Memory usage in bytes")
        self.process_cpu_percent = Gauge(f"{extractor_name}_cpu_percent",
                                         "CPU usage percent")

        self.info = Info(f"{extractor_name}_info",
                         "Information about running extractor")
        self.info.info({
            "extractor_version": extractor_version,
            "extractor_type": extractor_name
        })

        self.process_scrape_interval = process_scrape_interval
        self._start_proc_collector()

        self.startup.set_to_current_time()
예제 #4
0
class PPPoESessionCollector(BaseCollector):
    METRICS_SUBSYSTEM = 'pppoe'
    ENDPOINT = 'session'

    def __init__(self, client: Client):
        super().__init__(client)

        self._session = Info(namespace=self.METRICS_NAMESPACE,
                             subsystem=self.METRICS_SUBSYSTEM,
                             name='session',
                             documentation='Information about PPPoE Session')

        self._mtu = Gauge(namespace=self.METRICS_NAMESPACE,
                          subsystem=self.METRICS_SUBSYSTEM,
                          name='mtu',
                          documentation='The MTU of the PPPoE')

    def _process_data(self, data):
        mtu = data['MTU']
        del data['MTU']
        if mtu:
            self._mtu.set(mtu)
        else:
            self._mtu.set(-1)

        self._session.info(data)
def main():
    """Start exporter web server and refresh bios information"""

    # Parse Arguments
    parser = argparse.ArgumentParser(description='BIOS Prometheus Exporter')
    parser.add_argument('--port',
                        dest='port',
                        default=8000,
                        type=int,
                        action='store',
                        help='Set listening port')
    args = parser.parse_args()

    # Catch signals
    signal.signal(signal.SIGINT, exit_gracefully)
    signal.signal(signal.SIGTERM, exit_gracefully)

    # Create metric
    bios = Info('bios', 'Node BIOS Information')

    # Start Listener
    start_http_server(args.port)
    print("Listening on port", args.port, end='', flush=True)

    # Update BIOS Information
    while True:
        bios.info(get_bios_info())
        print('.', end='', flush=True)
        sleep(30)
예제 #6
0
 def test_info(self):
     i = Info('ii', 'A info', ['a', 'b'], registry=self.registry)
     i.labels('c', 'd').info({'foo': 'bar'})
     self.assertEqual(
         json.loads(
             """{"ii": {"samples": [{"sample_name": "ii_info", "labels": {"a": "c", "b": "d", 
     "foo": "bar"}, "value": "1.0", "timestamp": null, "exemplar": {}}], "help": "A info", "type": "info"}}"""
         ), json.loads(self.json_exporter.generate_latest_json()))
예제 #7
0
    def test_info(self):
        i = Info('ii', 'A info', ['a', 'b'], registry=self.registry)
        i.labels('c', 'd').info({'foo': 'bar'})
        self.assertEqual(b"""# HELP ii A info
# TYPE ii info
ii_info{a="c",b="d",foo="bar"} 1.0
# EOF
""", generate_latest(self.registry))
예제 #8
0
def start_prometheus_server(port):
    hostname = socket.gethostname()
    log.debug(
        f"[prometheus] Start web server: 0.0.0.0:{port} (Host:{hostname})")
    start_http_server(port)
    prometheus_info = Info("synology_exporter", "Synology Prometheus exporter")
    prometheus_info.info({"version": exporter_version, "running_on": hostname})
    log.info(f"[prometheus] Web server started: {hostname}:{port}")
    def __init__(self,
                 prometheus,
                 live: bool,
                 project_name: str,
                 registry=None):
        self.project_name = project_name
        self.prometheus = prometheus
        self.namespace = "csv_live" if live else "csv_hist"
        self.label_values = {self.project_name}
        self.registry = CognitePrometheus.registry if registry is None else registry

        self.info = Info("host",
                         "Host info",
                         namespace=self.namespace,
                         registry=CognitePrometheus.registry)
        self.info.info({
            "hostname": socket.gethostname(),
            "fqdn": socket.getfqdn()
        })
        self.process = ProcessCollector(namespace=self.namespace,
                                        registry=CognitePrometheus.registry)
        self.platform = PlatformCollector(registry=CognitePrometheus.registry)

        self.created_time_series_counter = self._create_metric(
            Counter, "created_time_series_total",
            "Number of time series created since the extractor started running"
        )

        self.all_data_points_counter = self._create_metric(
            Counter, "posted_data_points_total",
            "Number of datapoints posted since the extractor started running")

        self.count_of_time_series_gauge = self._create_metric(
            Gauge, "posted_time_series_count",
            "Number of timeseries that had valid datapoints in the current file"
        )

        self.processing_failed_counter = self._create_metric(
            Counter,
            "failed_processing_files",
            "Number of files where processing failed since the extractor started running",
        )

        self.available_csv_files_gauge = self._create_metric(
            Gauge, "available_csv_files",
            "Number of csv files in the folder that could be processed by the extractor"
        )

        self.unprocessed_files_gauge = self._create_metric(
            Gauge, "unprocessed_files",
            "Number of csv files that remains to be processed in this batch")

        self.successfully_processed_files_gauge = self._create_metric(
            Gauge,
            "successfully_processed_files",
            "Number of csv files that has been successfully processed in this batch",
        )
예제 #10
0
def init_http_server(port):
    hostname = socket.gethostname()
    log.debug(
        f"Start Prometheus web server: 0.0.0.0:{port} (Host:{hostname}) ..")
    start_http_server(port)
    prometheus_info = Info("mi_flower_exporter",
                           "Mi-Flower Prometheus exporter")
    prometheus_info.info({"version": VERSION, "running_on": hostname})
    log.info(f"Prometheus web server started: {hostname}:{port}")
예제 #11
0
class ModuleCollector(BaseCollector):
    METRICS_SUBSYSTEM = 'module'

    def __init__(self, client: Client):
        super().__init__(client)

        self._info = Info(namespace=self.METRICS_NAMESPACE,
                          name=self.METRICS_SUBSYSTEM,
                          documentation='Firmware version information')

    def _process_data(self, data):
        self._info.info(data)
예제 #12
0
def metrics():
    registry = CollectorRegistry()
    multiprocess.MultiProcessCollector(registry)

    ProcessCollector(registry=registry)
    PlatformCollector(registry=registry)

    i = Info('build_info', "The build information", registry=registry)
    i.info({"version": "1,2,3"})

    data = generate_latest(registry)
    return Response(data, mimetype=CONTENT_TYPE_LATEST)
예제 #13
0
    def __init__(self, client: Client):
        super().__init__(client)

        self._session = Info(namespace=self.METRICS_NAMESPACE,
                             subsystem=self.METRICS_SUBSYSTEM,
                             name='session',
                             documentation='Information about PPPoE Session')

        self._mtu = Gauge(namespace=self.METRICS_NAMESPACE,
                          subsystem=self.METRICS_SUBSYSTEM,
                          name='mtu',
                          documentation='The MTU of the PPPoE')
예제 #14
0
 def prometheus_solid(context):
     i = Info(
         "my_build_version",
         "Description of info",
         registry=context.resources.prometheus.registry,
     )
     info_labels = {"version": "1.2.3", "buildhost": "foo@bar"}
     i.info(info_labels)
     metric = None
     for metric in context.resources.prometheus.registry.collect():
         if metric.name == "my_build_version":
             break
     assert metric and metric.samples[0].labels == info_labels
예제 #15
0
 def prometheus_solid(context):
     i = Info(
         'my_build_version',
         'Description of info',
         registry=context.resources.prometheus.registry,
     )
     info_labels = {'version': '1.2.3', 'buildhost': 'foo@bar'}
     i.info(info_labels)
     metric = None
     for metric in context.resources.prometheus.registry.collect():
         if metric.name == 'my_build_version':
             break
     assert metric and metric.samples[0].labels == info_labels
예제 #16
0
def init_http_server(port):
    hostname = socket.gethostname()
    log.debug(f"Start Prometheus web server: {hostname}:{port} ..")

    start_http_server(port)

    prometheus_info = Info('cinder_exporter',
                           'Openstack Cinder Prometheus exporter')
    prometheus_info.info({
        'version': cinder_exporter.__version__,
        'running_on': hostname
    })

    log.info(f"Prometheus web server started: {hostname}:{port}")
예제 #17
0
 def initialize(self, metrics_prefix: str,
                registry: CollectorRegistry) -> None:
     self.metrics = {
         "host_info":
         Info(f'{metrics_prefix}_host_info',
              'Description of info',
              registry=registry),
         "learning_status":
         Enum(f'{metrics_prefix}_node_discovery',
              'Learning loop status',
              states=['starting', 'running', 'stopped'],
              registry=registry),
         "known_nodes_gauge":
         Gauge(f'{metrics_prefix}_known_nodes',
               'Number of currently known nodes',
               registry=registry),
         "work_orders_gauge":
         Gauge(f'{metrics_prefix}_work_orders',
               'Number of accepted work orders',
               registry=registry),
         "policies_held_gauge":
         Gauge(f'{metrics_prefix}_policies_held',
               'Policies held',
               registry=registry),
         "availability_score_gauge":
         Gauge(f'{metrics_prefix}_availability_score',
               'Availability score',
               registry=registry),
     }
    def __init__( self, hostname, autohost, verbose, configfile ):
        self.host = cycleIterator( [hostname] )
        self.servers = cycleIterator( [hostname] )
        self.loadbalance = autohost
        self.verbose = verbose

        # load the config file
        self.weka_stat_list = self._load_config( configfile )

        # set up commands to get stats defined in config file
        # category: {{ stat:unit}, {stat:unit}}
        for category, stat_dict in self.weka_stat_list.items():
            for stat, unit in stat_dict.items():
                # have to create the category keys, so do it with a try: block
                try:
                    self.wekaIOCommands[category][stat] = "stats --start-time -1m --stat "+stat+" --category "+category+" -R -Z --per-node"
                except KeyError:
                    self.wekaIOCommands[category] = {}
                    self.wekaIOCommands[category][stat] = "stats --start-time -1m --stat "+stat+" --category "+category+" -R -Z --per-node"

        # one gauge to rule them all... all categories and stats are in the labels
        self.gaugelist["weka_stats"] = Gauge( 'weka_stats',
            'WekaFS statistics. For more info refer to: https://docs.weka.io/usage/statistics/list-of-statistics',
            ['cluster','host_name','host_role','node_id','node_role','category','stat','unit'])

        # set up buckets, [4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, inf]
        buckets=[]
        for i in range(12,12+16):
            buckets.append( 2 ** i )

        buckets.append( float("inf") )
        #print( buckets )

        # create histograms for blocksize distribution metrics
        for category, stat_dict in self.weka_stat_list.items():     # creates duplicates?
            for stat, unit in stat_dict.items():
                if unit == "sizes":
                    #print( "category="+category+", stat="+stat )
                    if not category in self.histograms:
                       self.histograms[category] = {}

                       self.histograms[category][stat] = WekaIOHistogram( "weka_blocksize_"+category+"_"+stat, "weka "+category+" "+stat+" blocksizes",
                           labelnames=['cluster','host_name','host_role','node_id','node_role','category','stat','unit'],
                           buckets=buckets )   

        # cluster information
        # create guages, etc here - the stuff we'll collect
        self.gaugelist["wekaInfo"] = Info( 'weka', "Information about the Weka cluster" )

        # general stats
        # note gaugelist key is the name of the gauge
        for name, parms in self.clusterInfo.items():
            self.gaugelist[name] = Gauge( name, parms[0], parms[1] )
        for name, parms in self.clusterStats.items():
            self.gaugelist[name] = Gauge( name, parms[0], parms[1] )
        for name, parms in self.clusterFsStats.items():
            self.gaugelist[name] = Gauge( name, parms[0], parms[1] )

        # gauges to track this program's performance, etc
        self.cmd_exec_gauge = Gauge('weka_prometheus_cmd_execute_seconds', 'Time spent gathering statistics', ["stat"])
예제 #19
0
class LteCollector(BaseCollector):
    METRICS_SUBSYSTEM = 'lte'
    ENDPOINT = 'lteinfo'

    def __init__(self, client: Client):
        super().__init__(client)

        self._device_info = Info(namespace=self.METRICS_NAMESPACE,
                                 subsystem=self.METRICS_SUBSYSTEM,
                                 name='device',
                                 documentation='LTE Device Information')
        self._connection_info = Info(namespace=self.METRICS_NAMESPACE,
                                     subsystem=self.METRICS_SUBSYSTEM,
                                     name='connection',
                                     documentation='LTE Cell Information')

        self._rsrp = Gauge(namespace=self.METRICS_NAMESPACE,
                           subsystem=self.METRICS_SUBSYSTEM,
                           name='rsrp',
                           documentation='LTE RSRP')
        self._rsrq = Gauge(namespace=self.METRICS_NAMESPACE,
                           subsystem=self.METRICS_SUBSYSTEM,
                           name='rsrq',
                           documentation='LTE RSRQ')

    # noinspection SpellCheckingInspection
    def _process_data(self, data):
        self._device_info.info({
            'imei': data['imei'],
            'imsi': data['imsi'],
            'device_status': data['device_status'],
            'card_status': data['card_status'],
            'antenna_mode': data['antenna_mode'],
        })

        self._connection_info.info({
            'phycellid': data['phycellid'],
            'cellid': data['cellid'],
            'tac': data['tac'],
            'service_status': data['service_status'],
            'eps': data['eps']
        })

        self._rsrp.set(data['rsrp'])
        self._rsrq.set(data['rsrq'])
예제 #20
0
def init_prom(port, http_server):
    """ (Str) -> None
    Initialize Prometheus exporter and start the http server exposing
    the metrics.
    Parameters:
      port: The http port for the client
      http_sever: for the moment only twisted
    """
    if http_server == 'twisted':
        # start the exporter http server with twisted
        from prometheus_client import start_http_server
        start_http_server(int(port))
    else:
        print(f'{http_server} is not supoorted. supported: twisted')
        sys.exit(1)
    i = Info('purestorage_exporter',
             'Purestorage Flasharray Prometheus exporter')
    i.info({'version': purestoragefa_exporter.__version__,
            'running_on': socket.gethostname()})
예제 #21
0
    def __init__(self,
                 name: str,
                 config_dict,
                 loglvl=logging.INFO,
                 setup_logs=True,
                 monitoring=True):
        if setup_logs:
            # Setup Logging
            logs_dir = config_dict["GENERAL"].get("LOGS_DIR", fallback="")

            logging.basicConfig(format=LOGGING_FORMAT,
                                level=loglvl,
                                filename=os.path.join(logs_dir,
                                                      f"{name}-bot.log"))

            # Log also to stdout
            stream_log_handler = logging.StreamHandler()
            stream_log_handler.setFormatter(logging.Formatter(LOGGING_FORMAT))
            logging.getLogger().addHandler(stream_log_handler)

        if name not in [
                "signal", "threema", "telegram", "interactive", "twitter",
                "mastodon", "instagram", "messenger", "facebook", "feedback",
                "matrix"
        ]:
            raise ValueError(
                f"Invalid messenger interface was requested: {name}")

        self.name = name
        self.config = config_dict

        monitor_port = self.config.getint(name.upper(),
                                          "PROMETHEUS_PORT",
                                          fallback=0)
        if monitoring and monitor_port > 0:
            try:
                prometheus_client.start_http_server(monitor_port, '0.0.0.0')
            except OSError as e:
                logging.error("Error while starting Prometheus Endpoint",
                              exc_info=e)
            i = Info('platform', 'Bot Platform')
            i.info({'platform': self.name})
예제 #22
0
    def __init__(self, client: Client):
        super().__init__(client)

        self._device_info = Info(namespace=self.METRICS_NAMESPACE,
                                 subsystem=self.METRICS_SUBSYSTEM,
                                 name='device',
                                 documentation='LTE Device Information')
        self._connection_info = Info(namespace=self.METRICS_NAMESPACE,
                                     subsystem=self.METRICS_SUBSYSTEM,
                                     name='connection',
                                     documentation='LTE Cell Information')

        self._rsrp = Gauge(namespace=self.METRICS_NAMESPACE,
                           subsystem=self.METRICS_SUBSYSTEM,
                           name='rsrp',
                           documentation='LTE RSRP')
        self._rsrq = Gauge(namespace=self.METRICS_NAMESPACE,
                           subsystem=self.METRICS_SUBSYSTEM,
                           name='rsrq',
                           documentation='LTE RSRQ')
예제 #23
0
def set_static_info(api):
    model = str(api.information.model)
    amount_of_ram = str(api.information.ram)
    serial_number = str(api.information.serial)
    dsm_version = str(api.information.version_string)

    Info(metric("model_metadata"), "Model metadata").info({
        "model": model,
        "amount_of_ram": amount_of_ram,
        "serial_number": serial_number,
        "dsm_version": dsm_version
    })
예제 #24
0
 def register_info(self, metric_name, description, data):
     """
     Registers an Info type of metric, e.g. the current version
     :param str metric_name: the metric name
     :param str description: details about what it measures
     :param T data: what to display
     :return:
     """
     if metric_name in self.registry:
         raise ValueError(f'Duplicate name: {metric_name}')
     self.registry[metric_name] = Info(metric_name, description)
     self.registry[metric_name].info(data)
예제 #25
0
    def create_metric(self):
        # record app conf
        self.conf_info = Info('celery_conf_info', 'APP_CONF')
        self.conf_info_c = CollectorRegistry()

        # monitor worker info
        self.workers_info = Info('celery_workers_info', 'WORKER_INFO')
        self.workers_info_c = CollectorRegistry()

        # monitor worker info real-time
        self.workers_state = Gauge('celery_workers_state', 'WORKER_STATE',
                                   ['worker'])
        self.workers_state_c = CollectorRegistry()
        self.workers_processed = Gauge('celery_processed_tasks_total',
                                       'WORKER_TASKS_PROCESSED', ['worker'])
        self.workers_processed_c = CollectorRegistry()
        self.workers_active = Gauge('celery_active_tasks_total',
                                    'WORKER_TASKS_ACTIVE', ['worker'])
        self.workers_active_c = CollectorRegistry()

        # monitor tasks info
        self.tasks_counter = Counter('celery_tasks_total', 'TASK_COUNT_INFO',
                                     ['worker', 'task', 'result'])
        self.tasks_counter_c = CollectorRegistry()
        self.tasks_runtime = Summary('celery_tasks_seconds', 'TASK_RUNTIME',
                                     ['worker', 'task'])
        self.tasks_runtime_c = CollectorRegistry()
        self.tasks_info = Info('celery_tasks_info', 'TASK_INFO')
        self.tasks_info_c = CollectorRegistry()
def put_nvme_info(nvme_list_json):

    nvme_info = Info('nvme_info', 'Description of NVMe Info', ['device'])

    for nvme in nvme_list_json['Devices']:
        nvme_info.labels(nvme['DevicePath']).info(
            {'ProduceName': nvme['ProductName']})
        nvme_info.labels(nvme['DevicePath']).info(
            {'ModelNumber': nvme['ModelNumber']})
예제 #27
0
def update_base_metrics(increment: bool = False) -> dict:
    """ Update this exporter's own Prometheus metrics

    Args:
        increment: Increment the count of total Ansible Galaxy API calls by one

    Returns:
        Dict containing base metrics
    """
    if 'version' not in METRICS:
        METRICS['version'] = Info('ansible_galaxy_exporter_version',
                                  'Current exporter version')
        METRICS['version'].info({'version': __version__})
    if 'api_call_count' not in METRICS:
        METRICS['api_call_count'] = Counter('ansible_galaxy_exporter_api_call_count',
                                            'API calls to Ansible Galaxy')
    if increment:
        METRICS['api_call_count'].inc()
    return METRICS
예제 #28
0
    def _setup_metrics(self):
        self._metrics['state'] = Enum(
            self.DROP_IN_ID + '_drop_in_status',
            'Current status of the drop-in', ['drop_in_name'],
            states=['starting', 'ready', 'measuring'])
        self._metrics['state'].labels('soil').state('starting')

        self._metrics['periodic_passes'] = Counter(
            self.DROP_IN_ID + '_measurements_count',
            'Number of times periodic measurements were performed',
            ['drop_in_name'])

        self._metrics['temperature'] = Gauge(self.DROP_IN_ID + '_temperature',
                                             'Temperature (Celsius degrees)',
                                             ['drop_in_name'])
        self._metrics['capacitance'] = Gauge(
            self.DROP_IN_ID + '_capacitance',
            # see https://github.com/Miceuz/i2c-moisture-sensor/issues/27#issuecomment-434716035
            'Capacitance value (arbitrary unit)',
            ['drop_in_name'])
        self._metrics['moisture'] = Gauge(self.DROP_IN_ID + '_moisture',
                                          'Moisture (%)', ['drop_in_name'])
        self._metrics['brightness'] = Gauge(
            self.DROP_IN_ID + '_brightness',
            # see https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/ - #Rugged Version
            'Brightness (arbitrary unit)',
            ['drop_in_name'])

        self._metrics['soil'] = Info(self.DROP_IN_ID + '_drop_in',
                                     'Information regarding this drop_in',
                                     ['drop_in_name'])
        self._metrics['soil'].labels('soil').info({
            'version':
            self.DROP_IN_VERSION,
            'id':
            self.DROP_IN_ID,
            'rule':
            self.FLASK_ROUTING_RULE,
            'capabilities':
            'temperature, capacitance, brightness, moisture'
        })
예제 #29
0
 def init_prometheus(self):
     self.slugify = Slugify(to_lower=True)
     self.slugify.separator = "_"
     self.slugify.pretranslate = {"+": "plus", "-": "minus"}
     for n, r in enumerate(registers):
         s = self.slugify(f"empro_{r['short_name']}")
         registers[n]["slug"] = s
         if s in self.metrics:
             print(s, r)
         if r["datatype"] in [
                 "uint8",
                 "uint16",
                 "sint16",
                 "uint32",
                 "sint32",
                 "fl32",
         ]:
             self.metrics[s] = Gauge(s, r["description"],
                                     ["unit", "register"])
         else:
             self.metrics[s] = Info(s, r["description"], ["register"])
예제 #30
0
 def _setup_generic_metrics(self, metric_prefix: str) -> dict:
     return dict(
         created=Gauge(f'{metric_prefix}created',
                       'Created datetime in epoch format',
                       self.labels.keys(), registry=self.registry),
         community_score=Gauge(f'{metric_prefix}community_score',
                               'Community score',
                               self.labels.keys(), registry=self.registry),
         community_survey=Gauge(f'{metric_prefix}community_surveys',
                                'Community surveys',
                                self.labels.keys(), registry=self.registry),
         download=Gauge(f'{metric_prefix}downloads', 'Download count',
                        self.labels.keys(), registry=self.registry),
         modified=Gauge(f'{metric_prefix}modified',
                        'Modified datetime in epoch format',
                        self.labels.keys(), registry=self.registry),
         quality_score=Gauge(f'{metric_prefix}quality_score', 'Quality score',
                             self.labels.keys(), registry=self.registry),
         version=Info(f'{metric_prefix}version', 'Current release version',
                      self.labels.keys(), registry=self.registry),
         versions=Gauge(f'{metric_prefix}versions', 'Version count',
                        self.labels.keys(), registry=self.registry),
     )