Skip to content

Commit

Permalink
feat: implement debug output for file and websocket (#352)
Browse files Browse the repository at this point in the history
  • Loading branch information
farhat-ha authored Apr 26, 2024
1 parent dcaa51e commit 8d1f8e6
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 19 deletions.
11 changes: 6 additions & 5 deletions packages/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,16 @@ const call = client.newCall({
// Destination is required and can be a phone number or SIP URI
destinationNumber: '18004377950',
callerNumber: '‬155531234567',
debug: true // Default is false,
debugOutput: 'socket' // Possible values are 'socket' | 'file'
});

// Start the gathering of data
call.startDebugger();

// Stop the gathering of data
call.stopDebugger();
// The debug dump is set to be sent to telnyx by default, if you want to save the debug data to disk
// You can change the debugOutput option to 'file'
```



---

## Examples
Expand Down
14 changes: 14 additions & 0 deletions packages/js/src/Modules/Verto/messages/WebRTCStatsMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import BaseMessage from './BaseMessage';
import { v4 } from 'uuid';
export class WebRTCStatsMessage extends BaseMessage {
constructor(data: any) {
super();
const reportId = v4();
this.buildRequest({
type: 'debug_final_report',
debug_final_report: btoa(JSON.stringify(data)),
debug_report_id: reportId,
});
console.log(`WebRTC Debug Report generated: ${reportId}`);
}
}
5 changes: 4 additions & 1 deletion packages/js/src/Modules/Verto/util/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ export interface IVertoOptions {
env?: Environment;
iceServers?: RTCIceServer[];
/**
* autoReconnect: Determine if the SDK has to re-connect automatically when detecting a gateway connection failure.
* autoReconnect: Determine if the SDK has to re-connect automatically when detecting a gateway connection failure.
* This is set to`true` as default
* @type {boolean}
*/
autoReconnect?: boolean;

debug?: boolean;
debugOutput?: 'socket' | 'file';
}
export interface SubscribeParams {
channels?: string[];
Expand Down
27 changes: 22 additions & 5 deletions packages/js/src/Modules/Verto/webrtc/BaseCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { MCULayoutEventHandler } from './LayoutHandler';
import Call from './Call';
import pkg from '../../../../package.json';
import { WebRTCStats } from '@peermetrics/webrtc-stats';
import { WebRTCStatsMessage } from '../messages/WebRTCStatsMessage';
const SDK_VERSION = pkg.version;

/**
Expand Down Expand Up @@ -296,7 +297,6 @@ export default abstract class BaseCall implements IWebRTCCall {
this.direction = Direction.Outbound;
this.peer = new Peer(PeerType.Offer, this.options);
await this.peer.iceGatheringComplete.promise;
console.log('icegatheringcompleted')
this._onIceSdp(this.peer.instance.localDescription);
}

Expand Down Expand Up @@ -374,12 +374,30 @@ export default abstract class BaseCall implements IWebRTCCall {
this.setState(State.Hangup);

const _close = () => {
this.peer ? this.peer.instance.close() : null;
this.setState(State.Destroy);
const debugData = this.peer?.close();
if (!debugData) {
return this.setState(State.Destroy);
}
if (this.options.debugOutput === 'socket') {
this._execute(new WebRTCStatsMessage(debugData));
}
if (this.options.debugOutput === 'file') {
// Save to file
const blob = new Blob([JSON.stringify(debugData)], {
type: 'application/json',
});
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = `call_${this.options.id}.json`;
link.click();
URL.revokeObjectURL(downloadUrl);
}
return this.setState(State.Destroy);
};

this.stopRingtone();
this.stopDebugger();
this.stopDebugger();
if (execute) {
const bye = new Bye({
sessid: this.session.sessionid,
Expand Down Expand Up @@ -1470,7 +1488,6 @@ export default abstract class BaseCall implements IWebRTCCall {
this.hangup();
});
console.timeEnd(TIME_CALL_INVITE);

}

private _onIce(event: RTCPeerConnectionIceEvent) {
Expand Down
41 changes: 33 additions & 8 deletions packages/js/src/Modules/Verto/webrtc/Peer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,18 @@ import {
RTCPeerConnection,
streamIsValid,
} from '../util/webrtc';
import {
DeferredPromise,
deferredPromise,
isFunction,
} from '../util/helpers';
import { DeferredPromise, deferredPromise, isFunction } from '../util/helpers';
import { IVertoCallOptions } from './interfaces';
import { trigger } from '../services/Handler';

import { WebRTCStats } from '@peermetrics/webrtc-stats';
/**
* @ignore Hide in docs output
*/
export default class Peer {
public instance: RTCPeerConnection;
public iceGatheringComplete: DeferredPromise<boolean>;
public onSdpReadyTwice: Function = null;

private _webrtcStats: WebRTCStats;
private _constraints: {
offerToReceiveAudio: boolean;
offerToReceiveVideo: boolean;
Expand All @@ -56,6 +52,18 @@ export default class Peer {
this.createPeerConnection = this.createPeerConnection.bind(this);
this.iceGatheringComplete = deferredPromise({ debounceTime: 100 });

if (this.options.debug) {
this._webrtcStats = new WebRTCStats({
getStatsInterval: 1000,
rawStats: false,
statsObject: false,
filteredStats: false,
remote: true,
wrapGetUserMedia: true,
debug: false,
logLevel: 'warn',
});
}
this._init();
}

Expand Down Expand Up @@ -144,7 +152,13 @@ export default class Peer {
};
private async createPeerConnection() {
this.instance = RTCPeerConnection(this._config());

if (this.options.debug) {
this._webrtcStats?.addConnection({
pc: this.instance,
peerId: this.options.id,
connectionId: this.options.id,
});
}
this.instance.onsignalingstatechange = this.handleSignalingStateChangeEvent;
this.instance.onnegotiationneeded = this.handleNegotiationNeededEvent;
this.instance.ontrack = this.handleTrackEvent;
Expand Down Expand Up @@ -233,6 +247,7 @@ export default class Peer {
} else {
this.startNegotiation();
}

this._logTransceivers();
}

Expand Down Expand Up @@ -386,4 +401,14 @@ export default class Peer {
logger.info('RTC config', config);
return config;
}

public close() {
let data = null;
if (this._webrtcStats) {
data = this._webrtcStats.getTimeline('stats');
this._webrtcStats.destroy();
}
this.instance.close();
return data;
}
}
2 changes: 2 additions & 0 deletions packages/js/src/Modules/Verto/webrtc/VertoHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class VertoHandler {
callerNumber: params.callee_id_number,
attach,
mediaSettings: params.mediaSettings,
debug: session.options.debug ?? false,
debugOutput: session.options.debugOutput ?? 'socket',
};

if (params.telnyx_call_control_id) {
Expand Down
2 changes: 2 additions & 0 deletions packages/js/src/Modules/Verto/webrtc/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export const DEFAULT_CALL_OPTIONS: IVertoCallOptions = {
audio: true,
video: false,
useStereo: false,
debug: false,
debugOutput: 'socket',
attach: false,
screenShare: false,
userVariables: {},
Expand Down
2 changes: 2 additions & 0 deletions packages/js/src/Modules/Verto/webrtc/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export interface IVertoCallOptions {
negotiateVideo?: boolean;
mediaSettings?: IMediaSettings;
customHeaders?: Array<{ name: string; value: string }>;
debug?: boolean;
debugOutput?: 'socket' | 'file';
}

export interface IStatsBinding {
Expand Down

0 comments on commit 8d1f8e6

Please sign in to comment.