Skip to content

Commit

Permalink
chore: Merge branch 'v0.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
greenstatic committed Mar 21, 2024
2 parents 7371d8e + a3f32ab commit d2b5707
Show file tree
Hide file tree
Showing 5 changed files with 410 additions and 182 deletions.
62 changes: 51 additions & 11 deletions bbb-exporter/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
from functools import reduce
from collections import defaultdict

from prometheus_client.metrics_core import GaugeMetricFamily, HistogramMetricFamily, GaugeHistogramMetricFamily
from prometheus_client.metrics_core import GaugeMetricFamily, HistogramMetricFamily, GaugeHistogramMetricFamily, \
CounterMetricFamily
from prometheus_client.utils import INF

import api
import settings
from helpers import execution_duration, HistogramBucketHelper
from helpers import execution_duration, HistogramBucketHelper, str_integer_to_int


class BigBlueButtonCollector:
Expand All @@ -28,6 +29,12 @@ class BigBlueButtonCollector:
recordings_metrics_base_dir = settings.recordings_metrics_base_dir
recordings_metrics_from_disk = settings.RECORDINGS_METRICS_READ_FROM_DISK

last_scrape_meetings = set([])
unique_meetings_count = 0

last_scrape_breakout_rooms = set([])
unique_breakout_rooms_count = 0

def set_room_participants_buckets(self, buckets):
assert type(buckets) == list
assert len(buckets) != 0
Expand Down Expand Up @@ -103,6 +110,9 @@ def collect(self):
yield self.metric_voice_participants_histogram(meetings)
yield self.metric_video_participants_histogram(meetings)

yield self.metric_unique_meetings_count(meetings)
yield self.metric_unique_breakout_rooms_count(meetings)

bbb_exporter = GaugeMetricFamily("bbb_exporter", "BigBlueButton Exporter version", labels=["version"])
bbb_exporter.add_metric([settings.VERSION], 1)
yield bbb_exporter
Expand All @@ -123,14 +133,14 @@ def metric_meetings(self, meetings):
return metric

def metric_participants(self, meetings):
no_participants = reduce(lambda total, meeting: total + int(meeting['participantCount']), meetings, 0)
no_participants = reduce(lambda total, meeting: total + str_integer_to_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)
no_listeners = reduce(lambda total, meeting: total + str_integer_to_int(meeting['listenerCount']), meetings, 0)
metric = GaugeMetricFamily('bbb_meetings_listeners',
"Total number of listeners in all BigBlueButton meetings")
metric.add_metric([], no_listeners)
Expand All @@ -146,14 +156,14 @@ def metric_meetings_participants_origin(self, meetings):
return metric

def metric_meetings_voice_participants(self, meetings):
no_voice_participants = reduce(lambda total, meeting: total + int(meeting['voiceParticipantCount']), meetings, 0)
no_voice_participants = reduce(lambda total, meeting: total + str_integer_to_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)
no_video_participants = reduce(lambda total, meeting: total + str_integer_to_int(meeting['videoCount']), meetings, 0)
metric = GaugeMetricFamily('bbb_meetings_video_participants',
"Total number of video participants in all BigBlueButton meetings")

Expand Down Expand Up @@ -218,7 +228,7 @@ 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']))
histogram.add(str_integer_to_int(meeting['participantCount']))

metric = GaugeHistogramMetricFamily('bbb_room_participants', "BigBlueButton room participants histogram gauge")
metric.add_metric([], histogram.get_buckets(), histogram.sum)
Expand All @@ -229,7 +239,7 @@ 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']))
histogram.add(str_integer_to_int(meeting['listenerCount']))

metric = GaugeHistogramMetricFamily('bbb_room_listeners', "BigBlueButton room listeners histogram gauge")
metric.add_metric([], histogram.get_buckets(), histogram.sum)
Expand All @@ -239,7 +249,7 @@ 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']))
histogram.add(str_integer_to_int(meeting['voiceParticipantCount']))

metric = GaugeHistogramMetricFamily('bbb_room_voice_participants',
"BigBlueButton room voice participants histogram gauge")
Expand All @@ -250,7 +260,7 @@ 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']))
histogram.add(str_integer_to_int(meeting['videoCount']))

metric = GaugeHistogramMetricFamily('bbb_room_video_participants',
"BigBlueButton room video participants histogram gauge")
Expand Down Expand Up @@ -285,6 +295,36 @@ def metric_recordings_unprocessed_from_disk(self):
metric.add_metric([], recordings_unprocessed_from_disk(self.recordings_metrics_base_dir))
return metric

def metric_unique_meetings_count(self, meetings):
logging.debug("Calculating count of unique non-breakout meetings")

# Meetings that are not breakout rooms
m = list(filter(lambda meeting: meeting['isBreakout'].lower() == "false", meetings))

meetings_2 = set(map(lambda meeting: meeting['internalMeetingID'], m))
new_meetings_count = len(meetings_2 - self.last_scrape_meetings)
self.unique_meetings_count += new_meetings_count
self.last_scrape_meetings = meetings_2

metric = CounterMetricFamily('bbb_unique_meetings', "Unique non-breakout meetings counter")
metric.add_metric([], self.unique_meetings_count)
return metric

def metric_unique_breakout_rooms_count(self, meetings):
logging.debug("Calculating count of unique breakout rooms")

# Meetings that are not breakout rooms
m = list(filter(lambda meeting: meeting['isBreakout'].lower() == "true", meetings))

meetings_2 = set(map(lambda meeting: meeting['internalMeetingID'], m))
new_breakout_meetings_count = len(meetings_2 - self.last_scrape_breakout_rooms)
self.unique_breakout_rooms_count += new_breakout_meetings_count
self.last_scrape_breakout_rooms = meetings_2

metric = CounterMetricFamily('bbb_unique_breakout_rooms', "Unique breakout rooms counter")
metric.add_metric([], self.unique_breakout_rooms_count)
return metric

@staticmethod
def _get_participant_count_by_client(meetings):
p_by_c = defaultdict(int, {'HTML5': 0, 'DIAL-IN': 0})
Expand All @@ -305,7 +345,7 @@ def _get_participant_count_by_client(meetings):
def _get_participants_count_by_origin(meetings):
p_by_m = defaultdict(int)
for meeting in meetings:
participants = int(meeting['participantCount'])
participants = str_integer_to_int(meeting['participantCount'])
if participants == 0:
continue
key = ('', '')
Expand Down
20 changes: 20 additions & 0 deletions bbb-exporter/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,23 @@ def str_to_bool_or_none(s: str) -> Optional[bool]:
return False

return None


def str_integer_to_int(s: str) -> int:
# Converts a string into an integer. The string can be simply an signed integer (e.g. 123, -123), comma thousands
# separated signed integer (e.g. 1,234 , -1,234) or a signed decimal integer (e.g. 1.234, -1.234). In the case of
# a signed decimal integer we will truncate everything after the decimal point. In the case of an empty string
# the function will return 0.
#
# "-1,223.234" -> -1223

if s == '':
return 0

s = s.replace(',', '')
s = s.split('.')

if len(s) > 0:
return int(s[0])

return 0
21 changes: 21 additions & 0 deletions bbb-exporter/helpers_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import unittest

from helpers import str_integer_to_int


class StrIntegerToIntTest(unittest.TestCase):
def test_something(self):
self.assertEqual(str_integer_to_int("0"), 0)
self.assertEqual(str_integer_to_int("11"), 11)
self.assertEqual(str_integer_to_int("-123"), -123)
self.assertEqual(str_integer_to_int(""), 0)
self.assertEqual(str_integer_to_int("1,234"), 1234)
self.assertEqual(str_integer_to_int("-1,234"), -1234)
self.assertEqual(str_integer_to_int("1.234"), 1)
self.assertEqual(str_integer_to_int("-1.234"), -1)
self.assertEqual(str_integer_to_int("1,223.234"), 1223)
self.assertEqual(str_integer_to_int("-1,223.234"), -1223)


if __name__ == '__main__':
unittest.main()
6 changes: 3 additions & 3 deletions bbb-exporter/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from helpers import validate_api_base_url, validate_buckets, str_to_bool_or_none

MAJOR = 0
MINOR = 6
BUGFIX = 1
INFO = ""
MINOR = 7
BUGFIX = 0
INFO = "preview2"

VERSION = "{}.{}.{}".format(MAJOR, MINOR, BUGFIX)
if INFO:
Expand Down
Loading

0 comments on commit d2b5707

Please sign in to comment.