瀏覽代碼

feat: Adds more debug information in the GSM bars popover (#7627)

master
George Politis 5 年之前
父節點
當前提交
b5310573fc
No account linked to committer's email address

+ 3
- 13
conference.js 查看文件

@@ -108,6 +108,7 @@ import {
108 108
     getBackendSafePath,
109 109
     getJitsiMeetGlobalNS
110 110
 } from './react/features/base/util';
111
+import { downloadJSON } from './react/features/base/util/downloadJSON';
111 112
 import { showDesktopPicker } from './react/features/desktop-picker';
112 113
 import { appendSuffix } from './react/features/display-name';
113 114
 import {
@@ -1221,19 +1222,8 @@ export default {
1221 1222
         // this can be called from console and will not have reference to this
1222 1223
         // that's why we reference the global var
1223 1224
         const logs = APP.connection.getLogs();
1224
-        const data = encodeURIComponent(JSON.stringify(logs, null, '  '));
1225
-
1226
-        const elem = document.createElement('a');
1227
-
1228
-        elem.download = filename;
1229
-        elem.href = `data:application/json;charset=utf-8,\n${data}`;
1230
-        elem.dataset.downloadurl
1231
-            = [ 'text/json', elem.download, elem.href ].join(':');
1232
-        elem.dispatchEvent(new MouseEvent('click', {
1233
-            view: window,
1234
-            bubbles: true,
1235
-            cancelable: false
1236
-        }));
1225
+
1226
+        downloadJSON(logs, filename);
1237 1227
     },
1238 1228
 
1239 1229
     /**

+ 1
- 3
css/_connection-info.scss 查看文件

@@ -45,10 +45,8 @@
45 45
         @extend .connection-info__icon;
46 46
     }
47 47
 
48
-    .showmore {
49
-        display: block;
48
+    .connection-actions {
50 49
         margin: 10px auto;
51 50
         text-align: center;
52
-        width: 90px;
53 51
     }
54 52
 }

+ 5
- 1
lang/main.json 查看文件

@@ -99,6 +99,7 @@
99 99
     },
100 100
     "connectionindicator": {
101 101
         "address": "Address:",
102
+        "audio_ssrc": "Audio SSRC:",
102 103
         "bandwidth": "Estimated bandwidth:",
103 104
         "bitrate": "Bitrate:",
104 105
         "bridgeCount": "Server count: ",
@@ -126,9 +127,12 @@
126 127
         "remoteport": "Remote port:",
127 128
         "remoteport_plural": "Remote ports:",
128 129
         "resolution": "Resolution:",
130
+        "savelogs": "Save logs",
131
+        "participant_id": "Participant id:",
129 132
         "status": "Connection:",
130 133
         "transport": "Transport:",
131
-        "transport_plural": "Transports:"
134
+        "transport_plural": "Transports:",
135
+        "video_ssrc": "Video SSRC:"
132 136
     },
133 137
     "dateUtils": {
134 138
         "earlier": "Earlier",

+ 23
- 0
react/features/base/util/downloadJSON.js 查看文件

@@ -0,0 +1,23 @@
1
+// @flow
2
+
3
+/**
4
+ * Downloads a JSON object.
5
+ *
6
+ * @param {Object} json - The JSON object to download.
7
+ * @param {string} filename - The filename to give to the downloaded file.
8
+ * @returns {void}
9
+ */
10
+export function downloadJSON(json: Object, filename: string) {
11
+    const data = encodeURIComponent(JSON.stringify(json, null, '  '));
12
+
13
+    const elem = document.createElement('a');
14
+
15
+    elem.download = filename;
16
+    elem.href = `data:application/json;charset=utf-8,\n${data}`;
17
+    elem.dataset.downloadurl = [ 'text/json', elem.download, elem.href ].join(':');
18
+    elem.dispatchEvent(new MouseEvent('click', {
19
+        view: window,
20
+        bubbles: true,
21
+        cancelable: false
22
+    }));
23
+}

+ 18
- 0
react/features/connection-indicator/actions.js 查看文件

@@ -0,0 +1,18 @@
1
+import getRoomName from '../base/config/getRoomName';
2
+import { downloadJSON } from '../base/util/downloadJSON';
3
+
4
+
5
+/**
6
+ * Create an action for saving the conference logs.
7
+ *
8
+ * @returns {Function}
9
+ */
10
+export function saveLogs() {
11
+    return (dispatch, getState) => {
12
+
13
+        const logs = getState()['features/base/connection'].connection.getLogs();
14
+        const roomName = getRoomName() || '';
15
+
16
+        downloadJSON(logs, `meetlog-${roomName}.json`);
17
+    };
18
+}

+ 77
- 3
react/features/connection-indicator/components/web/ConnectionIndicator.js 查看文件

@@ -1,12 +1,17 @@
1 1
 // @flow
2 2
 
3 3
 import React from 'react';
4
+import type { Dispatch } from 'redux';
4 5
 
5 6
 import { translate } from '../../../base/i18n';
6 7
 import { Icon, IconConnectionActive, IconConnectionInactive } from '../../../base/icons';
7 8
 import { JitsiParticipantConnectionStatus } from '../../../base/lib-jitsi-meet';
9
+import { MEDIA_TYPE } from '../../../base/media';
8 10
 import { Popover } from '../../../base/popover';
11
+import { connect } from '../../../base/redux';
12
+import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
9 13
 import { ConnectionStatsTable } from '../../../connection-stats';
14
+import { saveLogs } from '../../actions';
10 15
 import AbstractConnectionIndicator, {
11 16
     INDICATOR_DISPLAY_THRESHOLD,
12 17
     type Props as AbstractProps,
@@ -62,12 +67,22 @@ type Props = AbstractProps & {
62 67
      */
63 68
     alwaysVisible: boolean,
64 69
 
70
+    /**
71
+     * The audio SSRC of this client.
72
+     */
73
+    audioSsrc: number,
74
+
65 75
     /**
66 76
      * The current condition of the user's connection, matching one of the
67 77
      * enumerated values in the library.
68 78
      */
69 79
     connectionStatus: string,
70 80
 
81
+    /**
82
+     * The Redux dispatch function.
83
+     */
84
+    dispatch: Dispatch<any>,
85
+
71 86
     /**
72 87
      * Whether or not clicking the indicator should display a popover for more
73 88
      * details.
@@ -93,7 +108,17 @@ type Props = AbstractProps & {
93 108
     /**
94 109
      * Invoked to obtain translated strings.
95 110
      */
96
-    t: Function
111
+    t: Function,
112
+
113
+    /**
114
+     * The video SSRC of this client.
115
+     */
116
+    videoSsrc: number,
117
+
118
+    /**
119
+     * Invoked to save the conference logs.
120
+     */
121
+    _onSaveLogs: Function
97 122
 };
98 123
 
99 124
 /**
@@ -353,6 +378,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
353 378
 
354 379
         return (
355 380
             <ConnectionStatsTable
381
+                audioSsrc = { this.props.audioSsrc }
356 382
                 bandwidth = { bandwidth }
357 383
                 bitrate = { bitrate }
358 384
                 bridgeCount = { bridgeCount }
@@ -362,15 +388,63 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
362 388
                 framerate = { framerate }
363 389
                 isLocalVideo = { this.props.isLocalVideo }
364 390
                 maxEnabledResolution = { maxEnabledResolution }
391
+                onSaveLogs = { this.props._onSaveLogs }
365 392
                 onShowMore = { this._onToggleShowMore }
366 393
                 packetLoss = { packetLoss }
394
+                participantId = { this.props.participantId }
367 395
                 region = { region }
368 396
                 resolution = { resolution }
369 397
                 serverRegion = { serverRegion }
370 398
                 shouldShowMore = { this.state.showMoreStats }
371
-                transport = { transport } />
399
+                transport = { transport }
400
+                videoSsrc = { this.props.videoSsrc } />
372 401
         );
373 402
     }
374 403
 }
375 404
 
376
-export default translate(ConnectionIndicator);
405
+
406
+/**
407
+ * Maps redux actions to the props of the component.
408
+ *
409
+ * @param {Function} dispatch - The redux action {@code dispatch} function.
410
+ * @returns {{
411
+ *     _onSaveLogs: Function,
412
+ * }}
413
+ * @private
414
+ */
415
+export function _mapDispatchToProps(dispatch: Dispatch<any>) {
416
+    return {
417
+        /**
418
+         * Saves the conference logs.
419
+         *
420
+         * @returns {Function}
421
+         */
422
+        _onSaveLogs() {
423
+            dispatch(saveLogs());
424
+        }
425
+    };
426
+}
427
+
428
+
429
+/**
430
+ * Maps part of the Redux state to the props of this component.
431
+ *
432
+ * @param {Object} state - The Redux state.
433
+ * @param {Props} ownProps - The own props of the component.
434
+ * @returns {Props}
435
+ */
436
+export function _mapStateToProps(state: Object, ownProps: Props) {
437
+
438
+    const firstVideoTrack = getTrackByMediaTypeAndParticipant(
439
+        state['features/base/tracks'], MEDIA_TYPE.VIDEO, ownProps.participantId);
440
+    const firstAudioTrack = getTrackByMediaTypeAndParticipant(
441
+        state['features/base/tracks'], MEDIA_TYPE.AUDIO, ownProps.participantId);
442
+
443
+    return {
444
+        audioSsrc: firstAudioTrack
445
+            ? state['features/base/conference'].conference.getSsrcByTrack(firstAudioTrack.jitsiTrack) : undefined,
446
+        videoSsrc: firstVideoTrack
447
+            ? state['features/base/conference'].conference.getSsrcByTrack(firstVideoTrack.jitsiTrack) : undefined
448
+    };
449
+}
450
+export default translate(connect(_mapStateToProps, _mapDispatchToProps)(ConnectionIndicator));

+ 113
- 6
react/features/connection-stats/components/ConnectionStatsTable.js 查看文件

@@ -10,6 +10,11 @@ import { translate } from '../../base/i18n';
10 10
  */
11 11
 type Props = {
12 12
 
13
+    /**
14
+     * The audio SSRC of this client.
15
+     */
16
+    audioSsrc: number,
17
+
13 18
     /**
14 19
      * Statistics related to bandwidth.
15 20
      * {{
@@ -49,6 +54,11 @@ type Props = {
49 54
      */
50 55
     e2eRtt: number,
51 56
 
57
+    /**
58
+     * The endpoint id of this client.
59
+     */
60
+    participantId: string,
61
+
52 62
     /**
53 63
      * Statistics related to frame rates for each ssrc.
54 64
      * {{
@@ -68,6 +78,11 @@ type Props = {
68 78
      */
69 79
     maxEnabledResolution: number,
70 80
 
81
+    /**
82
+     * Callback to invoke when the user clicks on the download logs link.
83
+     */
84
+    onSaveLogs: Function,
85
+
71 86
     /**
72 87
      * Callback to invoke when the show additional stats link is clicked.
73 88
      */
@@ -114,6 +129,11 @@ type Props = {
114 129
      */
115 130
     t: Function,
116 131
 
132
+    /**
133
+     * The video SSRC of this client.
134
+     */
135
+    videoSsrc: number,
136
+
117 137
     /**
118 138
      * Statistics related to transports.
119 139
      */
@@ -138,9 +158,11 @@ class ConnectionStatsTable extends Component<Props> {
138 158
         return (
139 159
             <div className = 'connection-info'>
140 160
                 { this._renderStatistics() }
141
-                { isLocalVideo ? this._renderShowMoreLink() : null }
142
-                { isLocalVideo && this.props.shouldShowMore
143
-                    ? this._renderAdditionalStats() : null }
161
+                <div className = 'connection-actions'>
162
+                    { isLocalVideo ? this._renderSaveLogs() : null}
163
+                    { this._renderShowMoreLink() }
164
+                </div>
165
+                { this.props.shouldShowMore ? this._renderAdditionalStats() : null }
144 166
             </div>
145 167
         );
146 168
     }
@@ -153,12 +175,17 @@ class ConnectionStatsTable extends Component<Props> {
153 175
      * @returns {ReactElement}
154 176
      */
155 177
     _renderAdditionalStats() {
178
+        const { isLocalVideo } = this.props;
179
+
156 180
         return (
157 181
             <table className = 'connection-info__container'>
158 182
                 <tbody>
159
-                    { this._renderBandwidth() }
160
-                    { this._renderTransport() }
161
-                    { this._renderRegion() }
183
+                    { isLocalVideo ? this._renderBandwidth() : null }
184
+                    { isLocalVideo ? this._renderTransport() : null }
185
+                    { isLocalVideo ? this._renderRegion() : null }
186
+                    { this._renderAudioSsrc() }
187
+                    { this._renderVideoSsrc() }
188
+                    { this._renderParticipantId() }
162 189
                 </tbody>
163 190
             </table>
164 191
         );
@@ -224,6 +251,66 @@ class ConnectionStatsTable extends Component<Props> {
224 251
         );
225 252
     }
226 253
 
254
+    /**
255
+     * Creates a table row as a ReactElement for displaying the audio ssrc.
256
+     * This will typically be something like "Audio SSRC: 12345".
257
+     *
258
+     * @returns {JSX.Element}
259
+     * @private
260
+     */
261
+    _renderAudioSsrc() {
262
+        const { audioSsrc, t } = this.props;
263
+
264
+        return (
265
+            <tr>
266
+                <td>
267
+                    <span>{ t('connectionindicator.audio_ssrc') }</span>
268
+                </td>
269
+                <td>{ audioSsrc || 'N/A' }</td>
270
+            </tr>
271
+        );
272
+    }
273
+
274
+    /**
275
+     * Creates a table row as a ReactElement for displaying the video ssrc.
276
+     * This will typically be something like "Video SSRC: 12345".
277
+     *
278
+     * @returns {JSX.Element}
279
+     * @private
280
+     */
281
+    _renderVideoSsrc() {
282
+        const { videoSsrc, t } = this.props;
283
+
284
+        return (
285
+            <tr>
286
+                <td>
287
+                    <span>{ t('connectionindicator.video_ssrc') }</span>
288
+                </td>
289
+                <td>{ videoSsrc || 'N/A' }</td>
290
+            </tr>
291
+        );
292
+    }
293
+
294
+    /**
295
+     * Creates a table row as a ReactElement for displaying the endpoint id.
296
+     * This will typically be something like "Endpoint id: 1e8fbg".
297
+     *
298
+     * @returns {JSX.Element}
299
+     * @private
300
+     */
301
+    _renderParticipantId() {
302
+        const { participantId, t } = this.props;
303
+
304
+        return (
305
+            <tr>
306
+                <td>
307
+                    <span>{ t('connectionindicator.participant_id') }</span>
308
+                </td>
309
+                <td>{ participantId || 'N/A' }</td>
310
+            </tr>
311
+        );
312
+    }
313
+
227 314
     /**
228 315
      * Creates a a table row as a ReactElement for displaying codec, if present.
229 316
      * This will typically be something like "Codecs (A/V): Opus, vp8".
@@ -455,6 +542,26 @@ class ConnectionStatsTable extends Component<Props> {
455 542
         );
456 543
     }
457 544
 
545
+    /**
546
+     * Creates a ReactElement for display a link to save the logs.
547
+     *
548
+     * @private
549
+     * @returns {ReactElement}
550
+     */
551
+    _renderSaveLogs() {
552
+        return (
553
+            <span>
554
+                <a
555
+                    className = 'savelogs link'
556
+                    onClick = { this.props.onSaveLogs } >
557
+                    { this.props.t('connectionindicator.savelogs') }
558
+                </a>
559
+                <span> | </span>
560
+            </span>
561
+        );
562
+    }
563
+
564
+
458 565
     /**
459 566
      * Creates a ReactElement for display a link to toggle showing additional
460 567
      * statistics.

Loading…
取消
儲存