1 /*
2  * Copyright @ 2015 - Present, 8x8 Inc
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jitsi.videobridge.eventadmin.callstats;
17 
18 import org.jitsi.nlj.stats.*;
19 import org.jitsi.nlj.transform.node.incoming.*;
20 import org.jitsi.nlj.transform.node.outgoing.*;
21 import org.jitsi.stats.media.*;
22 import org.jitsi.videobridge.*;
23 
24 import java.util.*;
25 
26 /**
27  * Extends a {@link AbstractStatsPeriodicRunnable} which periodically generates
28  * a statistics for the conference channels.
29  *
30  * @author Damian Minkov
31  */
32 public class ConferencePeriodicRunnable
33     extends AbstractStatsPeriodicRunnable<Conference>
34 {
35     /**
36      * Constructs <tt>ConferencePeriodicRunnable</tt>.
37      * @param conference the conference.
38      * @param period the reporting interval.
39      * @param statsService the StatsService to use for reporting.
40      * @param conferenceIDPrefix prefix to use when creating conference IDs.
41      * @param initiatorID the id which identifies the current bridge.
42      */
ConferencePeriodicRunnable( Conference conference, long period, StatsService statsService, String conferenceIDPrefix, String initiatorID)43     ConferencePeriodicRunnable(
44         Conference conference,
45         long period,
46         StatsService statsService,
47         String conferenceIDPrefix,
48         String initiatorID)
49     {
50         super(conference,
51             period,
52             statsService,
53             conference.getName() == null
54                   ? "null" : conference.getName().toString(),
55             conferenceIDPrefix,
56             initiatorID);
57     }
58 
59     /**
60      * {@inheritDoc}
61      */
62     @Override
getEndpointStats()63     protected List<EndpointStats> getEndpointStats()
64     {
65         List<EndpointStats> allEndpointStats = new LinkedList<>();
66 
67         for (Endpoint endpoint : o.getLocalEndpoints())
68         {
69             String id = endpoint.getStatsId();
70             if (id == null)
71             {
72                 id = endpoint.getID();
73             }
74             EndpointStats endpointStats = new EndpointStats(id);
75 
76             TransceiverStats transceiverStats
77                     = endpoint.getTransceiver().getTransceiverStats();
78             int rttMs
79                     = (int) transceiverStats.getEndpointConnectionStats().getRtt();
80 
81             Map<Long, IncomingSsrcStats.Snapshot> incomingStats
82                     = transceiverStats.getIncomingStats().getSsrcStats();
83             incomingStats.forEach((ssrc, stats) ->
84             {
85                 SsrcStats receiveStats = new SsrcStats();
86                 receiveStats.ssrc = ssrc;
87                 receiveStats.bytes = stats.getNumReceivedBytes();
88                 receiveStats.packets = stats.getNumReceivedPackets();
89                 receiveStats.packetsLost = stats.getCumulativePacketsLost();
90                 receiveStats.rtt_ms = rttMs;
91                 // TODO: the incoming stats don't have the fractional packet
92                 //  loss, it has to be computed between snapshots.
93                 //receiveStats.fractionalPacketLoss = TODO;
94                 receiveStats.jitter_ms = stats.getJitter();
95                 endpointStats.addReceiveStats(receiveStats);
96             });
97 
98             Map<Long, OutgoingSsrcStats.Snapshot> outgoingStats
99                     = transceiverStats.getOutgoingStats().getSsrcStats();
100             outgoingStats.forEach((ssrc, stats) ->
101             {
102                 SsrcStats sendStats = new SsrcStats();
103                 sendStats.ssrc = ssrc;
104                 sendStats.bytes = stats.getOctetCount();
105                 sendStats.packets = stats.getPacketCount();
106                 // TODO: we don't keep track of outgoing loss per ssrc.
107                 //sendStats.packetsLost = TODO
108                 sendStats.rtt_ms = rttMs;
109                 // TODO: we don't keep track of outgoing loss per ssrc.
110                 //sendStats.fractionalPacketLoss = TODO
111                 // TODO: we don't keep track of outgoing loss per ssrc.
112                 //sendStats.jitter_ms = TODO
113                 endpointStats.addSendStats(sendStats);
114             });
115 
116             allEndpointStats.add(endpointStats);
117         }
118 
119         return allEndpointStats;
120     }
121 }
122