Skip to content

Commit

Permalink
feat: add stats for total Jibri failures
Browse files Browse the repository at this point in the history
The following JSON keys will be added to the stats:
"total_live_streaming_failures"
"total_recording_failures"
"total_sip_call_failures"
  • Loading branch information
paweldomas committed Mar 26, 2020
1 parent a126bf5 commit 82ff6f4
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 16 deletions.
7 changes: 6 additions & 1 deletion src/main/java/org/jitsi/jicofo/JitsiMeetConferenceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,11 @@ public synchronized void start()
{
jibriRecorder
= new JibriRecorder(
this, getXmppConnection(), executor, globalConfig);
osgiCtx,
this,
getXmppConnection(),
executor,
globalConfig);

jibriOpSet.addJibri(jibriRecorder);
}
Expand All @@ -429,6 +433,7 @@ public synchronized void start()
{
jibriSipGateway
= new JibriSipGateway(
osgiCtx,
this,
getXmppConnection(),
FocusBundleActivator.getSharedThreadPool(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ protected String[][] getBundlesImpl()
},
{
"org/jitsi/jicofo/bridge/JvbDoctor",
"org/jitsi/jicofo/recording/jibri/JibriStats",
"org/jitsi/jicofo/VersionBroadcaster"
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jitsi.utils.logging.*;
import org.jivesoftware.smack.packet.*;
import org.jxmpp.jid.*;
import org.osgi.framework.*;

import java.util.*;
import java.util.concurrent.*;
Expand All @@ -42,6 +43,11 @@
*/
public abstract class CommonJibriStuff
{
/**
* OSGI bundle context.
*/
protected final BundleContext bundleContext;

/**
* The Jitsi Meet conference instance.
*/
Expand Down Expand Up @@ -89,6 +95,7 @@ public abstract class CommonJibriStuff

/**
* Creates new instance of <tt>JibriRecorder</tt>.
* @param bundleContext OSGi {@link BundleContext}.
* @param isSIP indicates whether this stuff is for SIP Jibri or for regular
* Jibris.
* @param conference <tt>JitsiMeetConference</tt> to be recorded by new
Expand All @@ -99,14 +106,15 @@ public abstract class CommonJibriStuff
* @param globalConfig the global config that provides some values required
* by <tt>JibriRecorder</tt> to work.
*/
CommonJibriStuff(
CommonJibriStuff( BundleContext bundleContext,
boolean isSIP,
JitsiMeetConferenceImpl conference,
XmppConnection xmppConnection,
ScheduledExecutorService scheduledExecutor,
JitsiMeetGlobalConfig globalConfig,
Logger logger)
{
this.bundleContext = Objects.requireNonNull(bundleContext, "bundleContext");
this.connection
= Objects.requireNonNull(xmppConnection, "xmppConnection");
this.conference = Objects.requireNonNull(conference, "conference");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.jitsi.utils.*;
import org.jitsi.utils.logging.*;
import org.jivesoftware.smack.packet.*;
import org.osgi.framework.*;

import java.util.concurrent.*;

Expand Down Expand Up @@ -58,6 +59,7 @@ public class JibriRecorder

/**
* Creates new instance of <tt>JibriRecorder</tt>.
* @param bundleContext OSGi {@link BundleContext}.
* @param conference <tt>JitsiMeetConference</tt> to be recorded by new
* instance.
* @param connection the XMPP connection which will be used for
Expand All @@ -66,12 +68,14 @@ public class JibriRecorder
* @param globalConfig the global config that provides some values required
* by <tt>JibriRecorder</tt> to work.
*/
public JibriRecorder(JitsiMeetConferenceImpl conference,
public JibriRecorder(BundleContext bundleContext,
JitsiMeetConferenceImpl conference,
XmppConnection connection,
ScheduledExecutorService scheduledExecutor,
JitsiMeetGlobalConfig globalConfig)
{
super(
bundleContext,
false /* deals with non SIP Jibri events */,
conference,
connection,
Expand Down Expand Up @@ -140,6 +144,7 @@ protected IQ handleStartRequest(JibriIq iq)
String sessionId = generateSessionId();
jibriSession
= new JibriSession(
bundleContext,
this,
conference.getRoomName(),
iq.getFrom(),
Expand Down
93 changes: 83 additions & 10 deletions src/main/java/org/jitsi/jicofo/recording/jibri/JibriSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package org.jitsi.jicofo.recording.jibri;

import org.jitsi.jicofo.util.*;
import org.jitsi.utils.*;
import org.jitsi.xmpp.extensions.jibri.*;
import org.jitsi.xmpp.extensions.jibri.JibriIq.*;
import net.java.sip.communicator.service.protocol.*;
Expand All @@ -29,6 +31,7 @@
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.*;
import org.jxmpp.jid.*;
import org.osgi.framework.*;

import java.util.*;
import java.util.concurrent.*;
Expand All @@ -51,6 +54,11 @@ public class JibriSession
static private final Logger classLogger
= Logger.getLogger(JibriSession.class);

/**
* Provides the {@link EventAdmin} instance for emitting events.
*/
private final EventAdminProvider eventAdminProvider;

/**
* Returns <tt>true</tt> if given <tt>status</tt> indicates that Jibri is in
* the middle of starting of the recording process.
Expand Down Expand Up @@ -182,6 +190,7 @@ static private boolean isStartingStatus(JibriIq.Status status)

/**
* Creates new {@link JibriSession} instance.
* @param bundleContext the OSGI context.
* @param owner the session owner which will be notified about this session
* state changes.
* @param roomName the name if the XMPP MUC room (full address).
Expand All @@ -206,6 +215,7 @@ static private boolean isStartingStatus(JibriIq.Status status)
* select logging level for this instance {@link #logger}.
*/
JibriSession(
BundleContext bundleContext,
JibriSession.Owner owner,
EntityBareJid roomName,
Jid initiator,
Expand All @@ -223,6 +233,7 @@ static private boolean isStartingStatus(JibriIq.Status status)
String applicationData,
Logger logLevelDelegate)
{
this.eventAdminProvider = new EventAdminProvider(bundleContext);
this.owner = owner;
this.roomName = roomName;
this.initiator = initiator;
Expand All @@ -242,24 +253,87 @@ static private boolean isStartingStatus(JibriIq.Status status)
logger = Logger.getLogger(classLogger, logLevelDelegate);
}

/**
* Used internally to call
* {@link Owner#onSessionStateChanged(JibriSession, Status, FailureReason)}.
* @param newStatus the new status to dispatch.
* @param failureReason the failure reason associated with the state
* transition if any.
*/
private void dispatchSessionStateChanged(
Status newStatus, FailureReason failureReason)
{
if (failureReason != null)
{
emitSessionFailedEvent();
}
owner.onSessionStateChanged(this, newStatus, failureReason);
}

/**
* Asynchronously emits {@link JibriSessionEvent#FAILED_TO_START} event over
* the {@link EventAdmin} bus.
*/
private void emitSessionFailedEvent()
{
JibriSessionEvent.Type jibriType;
if (isSIP)
{
jibriType = JibriSessionEvent.Type.SIP_CALL;
}
else if (StringUtils.isNullOrEmpty(streamID))
{
jibriType = JibriSessionEvent.Type.RECORDING;
}
else
{
jibriType = JibriSessionEvent.Type.LIVE_STREAMING;
}

eventAdminProvider
.get()
.postEvent(
JibriSessionEvent.newFailedToStartEvent(jibriType));
}

/**
* Starts this session. A new Jibri instance will be selected and start
* request will be sent (in non blocking mode).
* @throws StartException if failed to start.
*/
synchronized public void start()
throws StartException
{
try
{
startInternal();
}
catch (Exception e)
{
emitSessionFailedEvent();

throw e;
}
}

/**
* Does the actual start logic.
*
* @throws StartException if fails to start.
*/
private void startInternal()
throws StartException
{
final Jid jibriJid = jibriDetector.selectJibri();

if (jibriJid == null) {
logger.error("Unable to find an available Jibri, can't start");
logger.error("Unable to find an available Jibri, can't start");

if (jibriDetector.isAnyInstanceConnected()) {
throw new StartException(StartException.ALL_BUSY);
}
if (jibriDetector.isAnyInstanceConnected()) {
throw new StartException(StartException.ALL_BUSY);
}

throw new StartException(StartException.NOT_AVAILABLE);
throw new StartException(StartException.NOT_AVAILABLE);
}

try
Expand Down Expand Up @@ -624,7 +698,7 @@ private void handleJibriStatusUpdate(
+ "session has now failed: " + exc, exc);
// Propagate up that the session has failed entirely.
// We'll pass the original failure reason.
owner.onSessionStateChanged(this, newStatus, failureReason);
dispatchSessionStateChanged(newStatus, failureReason);
cleanupSession();
}
}
Expand All @@ -643,7 +717,7 @@ private void handleJibriStatusUpdate(
logger.info("Jibri failed, but max amount of retries ("
+ maxNumRetries + ") reached, giving up");
}
owner.onSessionStateChanged(this, newStatus, failureReason);
dispatchSessionStateChanged(newStatus, failureReason);
cleanupSession();
}
}
Expand All @@ -652,14 +726,13 @@ else if (Status.OFF.equals(newStatus))
logger.info("Jibri session ended cleanly, notifying owner and "
+ "cleaning up session");
// The Jibri stopped for some non-error reason
owner.onSessionStateChanged(this, newStatus, failureReason);
dispatchSessionStateChanged(newStatus, null);
cleanupSession();
}
else if (Status.ON.equals(newStatus))
{
logger.info("Jibri session started, notifying owner");
// The Jibri stopped for some non-error reason
owner.onSessionStateChanged(this, newStatus, failureReason);
dispatchSessionStateChanged(newStatus, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright @ 2018 - present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.jitsi.jicofo.recording.jibri;

import org.jitsi.eventadmin.*;

import java.util.*;

/**
* Events emitted for {@link JibriSession}.
*/
public class JibriSessionEvent extends Event
{
/**
* Event emitted when a {@link JibriSession} fails to start.
*/
public static final String FAILED_TO_START
= "org/jitsi/jicofo/jibri/session/FAILED_TO_START";

/**
* A key holding the {@link Type}.
*/
private static final String TYPE_KEY = "TYPE";

/**
* Creates new {@link JibriSessionEvent} with the {@link #FAILED_TO_START}
* topic.
*
* @param type - Tells which {@link Type} of Jibri session is the new event
* for.
*/
static public JibriSessionEvent newFailedToStartEvent(Type type)
{
Dictionary<String, Object> props = new Hashtable<>(1);

props.put(TYPE_KEY, type);

return new JibriSessionEvent(FAILED_TO_START, props);
}

/**
* Creates new instance.
* @param topic - The event's topic.
* @param properties - The event's properties.
*/
public JibriSessionEvent(String topic, Dictionary properties)
{
super(topic, properties);
}

/**
* @return {@code true} if the event comes for a SIP Jibri session or
* {@code false} otherwise.
*/
public Type getType()
{
Object type = getProperty(TYPE_KEY);

return type instanceof Type ? (Type) type : null;
}

/**
* A Jibri session type.
*/
public enum Type {
/**
* SIP Jibri call.
*/
SIP_CALL,
/**
* Jibri live streaming session.
*/
LIVE_STREAMING,
/**
* Jibri recording session.
*/
RECORDING
}
}
Loading

0 comments on commit 82ff6f4

Please sign in to comment.