Skip to content

Commit

Permalink
ref: Refactor statistics code and json format. (#452)
Browse files Browse the repository at this point in the history
* stats: Removes unnecessary levels from the stats json.

* ref: Migrate stats to getStats().
  • Loading branch information
bgrozev authored Apr 1, 2020
1 parent 4b47d13 commit 36dc201
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 263 deletions.
51 changes: 47 additions & 4 deletions src/main/java/org/jitsi/jicofo/FocusManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ public int getConferenceCount()
return conferences.size();
}

public int getNonHealthCheckConferenceCount()
private int getNonHealthCheckConferenceCount()
{
return (int)conferences.values().stream()
.filter(JitsiMeetConferenceImpl::includeInStatistics)
Expand Down Expand Up @@ -740,11 +740,54 @@ public JitsiMeetServices getJitsiMeetServices()

public JSONObject getStats()
{
JSONObject json = new JSONObject();
// We want to avoid exposing unnecessary hierarchy levels in the stats,
// so we'll merge stats from different "child" objects here.
JSONObject stats = jitsiMeetServices.getStats();
stats.put("total_participants", statistics.totalParticipants.get());
stats.put("total_conferences_created", statistics.totalConferencesCreated.get());
stats.put("conferences", getNonHealthCheckConferenceCount());

// Calculate the number of participants and conference size distribution
int numParticipants = 0;
int largestConferenceSize = 0;
int[] conferenceSizes = new int[22];
for (JitsiMeetConference conference : getConferences())
{
if (!conference.includeInStatistics())
{
continue;
}
int confSize = conference.getParticipantCount();
// getParticipantCount only includes endpoints with allocated media
// channels, so if a single participant is waiting in a meeting
// they wouldn't be counted. In stats, calling this a conference
// with size 0 would be misleading, so we add 1 in this case to
// properly show it as a conference of size 1. (If there really
// weren't any participants in there at all, the conference
// wouldn't have existed in the first place).
if (confSize == 0)
{
confSize = 1;
}
numParticipants += confSize;
largestConferenceSize = Math.max(largestConferenceSize, confSize);

json.put("services", jitsiMeetServices.getStats());
int conferenceSizeIndex = confSize < conferenceSizes.length
? confSize
: conferenceSizes.length - 1;
conferenceSizes[conferenceSizeIndex]++;
}

stats.put("largest_conference", largestConferenceSize);
stats.put("participants", numParticipants);
JSONArray conferenceSizesJson = new JSONArray();
for (int size : conferenceSizes)
{
conferenceSizesJson.add(size);
}
stats.put("conference_sizes", conferenceSizesJson);

return json;
return stats;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/jitsi/jicofo/JitsiMeetServices.java
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,23 @@ public JSONObject getStats()
JSONObject json = new JSONObject();

json.put("bridge_selector", bridgeSelector.getStats());
JigasiDetector jigasiDetector = getJigasiDetector();
if (jigasiDetector != null)
{
json.put("jigasi_detector", jigasiDetector.getStats());
}

JibriDetector jibriDetector = getJibriDetector();
if (jibriDetector != null)
{
json.put("jibri_detector", jibriDetector.getStats());
}

JibriDetector sipJibriDetector = getSipJibriDetector();
if (sipJibriDetector != null)
{
json.put("sip_jibri_detector", sipJibriDetector.getStats());
}

return json;
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/org/jitsi/jicofo/bridge/BridgeSelector.java
Original file line number Diff line number Diff line change
Expand Up @@ -753,10 +753,12 @@ public int getOperationalBridgeCount()

public JSONObject getStats()
{
JSONObject json = new JSONObject();
// We want to avoid exposing unnecessary hierarchy levels in the stats,
// so we'll merge stats from different "child" objects here.
JSONObject stats = bridgeSelectionStrategy.getStats();
stats.put("bridge_count", getBridgeCount());
stats.put("operational_bridge_count", getOperationalBridgeCount());

json.put("strategy", bridgeSelectionStrategy.getStats());

return json;
return stats;
}
}
10 changes: 10 additions & 0 deletions src/main/java/org/jitsi/jicofo/jigasi/JigasiDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import org.jitsi.jicofo.*;
import org.jitsi.jicofo.xmpp.*;
import org.json.simple.*;
import org.jxmpp.jid.*;

import java.util.*;
Expand Down Expand Up @@ -350,4 +351,13 @@ public int getJigasiTranscriberCount()
{
return (int) instances.stream().filter(i -> supportTranscription(i)).count();
}

public JSONObject getStats()
{
JSONObject stats = new JSONObject();
stats.put("sip_count", getJigasiSipCount());
stats.put("transcriber_count", getJigasiTranscriberCount());

return stats;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.jitsi.jicofo.*;
import org.jitsi.jicofo.xmpp.*;
import org.jitsi.osgi.*;
import org.json.simple.*;
import org.jxmpp.jid.*;

/**
Expand Down Expand Up @@ -186,4 +187,11 @@ private void notifyJibriStatus(Jid jibriJid, boolean available)
logger.warn("No EventAdmin!");
}
}

public JSONObject getStats()
{
JSONObject stats = new JSONObject();
stats.put("count", getInstanceCount());
return stats;
}
}
11 changes: 11 additions & 0 deletions src/main/java/org/jitsi/jicofo/recording/jibri/JibriStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.jitsi.eventadmin.*;
import org.jitsi.osgi.*;
import org.jitsi.utils.logging.*;
import org.json.simple.*;
import org.osgi.framework.*;

/**
Expand Down Expand Up @@ -130,4 +131,14 @@ public int getTotalRecordingFailures()
{
return totalRecordingFailures;
}

public JSONObject getStats()
{
JSONObject stats = new JSONObject();
stats.put("total_live_streaming_failures", getTotalLiveStreamingFailures());
stats.put("total_recording_failures", getTotalRecordingFailures());
stats.put("total_sip_call_failures", getTotalSipCallFailures());

return stats;
}
}
91 changes: 6 additions & 85 deletions src/main/java/org/jitsi/jicofo/rest/Statistics.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,70 +15,19 @@
*/
package org.jitsi.jicofo.rest;

import org.jitsi.jicofo.*;
import org.jitsi.jicofo.recording.jibri.*;
import org.jitsi.jicofo.stats.*;
import org.jitsi.jicofo.util.*;
import org.json.simple.*;

import javax.inject.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;

import static org.jitsi.xmpp.extensions.colibri.ColibriStatsExtension.*;

/**
* Adds statistics REST endpoint exposes some internal Jicofo stats.
*/
@Path("/stats")
public class Statistics
{
/**
* The current number of jitsi-videobridge instances.
*/
public static final String BREWERY_JVB_COUNT = "brewery_jvb_count";

/**
* The current number of jitsi-videobridge instances that are operational
* (not failed).
*/
public static final String BREWERY_JVB_OPERATIONAL_COUNT = "brewery_jvb_operational_count";

/**
* The current number of jigasi instances that support SIP.
*/
public static final String BREWERY_JIGASI_SIP_COUNT = "brewery_jigasi_sip_count";

/**
* The current number of jigasi instances that support transcription.
*/
public static final String BREWERY_JIGASI_TRANSCRIBER_COUNT = "brewery_jigasi_transcriber_count";

/**
* The current number of jibri instances for streaming.
*/
public static final String BREWERY_JIBRI_COUNT = "brewery_jibri_count";

/**
* The current number of jibri instances for SIP.
*/
public static final String BREWERY_JIBRI_SIP_COUNT = "brewery_jibri_sip_count";

/**
* How many times the live streaming has failed to start so far.
*/
public static final String TOTAL_LIVE_STREAMING_FAILURES = "total_live_streaming_failures";

/**
* How many times the recording has failed to start so far.
*/
public static final String TOTAL_RECORDING_FAILURES = "total_recording_failures";

/**
* How many times a SIP call has failed to start so far.
*/
public static final String TOTAL_SIP_CALL_FAILURES = "total_sip_call_failures";

@Inject
protected FocusManagerProvider focusManagerProvider;

Expand All @@ -93,41 +42,13 @@ public class Statistics
@Produces(MediaType.APPLICATION_JSON)
public String getStats()
{
FocusManager focusManager = focusManagerProvider.get();
JibriStats jibriStats = jibriStatsProvider.get();

JicofoStatisticsSnapshot snapshot
= JicofoStatisticsSnapshot.generate(focusManager, jibriStats);
JSONObject json = new JSONObject();
json.put(CONFERENCES, snapshot.numConferences);
json.put(LARGEST_CONFERENCE, snapshot.largestConferenceSize);
json.put(TOTAL_CONFERENCES_CREATED, snapshot.totalConferencesCreated);
json.put(PARTICIPANTS, snapshot.numParticipants);
json.put(TOTAL_PARTICIPANTS, snapshot.totalNumParticipants);
json.put(BREWERY_JVB_COUNT, snapshot.bridgeCount);
json.put(BREWERY_JVB_OPERATIONAL_COUNT, snapshot.operationalBridgeCount);
json.put(BREWERY_JIGASI_SIP_COUNT, snapshot.jigasiSipCount);
json.put(BREWERY_JIGASI_TRANSCRIBER_COUNT, snapshot.jigasiTranscriberCount);
json.put(BREWERY_JIBRI_COUNT, snapshot.jibriCount);
json.put(BREWERY_JIBRI_SIP_COUNT, snapshot.sipJibriCount);
json.put(TOTAL_LIVE_STREAMING_FAILURES, snapshot.totalLiveStreamingFailures);
json.put(TOTAL_RECORDING_FAILURES, snapshot.totalRecordingFailures);
json.put(TOTAL_SIP_CALL_FAILURES, snapshot.totalSipCallFailures);
JSONArray conferenceSizesJson = new JSONArray();
for (int size : snapshot.conferenceSizes)
{
conferenceSizesJson.add(size);
}
json.put(CONFERENCE_SIZES, conferenceSizesJson);
JSONObject stats = new JSONObject();

// XXX we have this top-down approach of populating the stats in various
// places in the bridge and thought to bring it over here. It'll bring
// proper name spacing of the various stats, but we'll have to type a
// bit more in dd to access said stats. For example the bridge selection
// strategy stats will be available under
// focus.services.selector.strategy.*
json.put("focus", focusManager.getStats());
// We want to avoid exposing unnecessary hierarchy levels in the stats,
// so we merge the FocusManager and Jibri stats in the root object.
stats.putAll(focusManagerProvider.get().getStats());
stats.putAll(jibriStatsProvider.get().getStats());

return json.toJSONString();
return stats.toJSONString();
}
}
Loading

0 comments on commit 36dc201

Please sign in to comment.