Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
675 lines (603 sloc) 26.5 KB

Detailed session monitoring


OpenVidu Pro brings the power of Elastic Stack. Events and monitoring stats are sent to Elasticsearch and can be visualized through Kibana.

OpenVidu Sessions dahsboard

This dashboard presents a summary of your video sessions and the server resources usage. That includes:

  • CPU and memory usage of the server
  • The number of session per day
  • The location of your users
  • The number of publishers and subscribers you have at any time
  • The total streamed minutes over time
  • Some low-level interesting stats related to the media connections

The last point includes things like the average time to select a pair candidate during the negotiation process, the average milliseconds your clients take to complete the ICE gathering process with OpenVidu Server, the ratio of successful and failed connections, and some WebRTC stats for your published and subscribed streams (Jitter, packet loss, Round-Trip-Time, target bitrate...)

All in all, this information will help you understand better the behavior and performance of your sessions.



OpenVidu Recordings dahsboard

This dashboard presents at a glance the status of your recordings. It includes information such as:

  • The total number of recordings per day
  • Average duration and size of your recorded files
  • The distributions of you recordings by duration and size
  • The ratio of recordings according to their output mode (COMPOSED{:target="_blank"} or INDIVIDUAL{:target="_blank"} recordings) and their recorded tracks (audio/video recordings{:target="_blank"})


Accessing Kibana

OpenVidu Pro serves Kibana through path /kibana. So, if you have deployed OpenVidu Pro with domain my.domain.com, you will be able to access OpenVidu Inspector through https://my.domain.com/inspector and Kibana through https://my.domain.com/kibana

This path is secured with Basic Auth, so when connecting to it for the first time you will have to enter the user and password specified when deploying OpenVidu Pro.



Creating your own visualizations and dashboards

The dashboards presented above, by default included in OpenVidu Pro, are just an example of what can be done thanks to Kibana. You can create your own visualizations, and set up your very own dashboards with them. To do so, you have available multiple events that OpenVidu Pro periodically stores in Elasticsearch, and you can then use them in Kibana to compose different types of graphs and other useful visual representations.

Each one of these events stored by OpenVidu Pro in Elasticsearch has an elastic_type field to identify the specific type of event. This field may be:

2.9.0 / 2.10.0 / 2.11.0
  • cdr: event of Call Detail Record. Can take multiple forms according to the type of event (see OpenVidu CDR{:target="_blank"})
  • kms: Kurento Media Server event. These events are always associated to one WebRTC endpoint (a publisher or a subscriber). Can take multiple forms according to the type of event (see Kurento docs{:target="_blank"})
  • monitoringStats: event of CPU, memory and network statistics usage of OpenVidu Pro host
  • webrtcStats: event of WebRTC statistics for each media endpoint established in Kurento Media Server
  • sessionSummary: summary of a session, stored once it is closed
  • recordingSummary: summary of a recording, stored once its session is closed
  • userSummary: summary of a user, stored once its session is closed
  • connectionSummary: summary of a connection, stored once its session is closed
  • publisherSummary: summary of a publisher, stored once its session is closed
  • subscriberSummary: summary of a subscriber, stored once its session is closed
cdr kms monitoringStats webrtcStats sessionSummary recordingSummary userSummary connectionSummary publisherSummary subscriberSummary
```json { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191848252, "startTime": 1554191765889, "duration": 82, "reason": "lastParticipantLeft", "event": "sessionDestroyed", "elastic_type": "cdr" } ```
```json { "streamId": 1, "componentId": 1, "state": "READY", "type": "IceComponentStateChange", "timestamp": 1554191839098, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "ewztvkfl8dttvcxk", "endpoint": "ewztvkfl8dttvcxk_bahnv2b0n5fxbohy_CAMERA_XHIHV", "msSinceEndpointCreation": 11104, "elastic_type": "kms" } ```
```json { "timestamp": 1554212258873, "cpu": 11.887875624741168, "mem": { "used": 7287344, "percentage": 45.13347034796033 }, "net": { "veth2b4c47c": { "rxBytes": 0, "txBytes": 0 }, "wlp58s0": { "rxBytes": 0, "txBytes": 0 } }, "elastic_type": "monitoringStats" } ```
```json { "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "bahnv2b0n5fxbohy", "endpoint": "bahnv2b0n5fxbohy_CAMERA_XHIHV", "mediaType": "video", "jitter": 0.005244444590061903, "bytesReceived": 6455233, "packetsReceived": 6666, "packetsLost": 0, "timestamp": 1554191847505, "fractionLost": 0, "remb": 533208, "firCount": 6, "pliCount": 0, "nackCount": 0, "sliCount": 0, "elastic_type": "webrtcStats" } ```
```json { "createdAt": 1554191765889, "destroyedAt": 1554191848252, "sessionId": "weih6kaewklr4i05", "customSessionId": "", "mediaMode": "ROUTED", "recordingMode": "MANUAL", "duration": 82, "reason": "lastParticipantLeft", "users": { "numberOfElements": 1, "content": [ { "id": "6596FB7B9D1A7C25", "location": "Mumbai, India", "platform": "Chrome 72.0.3626.109 on Linux 64-bit", "connections": { "numberOfElements": 1, "content": [ { "createdAt": 1554191765994, "destroyedAt": 1554191848249, "connectionId": "bahnv2b0n5fxbohy", "clientData": "", "serverData": "", "duration": 82, "reason": "disconnect", "publishers": { "numberOfElements": 1, "content": [ { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191848247, "startTime": 1554191767577, "duration": 80, "reason": "disconnect", "streamId": "bahnv2b0n5fxbohy_CAMERA_XHIHV", "videoSource": "CAMERA", "videoFramerate": -1, "videoDimensions": "{\"width\":640,\"height\":480}", "audioEnabled": true, "videoEnabled": true, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "bahnv2b0n5fxbohy", "elastic_type": "publisherSummary" } ] }, "subscribers": { "numberOfElements": 0, "content": [] }, "geoPoints": "19.09,72.87", "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "timestamp": 1554191848252, "elastic_type": "connectionSummary" } ] }, "session": "weih6kaewklr4i05", "timestamp": 1554191848252, "elastic_type": "userSummary" } ] }, "recordings": { "numberOfElements": 1, "content": [ { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191784531, "startTime": 1554191770662, "duration": 9.734, "reason": "recordingStoppedByServer", "id": "weih6kaewklr4i05", "name": "RecordingTest", "outputMode": "COMPOSED", "resolution": "1920x1080", "recordingLayout": "BEST_FIT", "hasAudio": true, "hasVideo": true, "size": 1968384, "elastic_type": "recordingSummary" } ] } } ```
```json { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191784531, "startTime": 1554191770662, "duration": 9.734, "reason": "recordingStoppedByServer", "id": "weih6kaewklr4i05", "name": "RecordingTest", "outputMode": "COMPOSED", "resolution": "1920x1080", "recordingLayout": "BEST_FIT", "hasAudio": true, "hasVideo": true, "size": 1968384, "elastic_type": "recordingSummary" } ```
```json { "id": "6596FB7B9D1A7C25", "location": "Mumbai, India", "platform": "Chrome 72.0.3626.109 on Linux 64-bit", "connections": { "numberOfElements": 1, "content": [ { "createdAt": 1554191765994, "destroyedAt": 1554191848249, "connectionId": "bahnv2b0n5fxbohy", "clientData": "", "serverData": "", "duration": 82, "reason": "disconnect", "publishers": { "numberOfElements": 1, "content": [ { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191848247, "startTime": 1554191767577, "duration": 80, "reason": "disconnect", "streamId": "bahnv2b0n5fxbohy_CAMERA_XHIHV", "videoSource": "CAMERA", "videoFramerate": -1, "videoDimensions": "{\"width\":640,\"height\":480}", "audioEnabled": true, "videoEnabled": true, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "bahnv2b0n5fxbohy", "elastic_type": "publisherSummary" } ] }, "subscribers": { "numberOfElements": 0, "content": [] }, "geoPoints": "19.09,72.87", "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "timestamp": 1554191848252, "elastic_type": "connectionSummary" } ] }, "session": "weih6kaewklr4i05", "timestamp": 1554191848252, "elastic_type": "userSummary" } ```
```json { "createdAt": 1554191765994, "destroyedAt": 1554191848249, "connectionId": "bahnv2b0n5fxbohy", "clientData": "", "serverData": "", "duration": 82, "reason": "disconnect", "publishers": { "numberOfElements": 1, "content": [ { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191848247, "startTime": 1554191767577, "duration": 80, "reason": "disconnect", "streamId": "bahnv2b0n5fxbohy_CAMERA_XHIHV", "videoSource": "CAMERA", "videoFramerate": -1, "videoDimensions": "{\"width\":640,\"height\":480}", "audioEnabled": true, "videoEnabled": true, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "bahnv2b0n5fxbohy", "elastic_type": "publisherSummary" } ] }, "subscribers": { "numberOfElements": 0, "content": [] }, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "timestamp": 1554191848252, "elastic_type": "connectionSummary" } ```
```json { "sessionId": "weih6kaewklr4i05", "timestamp": 1554191848247, "startTime": 1554191767577, "duration": 80, "reason": "disconnect", "streamId": "bahnv2b0n5fxbohy_CAMERA_XHIHV", "videoSource": "CAMERA", "videoFramerate": -1, "videoDimensions": "{\"width\":640,\"height\":480}", "audioEnabled": true, "videoEnabled": true, "session": "weih6kaewklr4i05", "user": "6596FB7B9D1A7C25", "connection": "bahnv2b0n5fxbohy", "elastic_type": "publisherSummary" } ```
```json { "sessionId": "weih6kaewklr4i05", "timestamp": 1553694100398, "startTime": 1553693956035, "duration": 144, "reason": "disconnect", "streamId": "dbslbhe2jzhhybvj_CAMERA_CSBVI", "receivingFrom": "dbslbhe2jzhhybvj", "videoSource": "CAMERA", "videoFramerate": 30, "videoDimensions": "{\"width\":640,\"height\":480}", "audioEnabled": true, "videoEnabled": true, "session": "TestSession", "user": "A06BB386A40BBC83", "connection": "c1tgrtyzlmeix6l3", "elastic_type": "subscriberSummary" } ```
cdr kms monitoringStats webrtcStats sessionSummary recordingSummary userSummary connectionSummary publisherSummary subscriberSummary
```json ```
```json ```
```json ```
```json ```
```json ```
```json ```
```json ```
```json ```
```json ```
```json ```

NOTE 1: sessionSummary contains all the information available in the rest of summary documents, including an array of recordingSummary and an array of userSummary. In turn userSummary contains an array of connectionSummary, that finally contains an array of publisherSummary and other of subscriberSummary. To sum up, this is just a denormalization of the sessionSummary document, so Elasticsearch requests and Kibana visualizations are more flexible and easier to accomplish

NOTE 2: recordingSummary events may not contain the final information of the actual recordings (specifically properties size and duration). This is so because recordingSummary event is generated just after its session is closed, but since release 2.11.0 recordings may need a post-processing phase before being available for download and having these properties properly defined. To overcome this limitation, you can simply use the cdr event of type recordingStatusChanged and status ready corresponding to this recording (see event in CDR docs{:target="_blank"}). There you will have all properties of the recording well defined


You can create powerful visualizations and dashboards by using these documents. Let's see a quick example. Imagine that you are interested in knowing how many users are connected to your OpenVidu sessions over time.

First thing is navigating to Visualize section in Kibana and clicking on the button to add a new visualization

Then we have to choose a visualization type. In this case a vertical bar graph might be a pretty good choice

We select openvidu index, because that's the index of every OpenVidu Pro event stored in Elasticsearch

The visualization page will be shown. Now we have to filter the desired events. In this case, we just want the userSummary event, as it gathers all the information about the final users connecting to our sessions. So, we make sure that field elastic_type.keyword is userSummary

Finally we have to configure the data passed to our graph. The metric we want (Y-axis) is simply Count, because there is one "userSummary" event for each final user connecting to a session. And as Bucket (X-axis) we configure a Date Histogram by using timestamp field of the event

To store the new visualization just click on Save button in the upper menu and give it a meaningful name

The example above is a very simple visualization, but you can apply any metric to any property (or set of properties) of any event (or set of events). You can explore pre-existing visualizations included by default in OpenVidu Pro, and for further info visit Kibana docs{:target="_blank"}


<script> function changeVersion(event) { var parent = event.target.parentNode.parentNode; var txt = event.target.getAttribute('title'); var txt = txt.replace(/\./g, ''); for (var i = 0; i < parent.children.length; i++) { var child = parent.children[i]; // Change appearance of version buttons if (child.classList.contains('version-buttons')) { for (var j = 0; j < child.children.length; j++) { var a = child.children[j]; if (a === event.target) { a.classList.add('pressed-btn'); } else { a.classList.remove('pressed-btn'); } } } // Change visibility of version content if (child.classList.contains('version-container')) { if (child.id === ('list-' + txt) || child.id === ('content-' + txt)) { child.style.display = 'block'; } else { child.style.display = 'none'; } } } } </script> <script> function changeLangTab(event) { var parent = event.target.parentNode.parentNode; var txt = event.target.textContent || event.target.innerText; var txt = txt.replace(/\s/g, "-").toLowerCase(); for (var i = 0; i < parent.children.length; i++) { var child = parent.children[i]; // Change appearance of language buttons if (child.classList.contains('lang-tabs-header')) { for (var j = 0; j < child.children.length; j++) { var btn = child.children[j]; if (btn.classList.contains('lang-tabs-btn')) { btn.style.backgroundColor = btn === event.target ? '#e8e8e8' : '#f9f9f9'; btn.style.fontWeight = btn === event.target ? 'bold' : 'normal'; } } } // Change visibility of language content if (child.classList.contains('lang-tabs-content')) { if (child.id === txt) { child.style.display = 'block'; } else { child.style.display = 'none'; } } } } </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.20/jquery.fancybox.min.js"></script> <script> $().fancybox({ selector : '[data-fancybox]', infobar : true, arrows : false, loop: true, protect: true, transitionEffect: 'slide', buttons : [ 'close' ], clickOutside : 'close', clickSlide : 'close', }); </script> <script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script> <script> $('.slick-captions').slick({ asNavFor: '.pro-gallery-steps', arrows: false, infinite: false, speed: 200, fade: true, dots: false }); $('.pro-gallery-steps').slick({ asNavFor: '.slick-captions', autoplay: false, arrows: true, prevArrow: '
', nextArrow: '
', infinite: false, dots: true, responsive: [ { breakpoint: 768, settings: { arrows: true, slidesToShow: 1 } }, ] }); </script>
You can’t perform that action at this time.