def metric_listeners_histogram(self, meetings): logging.debug("Calculating room listeners histogram") histogram = HistogramBucketHelper(self.room_listeners_buckets) for meeting in meetings: histogram.add(int(meeting['listenerCount'])) metric = GaugeHistogramMetricFamily('bbb_room_listeners', "BigBlueButton room listeners histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric
class BigBlueButtonCollector: api_latency_buckets = [ .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 5.0, 7.5, 10.0, INF ] histogram_data_meetings_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_processing_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_processed_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_published_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_unpublished_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_deleted_latency = HistogramBucketHelper( api_latency_buckets) room_participants_buckets = [ 0, 1, 5, 15, 30, 60, 90, 120, 150, 200, 250, 300, 400, 500, INF ] room_listeners_buckets = room_participants_buckets.copy() room_voice_participants_buckets = [0, 1, 5, 15, 30, 60, 90, 120, INF] room_video_participants_buckets = room_voice_participants_buckets.copy() def set_room_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_participants_buckets = buckets + [INF] def set_room_listeners_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_listeners_buckets = buckets + [INF] def set_room_voice_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_voice_participants_buckets = buckets + [INF] def set_room_video_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_video_participants_buckets = buckets + [INF] def collect(self): logging.info("Collecting metrics from BigBlueButton API") logging.debug("Requesting via API meetings data") meetings, meetings_data_latency = execution_duration( api.get_meetings)() bbb_api_latency = HistogramMetricFamily( 'bbb_api_latency', "BigBlueButton API call latency", labels=['endpoint', 'parameters']) self.histogram_data_meetings_latency.add(meetings_data_latency) bbb_api_latency.add_metric( ["getMeetings", ""], self.histogram_data_meetings_latency.get_buckets(), self.histogram_data_meetings_latency.sum) yield self.metric_meetings(meetings) yield self.metric_participants(meetings) yield self.metric_meetings_listeners(meetings) yield self.metric_meetings_voice_participants(meetings) yield self.metric_meetings_video_participants(meetings) yield self.metric_meetings_participant_clients(meetings) if settings.RECORDINGS_METRICS_ENABLE: yield self.metric_recordings_processing(bbb_api_latency) yield self.metric_recordings_processed_data(bbb_api_latency) yield self.metric_recordings_published(bbb_api_latency) yield self.metric_recordings_unpublished(bbb_api_latency) yield self.metric_recordings_deleted(bbb_api_latency) yield bbb_api_latency bbb_api_up = GaugeMetricFamily( 'bbb_api_up', "1 if BigBlueButton API is responding 0 otherwise") bbb_api_up.add_metric([], 1 if settings._api_up else 0) yield bbb_api_up yield self.metric_participants_histogram(meetings) yield self.metric_listeners_histogram(meetings) yield self.metric_voice_participants_histogram(meetings) yield self.metric_video_participants_histogram(meetings) bbb_exporter = GaugeMetricFamily("bbb_exporter", "BigBlueButton Exporter version", labels=["version"]) bbb_exporter.add_metric([settings.VERSION], 1) yield bbb_exporter logging.info("Finished collecting metrics from BigBlueButton API") def metric_meetings(self, meetings): no_meetings = len(meetings) metric = GaugeMetricFamily('bbb_meetings', "Number of BigBlueButton meetings") metric.add_metric([], no_meetings) return metric def metric_participants(self, meetings): no_participants = reduce( lambda total, meeting: total + int(meeting['participantCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_participants', "Total number of participants in all BigBlueButton meetings") metric.add_metric([], no_participants) return metric def metric_meetings_listeners(self, meetings): no_listeners = reduce( lambda total, meeting: total + int(meeting['listenerCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_listeners', "Total number of listeners in all BigBlueButton meetings") metric.add_metric([], no_listeners) return metric def metric_meetings_voice_participants(self, meetings): no_voice_participants = reduce( lambda total, meeting: total + int(meeting['voiceParticipantCount'] ), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_voice_participants', "Total number of voice participants in all BigBlueButton meetings") metric.add_metric([], no_voice_participants) return metric def metric_meetings_video_participants(self, meetings): no_video_participants = reduce( lambda total, meeting: total + int(meeting['videoCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_video_participants', "Total number of video participants in all BigBlueButton meetings") metric.add_metric([], no_video_participants) return metric def metric_meetings_participant_clients(self, meetings): participants_by_client = self._get_participant_count_by_client( meetings) metric = GaugeMetricFamily( 'bbb_meetings_participant_clients', "Total number of participants in all BigBlueButton meetings by client", labels=["type"]) for client, num in participants_by_client.items(): metric.add_metric([client.lower()], num) return metric def metric_recordings_processing(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings processing data") histogram = GaugeMetricFamily( 'bbb_recordings_processing', "Total number of BigBlueButton recordings processing") recording_processing_data, recording_processing_latency = execution_duration( api.get_recordings)("processing") histogram.add_metric([], len(recording_processing_data)) self.histogram_data_recording_processing_latency.add( recording_processing_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=processing"], self.histogram_data_recording_processing_latency.get_buckets(), self.histogram_data_recording_processing_latency.sum) return histogram def metric_recordings_processed_data(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings processed data") histogram = GaugeMetricFamily( 'bbb_recordings_processed', "Total number of BigBlueButton recordings processed") recording_processed_data, recording_processed_latency = execution_duration( api.get_recordings)("processed") histogram.add_metric([], len(recording_processed_data)) self.histogram_data_recording_processed_latency.add( recording_processed_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=processed"], self.histogram_data_recording_processed_latency.get_buckets(), self.histogram_data_recording_processed_latency.sum) return histogram def metric_recordings_published(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings published data") metric = GaugeMetricFamily( 'bbb_recordings_published', "Total number of BigBlueButton recordings published") recording_published_data, recording_published_latency = execution_duration( api.get_recordings)("published") metric.add_metric([], len(recording_published_data)) self.histogram_data_recording_published_latency.add( recording_published_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=published"], self.histogram_data_recording_published_latency.get_buckets(), self.histogram_data_recording_published_latency.sum) return metric def metric_recordings_unpublished(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings unpublished data") metric = GaugeMetricFamily( 'bbb_recordings_unpublished', "Total number of BigBlueButton recordings unpublished") recording_unpublished_data, recording_unpublished_latency = execution_duration( api.get_recordings)("unpublished") metric.add_metric([], len(recording_unpublished_data)) self.histogram_data_recording_unpublished_latency.add( recording_unpublished_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=unpublished"], self.histogram_data_recording_unpublished_latency.get_buckets(), self.histogram_data_recording_unpublished_latency.sum) return metric def metric_recordings_deleted(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings deleted data") metric = GaugeMetricFamily( 'bbb_recordings_deleted', "Total number of BigBlueButton recordings deleted") recording_deleted_data, recording_deleted_latency = execution_duration( api.get_recordings)("deleted") metric.add_metric([], len(recording_deleted_data)) self.histogram_data_recording_deleted_latency.add( recording_deleted_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=deleted"], self.histogram_data_recording_deleted_latency.get_buckets(), self.histogram_data_recording_deleted_latency.sum) return metric def metric_participants_histogram(self, meetings): logging.debug("Calculating room participants histogram") histogram = HistogramBucketHelper(self.room_participants_buckets) for meeting in meetings: histogram.add(int(meeting['participantCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_participants', "BigBlueButton room participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_listeners_histogram(self, meetings): logging.debug("Calculating room listeners histogram") histogram = HistogramBucketHelper(self.room_listeners_buckets) for meeting in meetings: histogram.add(int(meeting['listenerCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_listeners', "BigBlueButton room listeners histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_voice_participants_histogram(self, meetings): logging.debug("Calculating room voice participants histogram") histogram = HistogramBucketHelper(self.room_voice_participants_buckets) for meeting in meetings: histogram.add(int(meeting['voiceParticipantCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_voice_participants', "BigBlueButton room voice participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_video_participants_histogram(self, meetings): logging.debug("Calculating room video participants histogram") histogram = HistogramBucketHelper(self.room_video_participants_buckets) for meeting in meetings: histogram.add(int(meeting['videoCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_video_participants', "BigBlueButton room video participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric @staticmethod def _get_participant_count_by_client(meetings): p_by_c = defaultdict(int, {'HTML5': 0, 'DIAL-IN': 0, 'FLASH': 0}) for meeting in meetings: if not meeting.get("attendees"): continue if isinstance(meeting['attendees']['attendee'], list): attendees = meeting['attendees']['attendee'] else: attendees = [meeting['attendees']['attendee']] for attendee in attendees: p_by_c[attendee['clientType']] += 1 return p_by_c
class BigBlueButtonCollector: buckets = [ .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 5.0, 7.5, 10.0, INF ] histogram_data_meetings_latency = HistogramBucketHelper(buckets) histogram_data_recording_processing_latency = HistogramBucketHelper( buckets) histogram_data_recording_processed_latency = HistogramBucketHelper(buckets) histogram_data_recording_published_latency = HistogramBucketHelper(buckets) histogram_data_recording_unpublished_latency = HistogramBucketHelper( buckets) histogram_data_recording_deleted_latency = HistogramBucketHelper(buckets) def __init__(self): pass def collect(self): logging.info("Collecting metrics from BigBlueButton API") logging.debug("Requesting via API meetings data") meetings, meetings_data_latency = execution_duration( api.get_meetings)() no_meetings = len(meetings) no_participants = reduce( lambda total, meeting: total + int(meeting['participantCount']), meetings, 0) no_listeners = reduce( lambda total, meeting: total + int(meeting['listenerCount']), meetings, 0) no_voice_participants = reduce( lambda total, meeting: total + int(meeting['voiceParticipantCount'] ), meetings, 0) no_video_participants = reduce( lambda total, meeting: total + int(meeting['videoCount']), meetings, 0) participants_by_client = self._get_participant_count_by_client( meetings) bbb_api_latency = HistogramMetricFamily( 'bbb_api_latency', "BigBlueButton API call latency", labels=['endpoint', 'parameters']) self.histogram_data_meetings_latency.add(meetings_data_latency) bbb_api_latency.add_metric( ["getMeetings", ""], self.histogram_data_meetings_latency.get_buckets(), self.histogram_data_meetings_latency.sum) bbb_meetings = GaugeMetricFamily('bbb_meetings', "Number of BigBlueButton meetings") bbb_meetings.add_metric([], no_meetings) yield bbb_meetings bbb_meetings_participants = GaugeMetricFamily( 'bbb_meetings_participants', "Total number of participants in all BigBlueButton meetings") bbb_meetings_participants.add_metric([], no_participants) yield bbb_meetings_participants bbb_meetings_listeners = GaugeMetricFamily( 'bbb_meetings_listeners', "Total number of listeners in all BigBlueButton meetings") bbb_meetings_listeners.add_metric([], no_listeners) yield bbb_meetings_listeners bbb_meetings_voice_participants = GaugeMetricFamily( 'bbb_meetings_voice_participants', "Total number of voice participants in all BigBlueButton " "meetings") bbb_meetings_voice_participants.add_metric([], no_voice_participants) yield bbb_meetings_voice_participants bbb_meetings_video_participants = GaugeMetricFamily( 'bbb_meetings_video_participants', "Total number of video participants in all BigBlueButton " "meetings") bbb_meetings_video_participants.add_metric([], no_video_participants) yield bbb_meetings_video_participants bbb_meetings_participant_clients = GaugeMetricFamily( 'bbb_meetings_participant_clients', "Total number of participants in all BigBlueButton " "meetings by client", labels=["type"]) for client, num in participants_by_client.items(): bbb_meetings_participant_clients.add_metric([client.lower()], num) yield bbb_meetings_participant_clients logging.debug("Requesting via API recordings processing data") bbb_recordings_processing = GaugeMetricFamily( 'bbb_recordings_processing', "Total number of BigBlueButton recordings processing") recording_processing_data, recording_processing_latency = execution_duration( api.get_recordings)("processing") bbb_recordings_processing.add_metric([], len(recording_processing_data)) self.histogram_data_recording_processing_latency.add( recording_processing_latency) bbb_api_latency.add_metric( ["getRecordings", "state=processing"], self.histogram_data_recording_processing_latency.get_buckets(), self.histogram_data_recording_processing_latency.sum) yield bbb_recordings_processing logging.debug("Requesting via API recordings processed data") recordings_processed_data = GaugeMetricFamily( 'bbb_recordings_processed', "Total number of BigBlueButton recordings processed") recording_processed_data, recording_processed_latency = execution_duration( api.get_recordings)("processed") recordings_processed_data.add_metric([], len(recording_processed_data)) self.histogram_data_recording_processed_latency.add( recording_processed_latency) bbb_api_latency.add_metric( ["getRecordings", "state=processed"], self.histogram_data_recording_processed_latency.get_buckets(), self.histogram_data_recording_processed_latency.sum) yield recordings_processed_data logging.debug("Requesting via API recordings published data") recordings_published = GaugeMetricFamily( 'bbb_recordings_published', "Total number of BigBlueButton recordings published") recording_published_data, recording_published_latency = execution_duration( api.get_recordings)("published") recordings_published.add_metric([], len(recording_published_data)) self.histogram_data_recording_published_latency.add( recording_published_latency) bbb_api_latency.add_metric( ["getRecordings", "state=published"], self.histogram_data_recording_published_latency.get_buckets(), self.histogram_data_recording_published_latency.sum) yield recordings_published logging.debug("Requesting via API recordings unpublished data") recordings_unpublished = GaugeMetricFamily( 'bbb_recordings_unpublished', "Total number of BigBlueButton recordings unpublished") recording_unpublished_data, recording_unpublished_latency = execution_duration( api.get_recordings)("unpublished") recordings_unpublished.add_metric([], len(recording_unpublished_data)) self.histogram_data_recording_unpublished_latency.add( recording_unpublished_latency) bbb_api_latency.add_metric( ["getRecordings", "state=unpublished"], self.histogram_data_recording_unpublished_latency.get_buckets(), self.histogram_data_recording_unpublished_latency.sum) yield recordings_unpublished logging.debug("Requesting via API recordings deleted data") recordings_deleted = GaugeMetricFamily( 'bbb_recordings_deleted', "Total number of BigBlueButton recordings deleted") recording_deleted_data, recording_deleted_latency = execution_duration( api.get_recordings)("deleted") recordings_deleted.add_metric([], len(recording_deleted_data)) self.histogram_data_recording_deleted_latency.add( recording_deleted_latency) bbb_api_latency.add_metric( ["getRecordings", "state=deleted"], self.histogram_data_recording_deleted_latency.get_buckets(), self.histogram_data_recording_deleted_latency.sum) yield recordings_deleted bbb_api_up = GaugeMetricFamily( 'bbb_api_up', "1 if BigBlueButton API is responding 0 otherwise") bbb_api_up.add_metric([], 1 if settings._api_up else 0) yield bbb_api_up yield bbb_api_latency logging.info("Finished collecting metrics from BigBlueButton API") @staticmethod def _get_participant_count_by_client(meetings): p_by_c = defaultdict(int, {'HTML5': 0, 'DIAL-IN': 0, 'FLASH': 0}) for meeting in meetings: if not meeting.get("attendees"): continue if isinstance(meeting['attendees']['attendee'], list): attendees = meeting['attendees']['attendee'] else: attendees = [meeting['attendees']['attendee']] for attendee in attendees: p_by_c[attendee['clientType']] += 1 return p_by_c
class BigBlueButtonCollector: buckets = [.01, .025, .05, .075, .1, .25, .5, .75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 5.0, 7.5, 10.0, INF] histogram_data_meetings_latency = HistogramBucketHelper(buckets) histogram_data_recording_processing_latency = HistogramBucketHelper(buckets) histogram_data_recording_processed_latency = HistogramBucketHelper(buckets) histogram_data_recording_published_latency = HistogramBucketHelper(buckets) histogram_data_recording_unpublished_latency = HistogramBucketHelper(buckets) histogram_data_recording_deleted_latency = HistogramBucketHelper(buckets) def __init__(self): pass def collect(self): logging.info("Collecting metrics from BigBlueButton API") logging.debug("Requesting via API meetings data") meetings, meetings_data_latency = execution_duration(api.get_meetings)() no_meetings = len(meetings) no_participants = reduce(lambda total, meeting: total + int(meeting['participantCount']), meetings, 0) no_listeners = reduce(lambda total, meeting: total + int(meeting['listenerCount']), meetings, 0) no_voice_participants = reduce(lambda total, meeting: total + int(meeting['voiceParticipantCount']), meetings, 0) no_video_participants = reduce(lambda total, meeting: total + int(meeting['videoCount']), meetings, 0) bbb_api_latency = HistogramMetricFamily('bbb_api_latency', "BigBlueButton API call latency", labels=['endpoint', 'parameters']) self.histogram_data_meetings_latency.add(meetings_data_latency) bbb_api_latency.add_metric(["getMeetings", ""], self.histogram_data_meetings_latency.get_buckets(), self.histogram_data_meetings_latency.sum) bbb_meetings = GaugeMetricFamily('bbb_meetings', "Number of BigBlueButton meetings") bbb_meetings.add_metric([], no_meetings) yield bbb_meetings bbb_meetings_participants = GaugeMetricFamily('bbb_meetings_participants', "Total number of participants in all BigBlueButton meetings") bbb_meetings_participants.add_metric([], no_participants) yield bbb_meetings_participants bbb_meetings_listeners = GaugeMetricFamily('bbb_meetings_listeners', "Total number of listeners in all BigBlueButton meetings") bbb_meetings_listeners.add_metric([], no_listeners) yield bbb_meetings_listeners bbb_meetings_voice_participants = GaugeMetricFamily('bbb_meetings_voice_participants', "Total number of voice participants in all BigBlueButton " "meetings") bbb_meetings_voice_participants.add_metric([], no_voice_participants) yield bbb_meetings_voice_participants bbb_meetings_video_participants = GaugeMetricFamily('bbb_meetings_video_participants', "Total number of video participants in all BigBlueButton " "meetings") bbb_meetings_video_participants.add_metric([], no_video_participants) yield bbb_meetings_video_participants logging.debug("Requesting via API recordings processing data") bbb_recordings_processing = GaugeMetricFamily('bbb_recordings_processing', "Total number of BigBlueButton recordings processing") recording_processing_data, recording_processing_latency = execution_duration(api.get_recordings)("processing") bbb_recordings_processing.add_metric([], len(recording_processing_data)) self.histogram_data_recording_processing_latency.add(recording_processing_latency) bbb_api_latency.add_metric(["getRecordings", "state=processing"], self.histogram_data_recording_processing_latency.get_buckets(), self.histogram_data_recording_processing_latency.sum) yield bbb_recordings_processing logging.debug("Requesting via API recordings processed data") recordings_processed_data = GaugeMetricFamily('bbb_recordings_processed', "Total number of BigBlueButton recordings processed") recording_processed_data, recording_processed_latency = execution_duration(api.get_recordings)("processed") recordings_processed_data.add_metric([], len(recording_processed_data)) self.histogram_data_recording_processed_latency.add(recording_processed_latency) bbb_api_latency.add_metric(["getRecordings", "state=processed"], self.histogram_data_recording_processed_latency.get_buckets(), self.histogram_data_recording_processed_latency.sum) yield recordings_processed_data logging.debug("Requesting via API recordings published data") recordings_published = GaugeMetricFamily('bbb_recordings_published', "Total number of BigBlueButton recordings published") recording_published_data, recording_published_latency = execution_duration(api.get_recordings)("published") recordings_published.add_metric([], len(recording_published_data)) self.histogram_data_recording_published_latency.add(recording_published_latency) bbb_api_latency.add_metric(["getRecordings", "state=published"], self.histogram_data_recording_published_latency.get_buckets(), self.histogram_data_recording_published_latency.sum) yield recordings_published logging.debug("Requesting via API recordings unpublished data") recordings_unpublished = GaugeMetricFamily('bbb_recordings_unpublished', "Total number of BigBlueButton recordings unpublished") recording_unpublished_data, recording_unpublished_latency = execution_duration(api.get_recordings)("unpublished") recordings_unpublished.add_metric([], len(recording_unpublished_data)) self.histogram_data_recording_unpublished_latency.add(recording_unpublished_latency) bbb_api_latency.add_metric(["getRecordings", "state=unpublished"], self.histogram_data_recording_unpublished_latency.get_buckets(), self.histogram_data_recording_unpublished_latency.sum) yield recordings_unpublished logging.debug("Requesting via API recordings deleted data") recordings_deleted = GaugeMetricFamily('bbb_recordings_deleted', "Total number of BigBlueButton recordings deleted") recording_deleted_data, recording_deleted_latency = execution_duration(api.get_recordings)("deleted") recordings_deleted.add_metric([], len(recording_deleted_data)) self.histogram_data_recording_deleted_latency.add(recording_deleted_latency) bbb_api_latency.add_metric(["getRecordings", "state=deleted"], self.histogram_data_recording_deleted_latency.get_buckets(), self.histogram_data_recording_deleted_latency.sum) yield recordings_deleted bbb_api_up = GaugeMetricFamily('bbb_api_up', "1 if BigBlueButton API is responding 0 otherwise") bbb_api_up.add_metric([], 1 if settings._api_up else 0) yield bbb_api_up yield bbb_api_latency logging.info("Finished collecting metrics from BigBlueButton API")
class BigBlueButtonCollector: api_latency_buckets = [ .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 5.0, 7.5, 10.0, INF ] histogram_data_meetings_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_processing_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_processed_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_published_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_unpublished_latency = HistogramBucketHelper( api_latency_buckets) histogram_data_recording_deleted_latency = HistogramBucketHelper( api_latency_buckets) room_participants_buckets = [ 0, 1, 5, 15, 30, 60, 90, 120, 150, 200, 250, 300, 400, 500, INF ] room_listeners_buckets = room_participants_buckets.copy() room_voice_participants_buckets = [0, 1, 5, 15, 30, 60, 90, 120, INF] room_video_participants_buckets = room_voice_participants_buckets.copy() recordings_metrics_base_dir = settings.recordings_metrics_base_dir recordings_metrics_from_disk = settings.RECORDINGS_METRICS_READ_FROM_DISK def set_room_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_participants_buckets = buckets + [INF] def set_room_listeners_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_listeners_buckets = buckets + [INF] def set_room_voice_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_voice_participants_buckets = buckets + [INF] def set_room_video_participants_buckets(self, buckets): assert type(buckets) == list assert len(buckets) != 0 self.room_video_participants_buckets = buckets + [INF] def collect(self): logging.info("Collecting metrics from BigBlueButton API") logging.debug("Requesting via API meetings data") meetings, meetings_data_latency = execution_duration( api.get_meetings)() bbb_api_latency = HistogramMetricFamily( 'bbb_api_latency', "BigBlueButton API call latency", labels=['endpoint', 'parameters']) self.histogram_data_meetings_latency.add(meetings_data_latency) bbb_api_latency.add_metric( ["getMeetings", ""], self.histogram_data_meetings_latency.get_buckets(), self.histogram_data_meetings_latency.sum) yield self.metric_meetings(meetings) yield self.metric_participants(meetings) yield self.metric_meetings_listeners(meetings) yield self.metric_meetings_voice_participants(meetings) yield self.metric_meetings_video_participants(meetings) yield self.metric_meetings_participant_clients(meetings) yield self.metric_meetings_participants_origin(meetings) if settings.RECORDINGS_METRICS_ENABLE: yield self.metric_recordings_unpublished(bbb_api_latency) if self.recordings_metrics_from_disk: yield self.metric_recordings_processing_from_disk() yield self.metric_recordings_published_from_disk() # There is a slight race condition here since in order to calculate deleted recordings we need # the number of published recordings yield self.metric_recordings_deleted_from_disk() # This is an additional metric that is only available if recordings_metrics_from_disk is enabled # since this data isn't available via the API yield self.metric_recordings_unprocessed_from_disk() else: # Perform expensive API calls - this will increase the latency of the scrape yield self.metric_recordings_processing(bbb_api_latency) yield self.metric_recordings_published(bbb_api_latency) yield self.metric_recordings_deleted(bbb_api_latency) yield bbb_api_latency bbb_api_up = GaugeMetricFamily( 'bbb_api_up', "1 if BigBlueButton API is responding 0 otherwise") bbb_api_up.add_metric([], 1 if settings._api_up else 0) yield bbb_api_up yield self.metric_participants_histogram(meetings) yield self.metric_listeners_histogram(meetings) yield self.metric_voice_participants_histogram(meetings) yield self.metric_video_participants_histogram(meetings) bbb_exporter = GaugeMetricFamily("bbb_exporter", "BigBlueButton Exporter version", labels=["version"]) bbb_exporter.add_metric([settings.VERSION], 1) yield bbb_exporter logging.info("Finished collecting metrics from BigBlueButton API") def metric_meetings(self, meetings): no_meetings = len(meetings) metric = GaugeMetricFamily('bbb_meetings', "Number of BigBlueButton meetings") metric.add_metric([], no_meetings) return metric def metric_participants(self, meetings): no_participants = reduce( lambda total, meeting: total + int(meeting['participantCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_participants', "Total number of participants in all BigBlueButton meetings") metric.add_metric([], no_participants) return metric def metric_meetings_listeners(self, meetings): no_listeners = reduce( lambda total, meeting: total + int(meeting['listenerCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_listeners', "Total number of listeners in all BigBlueButton meetings") metric.add_metric([], no_listeners) return metric def metric_meetings_participants_origin(self, meetings): participants_by_origin = self._get_participants_count_by_origin( meetings) metric = GaugeMetricFamily( 'bbb_meetings_participants_origin', "Total number of participants in all BigBlueButton meetings by origin servername", labels=["server", "name"]) for (servername, origin), num in participants_by_origin.items(): metric.add_metric([servername.lower(), origin.lower()], num) return metric def metric_meetings_voice_participants(self, meetings): no_voice_participants = reduce( lambda total, meeting: total + int(meeting['voiceParticipantCount'] ), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_voice_participants', "Total number of voice participants in all BigBlueButton meetings") metric.add_metric([], no_voice_participants) return metric def metric_meetings_video_participants(self, meetings): no_video_participants = reduce( lambda total, meeting: total + int(meeting['videoCount']), meetings, 0) metric = GaugeMetricFamily( 'bbb_meetings_video_participants', "Total number of video participants in all BigBlueButton meetings") metric.add_metric([], no_video_participants) return metric def metric_meetings_participant_clients(self, meetings): participants_by_client = self._get_participant_count_by_client( meetings) metric = GaugeMetricFamily( 'bbb_meetings_participant_clients', "Total number of participants in all BigBlueButton meetings by client", labels=["type"]) for client, num in participants_by_client.items(): metric.add_metric([client.lower()], num) return metric def metric_recordings_processing(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings processing data") histogram = GaugeMetricFamily( 'bbb_recordings_processing', "Total number of BigBlueButton recordings processing") recording_processing_data, recording_processing_latency = execution_duration( api.get_recordings)("processing") histogram.add_metric([], len(recording_processing_data)) self.histogram_data_recording_processing_latency.add( recording_processing_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=processing"], self.histogram_data_recording_processing_latency.get_buckets(), self.histogram_data_recording_processing_latency.sum) return histogram def metric_recordings_published(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings published data") metric = GaugeMetricFamily( 'bbb_recordings_published', "Total number of BigBlueButton recordings published") recording_published_data, recording_published_latency = execution_duration( api.get_recordings)("published") metric.add_metric([], len(recording_published_data)) self.histogram_data_recording_published_latency.add( recording_published_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=published"], self.histogram_data_recording_published_latency.get_buckets(), self.histogram_data_recording_published_latency.sum) return metric def metric_recordings_unpublished(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings unpublished data") metric = GaugeMetricFamily( 'bbb_recordings_unpublished', "Total number of BigBlueButton recordings unpublished") recording_unpublished_data, recording_unpublished_latency = execution_duration( api.get_recordings)("unpublished") metric.add_metric([], len(recording_unpublished_data)) self.histogram_data_recording_unpublished_latency.add( recording_unpublished_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=unpublished"], self.histogram_data_recording_unpublished_latency.get_buckets(), self.histogram_data_recording_unpublished_latency.sum) return metric def metric_recordings_deleted(self, bbb_api_latency_metric): logging.debug("Requesting via API recordings deleted data") metric = GaugeMetricFamily( 'bbb_recordings_deleted', "Total number of BigBlueButton recordings deleted") recording_deleted_data, recording_deleted_latency = execution_duration( api.get_recordings)("deleted") metric.add_metric([], len(recording_deleted_data)) self.histogram_data_recording_deleted_latency.add( recording_deleted_latency) bbb_api_latency_metric.add_metric( ["getRecordings", "state=deleted"], self.histogram_data_recording_deleted_latency.get_buckets(), self.histogram_data_recording_deleted_latency.sum) return metric def metric_participants_histogram(self, meetings): logging.debug("Calculating room participants histogram") histogram = HistogramBucketHelper(self.room_participants_buckets) for meeting in meetings: histogram.add(int(meeting['participantCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_participants', "BigBlueButton room participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_listeners_histogram(self, meetings): logging.debug("Calculating room listeners histogram") histogram = HistogramBucketHelper(self.room_listeners_buckets) for meeting in meetings: histogram.add(int(meeting['listenerCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_listeners', "BigBlueButton room listeners histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_voice_participants_histogram(self, meetings): logging.debug("Calculating room voice participants histogram") histogram = HistogramBucketHelper(self.room_voice_participants_buckets) for meeting in meetings: histogram.add(int(meeting['voiceParticipantCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_voice_participants', "BigBlueButton room voice participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_video_participants_histogram(self, meetings): logging.debug("Calculating room video participants histogram") histogram = HistogramBucketHelper(self.room_video_participants_buckets) for meeting in meetings: histogram.add(int(meeting['videoCount'])) metric = GaugeHistogramMetricFamily( 'bbb_room_video_participants', "BigBlueButton room video participants histogram gauge") metric.add_metric([], histogram.get_buckets(), histogram.sum) return metric def metric_recordings_processing_from_disk(self): logging.debug("Querying disk for recordings processing data") metric = GaugeMetricFamily( 'bbb_recordings_processing', "Total number of BigBlueButton recordings processing " "(scraped from disk)") metric.add_metric([], recordings_processing_from_disk( self.recordings_metrics_base_dir)) return metric def metric_recordings_published_from_disk(self): logging.debug("Querying disk for recordings published data") metric = GaugeMetricFamily( 'bbb_recordings_published', "Total number of BigBlueButton recordings published " "(scraped from disk)") metric.add_metric([], recordings_published_from_disk( self.recordings_metrics_base_dir)) return metric def metric_recordings_deleted_from_disk(self): logging.debug("Querying disk for recordings deleted data") metric = GaugeMetricFamily( 'bbb_recordings_deleted', "Total number of BigBlueButton recordings deleted " "(scraped from disk)") metric.add_metric([], recordings_deleted_from_disk( self.recordings_metrics_base_dir)) return metric def metric_recordings_unprocessed_from_disk(self): logging.debug("Querying disk for recordings unprocessed data") metric = GaugeMetricFamily( 'bbb_recordings_unprocessed', "Total number of BigBlueButton recordings enqueued to " "be processed (scraped from disk)") metric.add_metric([], recordings_unprocessed_from_disk( self.recordings_metrics_base_dir)) return metric @staticmethod def _get_participant_count_by_client(meetings): p_by_c = defaultdict(int, {'HTML5': 0, 'DIAL-IN': 0, 'FLASH': 0}) for meeting in meetings: if not meeting.get("attendees"): continue if isinstance(meeting['attendees']['attendee'], list): attendees = meeting['attendees']['attendee'] else: attendees = [meeting['attendees']['attendee']] for attendee in attendees: p_by_c[attendee['clientType']] += 1 return p_by_c @staticmethod def _get_participants_count_by_origin(meetings): p_by_m = defaultdict(int) for meeting in meetings: participants = int(meeting['participantCount']) if participants == 0: continue key = ('', '') if meeting.get("metadata"): servername = meeting['metadata'].get( 'bbb-origin-server-name') or '' origin = meeting['metadata'].get('bbb-origin') or '' key = (servername, origin) p_by_m[key] += participants return p_by_m