openvidu-server: createdAt properties equal to CDR timestamps. KMS server events improved

pull/121/head
pabloFuente 2018-09-19 17:15:37 +02:00
parent 30874f24ce
commit e3ae7c34b2
11 changed files with 84 additions and 39 deletions

View File

@ -12,8 +12,8 @@ public class CDREventWebrtcConnection extends CDREventEnd implements Comparable<
// webrtcConnectionCreated // webrtcConnectionCreated
public CDREventWebrtcConnection(String sessionId, String participantId, MediaOptions mediaOptions, public CDREventWebrtcConnection(String sessionId, String participantId, MediaOptions mediaOptions,
String receivingFrom) { String receivingFrom, Long timestamp) {
super(CDREventName.webrtcConnectionCreated, sessionId, System.currentTimeMillis()); super(CDREventName.webrtcConnectionCreated, sessionId, timestamp);
this.participantId = participantId; this.participantId = participantId;
this.mediaOptions = mediaOptions; this.mediaOptions = mediaOptions;
this.receivingFrom = receivingFrom; this.receivingFrom = receivingFrom;

View File

@ -124,9 +124,9 @@ public class CallDetailRecord {
this.logger.log(new CDREventParticipant(e, reason)); this.logger.log(new CDREventParticipant(e, reason));
} }
public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions) { public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions, Long timestamp) {
CDREventWebrtcConnection publisher = new CDREventWebrtcConnection(sessionId, CDREventWebrtcConnection publisher = new CDREventWebrtcConnection(sessionId,
participant.getParticipantPublicId(), mediaOptions, null); participant.getParticipantPublicId(), mediaOptions, null, timestamp);
this.publications.put(participant.getParticipantPublicId(), publisher); this.publications.put(participant.getParticipantPublicId(), publisher);
if (openviduConfig.isCdrEnabled()) if (openviduConfig.isCdrEnabled())
this.logger.log(publisher); this.logger.log(publisher);
@ -143,10 +143,10 @@ public class CallDetailRecord {
return false; return false;
} }
public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId) { public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId, Long timestamp) {
CDREventWebrtcConnection publisher = this.publications.get(senderPublicId); CDREventWebrtcConnection publisher = this.publications.get(senderPublicId);
CDREventWebrtcConnection subscriber = new CDREventWebrtcConnection(sessionId, CDREventWebrtcConnection subscriber = new CDREventWebrtcConnection(sessionId,
participant.getParticipantPublicId(), publisher.mediaOptions, senderPublicId); participant.getParticipantPublicId(), publisher.mediaOptions, senderPublicId, timestamp);
this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>()); this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>());
this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber); this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber);
if (openviduConfig.isCdrEnabled()) if (openviduConfig.isCdrEnabled())

View File

@ -175,6 +175,10 @@ public class OpenviduConfig {
public boolean isKmsStatsEnabled() { public boolean isKmsStatsEnabled() {
return this.kmsStatsEnabled; return this.kmsStatsEnabled;
} }
public String getOpenViduRecordingNotification() {
return this.openviduRecordingNotification;
}
public ParticipantRole[] getRolesFromRecordingNotification() { public ParticipantRole[] getRolesFromRecordingNotification() {
ParticipantRole[] roles; ParticipantRole[] roles;

View File

@ -36,10 +36,14 @@ public class Participant {
private final String METADATA_SEPARATOR = "%/%"; private final String METADATA_SEPARATOR = "%/%";
public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata, public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata,
String location, String platform) { String location, String platform, Long createdAt) {
this.participantPrivatetId = participantPrivatetId; this.participantPrivatetId = participantPrivatetId;
this.participantPublicId = participantPublicId; this.participantPublicId = participantPublicId;
this.createdAt = System.currentTimeMillis(); if (createdAt != null) {
this.createdAt = createdAt;
} else {
this.createdAt = System.currentTimeMillis();
}
this.token = token; this.token = token;
this.clientMetadata = clientMetadata; this.clientMetadata = clientMetadata;
if (!token.getServerMetadata().isEmpty()) if (!token.getServerMetadata().isEmpty())

View File

@ -339,7 +339,7 @@ public abstract class SessionManager {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
String participantPublicId = this.generateRandomChain(); String participantPublicId = this.generateRandomChain();
Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata, location, Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata, location,
platform); platform, null);
while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId, while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId,
p) != null) { p) != null) {
participantPublicId = this.generateRandomChain(); participantPublicId = this.generateRandomChain();
@ -355,7 +355,7 @@ public abstract class SessionManager {
String clientMetadata) { String clientMetadata) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
token, clientMetadata, null, null); token, clientMetadata, null, null, null);
this.sessionidParticipantpublicidParticipant.get(sessionId) this.sessionidParticipantpublicidParticipant.get(sessionId)
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
return p; return p;

View File

@ -80,7 +80,8 @@ public class KurentoParticipant extends Participant {
public KurentoParticipant(Participant participant, KurentoSession kurentoSession, MediaPipeline pipeline, public KurentoParticipant(Participant participant, KurentoSession kurentoSession, MediaPipeline pipeline,
InfoHandler infoHandler, CallDetailRecord CDR, OpenviduConfig openviduConfig) { InfoHandler infoHandler, CallDetailRecord CDR, OpenviduConfig openviduConfig) {
super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(), super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(),
participant.getClientMetadata(), participant.getLocation(), participant.getPlatform()); participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(),
participant.getCreatedAt());
this.openviduConfig = openviduConfig; this.openviduConfig = openviduConfig;
this.session = kurentoSession; this.session = kurentoSession;
this.pipeline = pipeline; this.pipeline = pipeline;
@ -113,8 +114,6 @@ public class KurentoParticipant extends Participant {
// Remove streamId from publisher's map // Remove streamId from publisher's map
this.session.publishedStreamIds.putIfAbsent(this.getPublisherStreamId(), this.getParticipantPrivateId()); this.session.publishedStreamIds.putIfAbsent(this.getPublisherStreamId(), this.getParticipantPrivateId());
CDR.recordNewPublisher(this, this.session.getSessionId(), mediaOptions);
} }
public void shapePublisherMedia(GenericMediaElement element, MediaType type) { public void shapePublisherMedia(GenericMediaElement element, MediaType type) {
@ -233,6 +232,9 @@ public class KurentoParticipant extends Participant {
log.info("PARTICIPANT {}: Is now publishing video in room {}", this.getParticipantPublicId(), log.info("PARTICIPANT {}: Is now publishing video in room {}", this.getParticipantPublicId(),
this.session.getSessionId()); this.session.getSessionId());
CDR.recordNewPublisher(this, this.session.getSessionId(), this.publisher.getMediaOptions(),
this.publisher.createdAt());
return sdpResponse; return sdpResponse;
} }
@ -313,7 +315,8 @@ public class KurentoParticipant extends Participant {
senderName, this.session.getSessionId()); senderName, this.session.getSessionId());
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) { if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getParticipantPublicId()); CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getParticipantPublicId(),
subscriber.createdAt());
} }
return sdpAnswer; return sdpAnswer;
@ -601,14 +604,17 @@ public class KurentoParticipant extends Participant {
+ event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName() + event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName()
+ " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis();
endpoint.flowInMedia.put(event.getSource().getName(), event.getMediaType()); /*
if (endpoint.getPublisher().getMediaOptions().hasAudio() * endpoint.flowInMedia.put(event.getSource().getName(), event.getMediaType());
&& endpoint.getPublisher().getMediaOptions().hasVideo() * if (endpoint.getPublisher().getMediaOptions().hasAudio() &&
&& endpoint.flowInMedia.values().size() == 2) { * endpoint.getPublisher().getMediaOptions().hasVideo() &&
endpoint.kmsEvents.add(new KmsEvent(event)); * endpoint.flowInMedia.values().size() == 2) {
} else if (endpoint.flowInMedia.values().size() == 1) { */
endpoint.kmsEvents.add(new KmsEvent(event)); endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
} /*
* } else if (endpoint.flowInMedia.values().size() == 1) {
* endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt())); }
*/
log.info(msg1); log.info(msg1);
this.infoHandler.sendInfo(msg1); this.infoHandler.sendInfo(msg1);
@ -619,37 +625,48 @@ public class KurentoParticipant extends Participant {
+ event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName() + event.getState() + " | SOURCE: " + event.getSource().getName() + " | PAD: " + event.getPadName()
+ " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis(); + " | MEDIATYPE: " + event.getMediaType() + " | TIMESTAMP: " + System.currentTimeMillis();
endpoint.flowOutMedia.put(event.getSource().getName(), event.getMediaType()); /*
if (endpoint.getPublisher().getMediaOptions().hasAudio() * endpoint.flowOutMedia.put(event.getSource().getName(), event.getMediaType());
&& endpoint.getPublisher().getMediaOptions().hasVideo() * if (endpoint.getPublisher().getMediaOptions().hasAudio() &&
&& endpoint.flowOutMedia.values().size() == 2) { * endpoint.getPublisher().getMediaOptions().hasVideo() &&
endpoint.kmsEvents.add(new KmsEvent(event)); * endpoint.flowOutMedia.values().size() == 2) {
} else if (endpoint.flowOutMedia.values().size() == 1) { */
endpoint.kmsEvents.add(new KmsEvent(event)); endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
} /*
* } else if (endpoint.flowOutMedia.values().size() == 1) {
* endpoint.kmsEvents.add(new KmsEvent(event)); }
*/
log.info(msg1); log.info(msg1);
this.infoHandler.sendInfo(msg1); this.infoHandler.sendInfo(msg1);
}); });
endpoint.getWebEndpoint().addIceGatheringDoneListener(event -> { endpoint.getWebEndpoint().addIceGatheringDoneListener(event -> {
endpoint.kmsEvents.add(new KmsEvent(event)); endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
}); });
endpoint.getWebEndpoint().addConnectionStateChangedListener(event -> { endpoint.getWebEndpoint().addConnectionStateChangedListener(event -> {
endpoint.kmsEvents.add(new KmsEvent(event)); endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
}); });
endpoint.getWebEndpoint().addNewCandidatePairSelectedListener(event -> { endpoint.getWebEndpoint().addNewCandidatePairSelectedListener(event -> {
endpoint.selectedLocalIceCandidate = event.getCandidatePair().getLocalCandidate(); endpoint.selectedLocalIceCandidate = event.getCandidatePair().getLocalCandidate();
endpoint.selectedRemoteIceCandidate = event.getCandidatePair().getRemoteCandidate(); endpoint.selectedRemoteIceCandidate = event.getCandidatePair().getRemoteCandidate();
endpoint.kmsEvents.add(new KmsEvent(event)); endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
String msg = "ICE CANDIDATE SELECTED (" + endpoint.getEndpoint().getTag("name") + "): LOCAL CANDIDATE: " String msg = "ICE CANDIDATE SELECTED (" + endpoint.getEndpoint().getTag("name") + "): LOCAL CANDIDATE: "
+ endpoint.selectedLocalIceCandidate + " | REMOTE CANDIDATE: " + endpoint.selectedRemoteIceCandidate + endpoint.selectedLocalIceCandidate + " | REMOTE CANDIDATE: " + endpoint.selectedRemoteIceCandidate
+ " | TIMESTAMP: " + System.currentTimeMillis(); + " | TIMESTAMP: " + System.currentTimeMillis();
log.warn(msg); log.warn(msg);
this.infoHandler.sendInfo(msg); this.infoHandler.sendInfo(msg);
}); });
endpoint.getEndpoint().addMediaTranscodingStateChangeListener(event -> {
endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
});
endpoint.getWebEndpoint().addIceComponentStateChangeListener(event -> {
endpoint.kmsEvents.add(new KmsEvent(event, endpoint.createdAt()));
});
} }
public MediaPipeline getPipeline() { public MediaPipeline getPipeline() {

View File

@ -5,10 +5,15 @@ import org.kurento.client.MediaEvent;
public class KmsEvent { public class KmsEvent {
long timestamp; long timestamp;
long msSinceCreation;
String endpoint;
MediaEvent event; MediaEvent event;
public KmsEvent(MediaEvent event) { public KmsEvent(MediaEvent event, long createdAt) {
this.event = event; this.event = event;
this.endpoint = event.getSource().getTag("name");
this.event.setSource(null);
this.timestamp = System.currentTimeMillis(); this.timestamp = System.currentTimeMillis();
this.msSinceCreation = this.timestamp - createdAt;
} }
} }

View File

@ -31,12 +31,14 @@ import org.kurento.client.EventListener;
import org.kurento.client.IceCandidate; import org.kurento.client.IceCandidate;
import org.kurento.client.ListenerSubscription; import org.kurento.client.ListenerSubscription;
import org.kurento.client.MediaElement; import org.kurento.client.MediaElement;
import org.kurento.client.MediaEvent;
import org.kurento.client.MediaPipeline; import org.kurento.client.MediaPipeline;
import org.kurento.client.MediaType; import org.kurento.client.MediaType;
import org.kurento.client.OnIceCandidateEvent; import org.kurento.client.OnIceCandidateEvent;
import org.kurento.client.RtpEndpoint; import org.kurento.client.RtpEndpoint;
import org.kurento.client.SdpEndpoint; import org.kurento.client.SdpEndpoint;
import org.kurento.client.WebRtcEndpoint; import org.kurento.client.WebRtcEndpoint;
import org.kurento.jsonrpc.JsonUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -76,6 +78,7 @@ public abstract class MediaEndpoint {
private KurentoParticipant owner; private KurentoParticipant owner;
private String endpointName; private String endpointName;
protected Long createdAt; // Timestamp when this [publisher / subscriber] started [publishing / receiving]
private MediaPipeline pipeline = null; private MediaPipeline pipeline = null;
private ListenerSubscription endpointSubscription = null; private ListenerSubscription endpointSubscription = null;
@ -157,6 +160,10 @@ public abstract class MediaEndpoint {
} }
} }
public long createdAt() {
return this.createdAt;
}
public WebRtcEndpoint getWebEndpoint() { public WebRtcEndpoint getWebEndpoint() {
return webEndpoint; return webEndpoint;
} }
@ -492,6 +499,7 @@ public abstract class MediaEndpoint {
public JsonObject withStatsToJson() { public JsonObject withStatsToJson() {
JsonObject json = new JsonObject(); JsonObject json = new JsonObject();
json.addProperty("createdAt", this.createdAt);
json.addProperty("webrtcTagName", this.getEndpoint().getTag("name")); json.addProperty("webrtcTagName", this.getEndpoint().getTag("name"));
json.add("receivedCandidates", new GsonBuilder().create().toJsonTree(this.receivedCandidateList)); json.add("receivedCandidates", new GsonBuilder().create().toJsonTree(this.receivedCandidateList));
json.addProperty("localCandidate", this.selectedLocalIceCandidate); json.addProperty("localCandidate", this.selectedLocalIceCandidate);
@ -502,8 +510,13 @@ public abstract class MediaEndpoint {
JsonArray jsonArray = new JsonArray(); JsonArray jsonArray = new JsonArray();
for (KmsEvent event : this.kmsEvents) { for (KmsEvent event : this.kmsEvents) {
JsonObject jsonKmsEvent = new JsonObject(); JsonObject jsonKmsEvent = JsonUtils.toJsonObject(event.event);
jsonKmsEvent.addProperty(event.event.getType(), event.timestamp); // Set source name
jsonKmsEvent.addProperty("source", event.endpoint);
// Set custom more precise timestamp
jsonKmsEvent.addProperty("timestamp", event.timestamp);
// Set milliseconds since the Publisher or Subscriber started transmitting media
jsonKmsEvent.addProperty("msSinceCreation", event.msSinceCreation);
jsonArray.add(jsonKmsEvent); jsonArray.add(jsonKmsEvent);
} }
json.add("events", jsonArray); json.add("events", jsonArray);

View File

@ -201,6 +201,7 @@ public class PublisherEndpoint extends MediaEndpoint {
throw new OpenViduException(Code.MEDIA_SDP_ERROR_CODE, "Sdp type not supported: " + sdpType); throw new OpenViduException(Code.MEDIA_SDP_ERROR_CODE, "Sdp type not supported: " + sdpType);
} }
gatherCandidates(); gatherCandidates();
this.createdAt = System.currentTimeMillis();
return sdpResponse; return sdpResponse;
} }
@ -580,7 +581,7 @@ public class PublisherEndpoint extends MediaEndpoint {
} }
public String filterCollectionsToString() { public String filterCollectionsToString() {
return "{filter: " + ((this.filter != null) ? this.filter.getName() : "null") + ", listener: " + this.filterListeners.toString() return "{filter: " + ((this.filter != null) ? this.filter.getName() : "null") + ", listener: "
+ ", subscribers: " + this.subscribersToFilterEvents.toString() + "}"; + this.filterListeners.toString() + ", subscribers: " + this.subscribersToFilterEvents.toString() + "}";
} }
} }

View File

@ -53,6 +53,7 @@ public class SubscriberEndpoint extends MediaEndpoint {
publisher.connect(this.getEndpoint()); publisher.connect(this.getEndpoint());
setConnectedToPublisher(true); setConnectedToPublisher(true);
setPublisher(publisher); setPublisher(publisher);
this.createdAt = System.currentTimeMillis();
return sdpAnswer; return sdpAnswer;
} }

View File

@ -35,7 +35,7 @@ import io.openvidu.server.config.OpenviduConfig;
public class ConfigRestController { public class ConfigRestController {
@Autowired @Autowired
OpenviduConfig openviduConfig; protected OpenviduConfig openviduConfig;
@RequestMapping(value = "/openvidu-publicurl", method = RequestMethod.GET) @RequestMapping(value = "/openvidu-publicurl", method = RequestMethod.GET)
public String getOpenViduPublicUrl() { public String getOpenViduPublicUrl() {