@stream-io/video-client 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/index.browser.es.js +227 -125
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +229 -124
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.es.js +227 -125
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/src/Call.d.ts +2 -1
  10. package/dist/src/StreamSfuClient.d.ts +1 -0
  11. package/dist/src/StreamVideoClient.d.ts +5 -1
  12. package/dist/src/coordinator/connection/types.d.ts +3 -2
  13. package/dist/src/coordinator/connection/utils.d.ts +2 -1
  14. package/dist/src/logger.d.ts +4 -0
  15. package/dist/src/rtc/Dispatcher.d.ts +2 -0
  16. package/dist/src/rtc/IceTrickleBuffer.d.ts +2 -0
  17. package/dist/src/rtc/publisher.d.ts +1 -0
  18. package/dist/src/store/CallState.d.ts +2 -0
  19. package/index.ts +1 -0
  20. package/package.json +1 -1
  21. package/src/Call.ts +61 -40
  22. package/src/StreamSfuClient.ts +70 -29
  23. package/src/StreamVideoClient.ts +46 -3
  24. package/src/coordinator/connection/client.ts +22 -29
  25. package/src/coordinator/connection/connection.ts +2 -3
  26. package/src/coordinator/connection/connection_fallback.ts +0 -1
  27. package/src/coordinator/connection/types.ts +4 -2
  28. package/src/coordinator/connection/utils.ts +5 -2
  29. package/src/devices/devices.ts +10 -3
  30. package/src/events/call.ts +11 -4
  31. package/src/events/sessions.ts +7 -2
  32. package/src/logger.ts +45 -0
  33. package/src/rtc/Dispatcher.ts +14 -4
  34. package/src/rtc/IceTrickleBuffer.ts +8 -1
  35. package/src/rtc/codecs.ts +7 -5
  36. package/src/rtc/flows/join.ts +4 -1
  37. package/src/rtc/publisher.ts +31 -12
  38. package/src/rtc/signal.ts +8 -7
  39. package/src/rtc/subscriber.ts +16 -10
  40. package/src/stats/state-store-stats-reporter.ts +9 -3
  41. package/src/store/CallState.ts +6 -1
  42. package/src/types.ts +1 -0
@@ -5273,13 +5273,41 @@ const toggleDtx = (sdp, enable) => {
5273
5273
  return sdp;
5274
5274
  };
5275
5275
 
5276
+ let logger;
5277
+ const logToConsole = (logLevel, message, extraData, tags) => {
5278
+ let logMethod;
5279
+ if (logLevel === 'error') {
5280
+ logMethod = console.error;
5281
+ }
5282
+ else if (logLevel === 'warn') {
5283
+ logMethod = console.warn;
5284
+ }
5285
+ else {
5286
+ logMethod = console.log;
5287
+ }
5288
+ logMethod(logLevel, `${tags === null || tags === void 0 ? void 0 : tags.join(':')} - ${message}`, extraData ? extraData : '');
5289
+ };
5290
+ const setLogger = (l) => {
5291
+ logger = l;
5292
+ };
5293
+ const getLogger = (withTags) => {
5294
+ const loggerMethod = logger || (() => { });
5295
+ const result = (logLevel, messeage, extraData, tags) => {
5296
+ loggerMethod(logLevel, messeage, extraData, [
5297
+ ...(tags || []),
5298
+ ...(withTags || []),
5299
+ ]);
5300
+ };
5301
+ return result;
5302
+ };
5303
+
5276
5304
  const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5305
+ const logger = getLogger(['codecs']);
5277
5306
  if (!('getCapabilities' in RTCRtpSender)) {
5278
- console.warn('RTCRtpSender.getCapabilities is not supported');
5307
+ logger === null || logger === void 0 ? void 0 : logger('warn', 'RTCRtpSender.getCapabilities is not supported');
5279
5308
  return;
5280
5309
  }
5281
5310
  const cap = RTCRtpSender.getCapabilities(kind);
5282
- console.log('s4e');
5283
5311
  if (!cap)
5284
5312
  return;
5285
5313
  const matched = [];
@@ -5287,7 +5315,7 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5287
5315
  const unmatched = [];
5288
5316
  cap.codecs.forEach((c) => {
5289
5317
  const codec = c.mimeType.toLowerCase();
5290
- console.log(c);
5318
+ logger === null || logger === void 0 ? void 0 : logger('debug', `Found supported codec: ${codec}`);
5291
5319
  const shouldRemoveCodec = codecToRemove && codec === `${kind}/${codecToRemove}`;
5292
5320
  if (shouldRemoveCodec)
5293
5321
  return;
@@ -5307,10 +5335,11 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5307
5335
  }
5308
5336
  return;
5309
5337
  }
5310
- console.log('matched', matched);
5311
5338
  matched.push(c);
5312
5339
  });
5313
- return [...matched, ...partialMatched, ...unmatched];
5340
+ const result = [...matched, ...partialMatched, ...unmatched];
5341
+ logger === null || logger === void 0 ? void 0 : logger('info', `Preffered codecs: `, result);
5342
+ return result;
5314
5343
  };
5315
5344
  const getGenericSdp = (direction, isRedEnabled, preferredVideoCodec) => __awaiter(void 0, void 0, void 0, function* () {
5316
5345
  var _a;
@@ -5376,17 +5405,19 @@ class Dispatcher {
5376
5405
  constructor() {
5377
5406
  this.subscribers = {};
5378
5407
  this.dispatch = (message) => {
5408
+ var _a, _b;
5379
5409
  const eventKind = message.eventPayload.oneofKind;
5380
5410
  if (eventKind) {
5381
- // @ts-ignore
5382
- console.log(`Dispatching`, eventKind, message.eventPayload[eventKind]);
5411
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Dispatching ${eventKind}`);
5412
+ (_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'debug', `Event payload`, message.eventPayload[eventKind]);
5383
5413
  const listeners = this.subscribers[eventKind];
5384
5414
  listeners === null || listeners === void 0 ? void 0 : listeners.forEach((fn) => {
5415
+ var _a;
5385
5416
  try {
5386
5417
  fn(message);
5387
5418
  }
5388
5419
  catch (e) {
5389
- console.warn(`Listener failed with error`, e);
5420
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', 'Listener failed with error', e);
5390
5421
  }
5391
5422
  });
5392
5423
  }
@@ -5410,6 +5441,7 @@ class Dispatcher {
5410
5441
  this.subscribers = {};
5411
5442
  }
5412
5443
  };
5444
+ this.logger = getLogger(['sfu-client']);
5413
5445
  }
5414
5446
  }
5415
5447
 
@@ -5422,6 +5454,7 @@ class IceTrickleBuffer {
5422
5454
  this.subscriberCandidates = new ReplaySubject();
5423
5455
  this.publisherCandidates = new ReplaySubject();
5424
5456
  this.push = (iceTrickle) => {
5457
+ var _a;
5425
5458
  if (iceTrickle.peerType === PeerType.SUBSCRIBER) {
5426
5459
  this.subscriberCandidates.next(iceTrickle);
5427
5460
  }
@@ -5429,9 +5462,10 @@ class IceTrickleBuffer {
5429
5462
  this.publisherCandidates.next(iceTrickle);
5430
5463
  }
5431
5464
  else {
5432
- console.warn(`ICETrickle, Unknown peer type`, iceTrickle);
5465
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', `ICETrickle, Unknown peer type`, iceTrickle);
5433
5466
  }
5434
5467
  };
5468
+ this.logger = getLogger(['sfu-client']);
5435
5469
  }
5436
5470
  }
5437
5471
 
@@ -5622,6 +5656,7 @@ class Publisher {
5622
5656
  * @param opts
5623
5657
  */
5624
5658
  this.publishStream = (mediaStream, track, trackType, opts = {}) => __awaiter(this, void 0, void 0, function* () {
5659
+ var _a;
5625
5660
  let transceiver = this.publisher
5626
5661
  .getTransceivers()
5627
5662
  .find((t) => {
@@ -5635,7 +5670,8 @@ class Publisher {
5635
5670
  * Once the track has ended, it will notify the SFU and update the state.
5636
5671
  */
5637
5672
  const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
5638
- console.log(`Track ${TrackType[trackType]} has ended, notifying the SFU`);
5673
+ var _b;
5674
+ (_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
5639
5675
  yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
5640
5676
  // clean-up, this event listener needs to run only once.
5641
5677
  track.removeEventListener('ended', handleTrackEnded);
@@ -5660,7 +5696,7 @@ class Publisher {
5660
5696
  });
5661
5697
  this.transceiverRegistry[trackType] = transceiver;
5662
5698
  if ('setCodecPreferences' in transceiver && codecPreferences) {
5663
- console.log(`Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
5699
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
5664
5700
  transceiver.setCodecPreferences(codecPreferences);
5665
5701
  }
5666
5702
  }
@@ -5744,9 +5780,9 @@ class Publisher {
5744
5780
  this.publisher.close();
5745
5781
  };
5746
5782
  this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
5747
- var _a;
5748
- console.log('Update publish quality, requested rids by SFU:', enabledRids);
5749
- const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
5783
+ var _c, _d, _e, _f;
5784
+ (_c = this.logger) === null || _c === void 0 ? void 0 : _c.call(this, 'info', 'Update publish quality, requested rids by SFU:', enabledRids);
5785
+ const videoSender = (_d = this.transceiverRegistry[TrackType.VIDEO]) === null || _d === void 0 ? void 0 : _d.sender;
5750
5786
  if (!videoSender)
5751
5787
  return;
5752
5788
  const params = videoSender.getParameters();
@@ -5761,10 +5797,10 @@ class Publisher {
5761
5797
  });
5762
5798
  if (changed) {
5763
5799
  if (params.encodings.length === 0) {
5764
- console.warn('No suitable video encoding quality found');
5800
+ (_e = this.logger) === null || _e === void 0 ? void 0 : _e.call(this, 'warn', 'No suitable video encoding quality found');
5765
5801
  }
5766
5802
  yield videoSender.setParameters(params);
5767
- console.log(`Update publish quality, enabled rids: ${params.encodings
5803
+ (_f = this.logger) === null || _f === void 0 ? void 0 : _f.call(this, 'info', `Update publish quality, enabled rids: ${params.encodings
5768
5804
  .filter((e) => e.active)
5769
5805
  .map((e) => e.rid)
5770
5806
  .join(', ')}`);
@@ -5781,9 +5817,10 @@ class Publisher {
5781
5817
  }
5782
5818
  };
5783
5819
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
5820
+ var _g;
5784
5821
  const { candidate } = e;
5785
5822
  if (!candidate) {
5786
- console.log('null ice candidate');
5823
+ (_g = this.logger) === null || _g === void 0 ? void 0 : _g.call(this, 'warn', 'null ice candidate');
5787
5824
  return;
5788
5825
  }
5789
5826
  yield this.sfuClient.iceTrickle({
@@ -5792,7 +5829,8 @@ class Publisher {
5792
5829
  });
5793
5830
  });
5794
5831
  this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
5795
- console.log('AAA onNegotiationNeeded');
5832
+ var _h, _j;
5833
+ (_h = this.logger) === null || _h === void 0 ? void 0 : _h.call(this, 'info', 'AAA onNegotiationNeeded');
5796
5834
  const offer = yield this.publisher.createOffer();
5797
5835
  let sdp = offer.sdp;
5798
5836
  if (sdp) {
@@ -5855,28 +5893,38 @@ class Publisher {
5855
5893
  });
5856
5894
  }
5857
5895
  catch (e) {
5858
- console.error(`Publisher: setRemoteDescription error`, response.sdp, e);
5896
+ (_j = this.logger) === null || _j === void 0 ? void 0 : _j.call(this, 'error', `Publisher: setRemoteDescription error`, {
5897
+ sdp: response.sdp,
5898
+ error: e,
5899
+ });
5859
5900
  }
5860
5901
  this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
5902
+ var _k;
5861
5903
  try {
5862
5904
  const iceCandidate = JSON.parse(candidate.iceCandidate);
5863
5905
  yield this.publisher.addIceCandidate(iceCandidate);
5864
5906
  }
5865
5907
  catch (e) {
5866
- console.error(`Publisher: ICE candidate error`, e, candidate);
5908
+ (_k = this.logger) === null || _k === void 0 ? void 0 : _k.call(this, 'error', `Publisher: ICE candidate error`, {
5909
+ error: e,
5910
+ candidate,
5911
+ });
5867
5912
  }
5868
5913
  }));
5869
5914
  });
5870
5915
  this.onIceCandidateError = (e) => {
5916
+ var _a;
5871
5917
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
5872
5918
  `${e.errorCode}: ${e.errorText}`;
5873
- console.error(`Publisher: ICE Candidate error`, errorMessage);
5919
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Candidate error`, errorMessage);
5874
5920
  };
5875
5921
  this.onIceConnectionStateChange = () => {
5876
- console.log(`Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
5922
+ var _a;
5923
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
5877
5924
  };
5878
5925
  this.onIceGatheringStateChange = () => {
5879
- console.log(`Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
5926
+ var _a;
5927
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
5880
5928
  };
5881
5929
  this.ridToVideoQuality = (rid) => {
5882
5930
  return rid === 'q'
@@ -5909,12 +5957,13 @@ class Publisher {
5909
5957
  }
5910
5958
 
5911
5959
  const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, }) => {
5960
+ const logger = getLogger(['sfu-client']);
5912
5961
  const subscriber = new RTCPeerConnection(connectionConfig);
5913
5962
  attachDebugEventListeners(subscriber);
5914
5963
  subscriber.addEventListener('icecandidate', (e) => __awaiter(void 0, void 0, void 0, function* () {
5915
5964
  const { candidate } = e;
5916
5965
  if (!candidate) {
5917
- console.log('null ice candidate');
5966
+ logger === null || logger === void 0 ? void 0 : logger('warn', 'null ice candidate');
5918
5967
  return;
5919
5968
  }
5920
5969
  yield sfuClient.iceTrickle({
@@ -5930,7 +5979,7 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5930
5979
  if (message.eventPayload.oneofKind !== 'subscriberOffer')
5931
5980
  return;
5932
5981
  const { subscriberOffer } = message.eventPayload;
5933
- console.log(`Received subscriberOffer`, subscriberOffer);
5982
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Received subscriberOffer', subscriberOffer);
5934
5983
  yield subscriber.setRemoteDescription({
5935
5984
  type: 'offer',
5936
5985
  sdp: subscriberOffer.sdp,
@@ -5941,7 +5990,10 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5941
5990
  yield subscriber.addIceCandidate(iceCandidate);
5942
5991
  }
5943
5992
  catch (e) {
5944
- console.error(`Subscriber: ICE candidate error`, e, candidate);
5993
+ logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE candidate error`, {
5994
+ error: e,
5995
+ candidate,
5996
+ });
5945
5997
  }
5946
5998
  }));
5947
5999
  // apply ice candidates
@@ -5964,31 +6016,33 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5964
6016
  return subscriber;
5965
6017
  };
5966
6018
  const attachDebugEventListeners = (subscriber) => {
6019
+ const logger = getLogger(['sfu-client']);
5967
6020
  subscriber.addEventListener('icecandidateerror', (e) => {
5968
6021
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
5969
6022
  `${e.errorCode}: ${e.errorText}`;
5970
- console.error(`Subscriber: ICE Candidate error`, errorMessage);
6023
+ logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE Candidate error: ${errorMessage}`);
5971
6024
  });
5972
6025
  subscriber.addEventListener('iceconnectionstatechange', () => {
5973
- console.log(`Subscriber: ICE Connection state changed`, subscriber.iceConnectionState);
6026
+ logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Connection state changed: ${subscriber.iceConnectionState}`);
5974
6027
  });
5975
6028
  subscriber.addEventListener('icegatheringstatechange', () => {
5976
- console.log(`Subscriber: ICE Gathering State`, subscriber.iceGatheringState);
6029
+ logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Gathering State: ${subscriber.iceGatheringState}`);
5977
6030
  });
5978
6031
  };
5979
6032
 
5980
6033
  const createWebSocketSignalChannel = (opts) => {
6034
+ const logger = getLogger(['sfu-client']);
5981
6035
  const { endpoint, onMessage } = opts;
5982
6036
  const ws = new WebSocket(endpoint);
5983
6037
  ws.binaryType = 'arraybuffer'; // do we need this?
5984
6038
  ws.addEventListener('error', (e) => {
5985
- console.log('Signaling WS channel error', e);
6039
+ logger === null || logger === void 0 ? void 0 : logger('error', 'Signaling WS channel error', e);
5986
6040
  });
5987
6041
  ws.addEventListener('close', (e) => {
5988
- console.log('Signaling WS channel is closed', e);
6042
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is closed', e);
5989
6043
  });
5990
6044
  ws.addEventListener('open', (e) => {
5991
- console.log('Signaling WS channel is open', e);
6045
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is open', e);
5992
6046
  });
5993
6047
  if (onMessage) {
5994
6048
  ws.addEventListener('message', (e) => {
@@ -5999,7 +6053,7 @@ const createWebSocketSignalChannel = (opts) => {
5999
6053
  onMessage(message);
6000
6054
  }
6001
6055
  catch (err) {
6002
- console.error('Failed to decode a message. Check whether the Proto models match.', e.data, e, err);
6056
+ logger === null || logger === void 0 ? void 0 : logger('error', 'Failed to decode a message. Check whether the Proto models match.', { event: e, error: err });
6003
6057
  }
6004
6058
  });
6005
6059
  }
@@ -6100,14 +6154,14 @@ function convertErrorToJson(err) {
6100
6154
  * isOnline safely return the navigator.online value for browser env
6101
6155
  * if navigator is not in global object, it always return true
6102
6156
  */
6103
- function isOnline() {
6157
+ function isOnline(logger) {
6104
6158
  const nav = typeof navigator !== 'undefined'
6105
6159
  ? navigator
6106
6160
  : typeof window !== 'undefined' && window.navigator
6107
6161
  ? window.navigator
6108
6162
  : undefined;
6109
6163
  if (!nav) {
6110
- console.warn('isOnline failed to access window.navigator and assume browser is online');
6164
+ logger('warn', 'isOnline failed to access window.navigator and assume browser is online');
6111
6165
  return true;
6112
6166
  }
6113
6167
  // RN navigator has undefined for onLine
@@ -6163,16 +6217,16 @@ class StreamSfuClient {
6163
6217
  return retryable(() => this.rpc.updateSubscriptions({
6164
6218
  sessionId: this.sessionId,
6165
6219
  tracks: subscriptions,
6166
- }));
6220
+ }), this.logger);
6167
6221
  });
6168
6222
  this.setPublisher = (data) => __awaiter(this, void 0, void 0, function* () {
6169
- return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6223
+ return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6170
6224
  });
6171
6225
  this.sendAnswer = (data) => __awaiter(this, void 0, void 0, function* () {
6172
- return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6226
+ return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6173
6227
  });
6174
6228
  this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
6175
- return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6229
+ return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6176
6230
  });
6177
6231
  this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
6178
6232
  return this.updateMuteStates({
@@ -6185,7 +6239,7 @@ class StreamSfuClient {
6185
6239
  });
6186
6240
  });
6187
6241
  this.updateMuteStates = (data) => __awaiter(this, void 0, void 0, function* () {
6188
- return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6242
+ return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6189
6243
  });
6190
6244
  this.join = (data) => __awaiter(this, void 0, void 0, function* () {
6191
6245
  const joinRequest = JoinRequest.create(Object.assign(Object.assign({}, data), { sessionId: this.sessionId, token: this.token }));
@@ -6206,7 +6260,7 @@ class StreamSfuClient {
6206
6260
  clearInterval(this.keepAliveInterval);
6207
6261
  }
6208
6262
  this.keepAliveInterval = setInterval(() => {
6209
- console.log('Sending healthCheckRequest to SFU');
6263
+ this.logger('info', 'Sending healthCheckRequest to SFU');
6210
6264
  const message = SfuRequest.create({
6211
6265
  requestPayload: {
6212
6266
  oneofKind: 'healthCheckRequest',
@@ -6224,7 +6278,7 @@ class StreamSfuClient {
6224
6278
  if (this.lastMessageTimestamp) {
6225
6279
  const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
6226
6280
  if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
6227
- console.log('SFU connection unhealthy, closing');
6281
+ this.logger('error', 'SFU connection unhealthy, closing');
6228
6282
  this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
6229
6283
  }
6230
6284
  }
@@ -6232,12 +6286,22 @@ class StreamSfuClient {
6232
6286
  };
6233
6287
  this.sessionId = sessionId || generateUUIDv4();
6234
6288
  this.token = token;
6289
+ this.logger = getLogger(['sfu-client']);
6290
+ const logger = this.logger;
6291
+ const logInterceptor = {
6292
+ interceptUnary(next, method, input, options) {
6293
+ logger('info', `Calling SFU RPC method ${method.name}`);
6294
+ logger('debug', `Method call payload`, { input, options });
6295
+ return next(method, input, options);
6296
+ },
6297
+ };
6235
6298
  this.rpc = createSignalClient({
6236
6299
  baseUrl: url,
6237
6300
  interceptors: [
6238
6301
  withHeaders({
6239
6302
  Authorization: `Bearer ${token}`,
6240
6303
  }),
6304
+ logInterceptor,
6241
6305
  ],
6242
6306
  });
6243
6307
  // Special handling for the ICETrickle kind of events.
@@ -6279,7 +6343,7 @@ const MAX_RETRIES = 5;
6279
6343
  * @param <I> the type of the request object.
6280
6344
  * @param <O> the type of the response object.
6281
6345
  */
6282
- const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
6346
+ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* () {
6283
6347
  var _a;
6284
6348
  let retryAttempt = 0;
6285
6349
  let rpcCallResult;
@@ -6289,9 +6353,11 @@ const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
6289
6353
  yield sleep(retryInterval(retryAttempt));
6290
6354
  }
6291
6355
  rpcCallResult = yield rpc();
6356
+ logger('info', `SFU RPC response received for ${rpcCallResult.method.name}`);
6357
+ logger('debug', `Response payload`, rpcCallResult);
6292
6358
  // if the RPC call failed, log the error and retry
6293
6359
  if (rpcCallResult.response.error) {
6294
- console.error('SFU Error:', rpcCallResult.response.error);
6360
+ logger('error', 'SFU RPC Error:', rpcCallResult.response.error);
6295
6361
  }
6296
6362
  retryAttempt++;
6297
6363
  } while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
@@ -6974,7 +7040,7 @@ class CallState {
6974
7040
  this.updateParticipant = (sessionId, patch) => {
6975
7041
  const participant = this.findParticipantBySessionId(sessionId);
6976
7042
  if (!participant) {
6977
- console.warn(`Participant with sessionId ${sessionId} not found`);
7043
+ this.logger('warn', `Participant with sessionId ${sessionId} not found`);
6978
7044
  return;
6979
7045
  }
6980
7046
  const thePatch = typeof patch === 'function' ? patch(participant) : patch;
@@ -7023,6 +7089,7 @@ class CallState {
7023
7089
  return p;
7024
7090
  }));
7025
7091
  };
7092
+ this.logger = getLogger(['call-state']);
7026
7093
  this.participants$ = this.participantsSubject.pipe(map$1((ps) => ps.sort(this.sortParticipantsBy)));
7027
7094
  this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find(isStreamVideoLocalParticipant)));
7028
7095
  this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)));
@@ -7179,13 +7246,13 @@ const watchCallRejected = (call) => {
7179
7246
  const { call: eventCall } = event;
7180
7247
  const { session: callSession } = eventCall;
7181
7248
  if (!callSession) {
7182
- console.log('No call session provided. Ignoring call.rejected event.');
7249
+ call.logger('warn', 'No call session provided. Ignoring call.rejected event.', event);
7183
7250
  return;
7184
7251
  }
7185
7252
  const rejectedBy = callSession.rejected_by;
7186
7253
  const { members, callingState } = call.state;
7187
7254
  if (callingState !== CallingState.RINGING) {
7188
- console.log('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.');
7255
+ call.logger('warn', 'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
7189
7256
  return;
7190
7257
  }
7191
7258
  if (call.isCreatedByMe) {
@@ -7193,13 +7260,13 @@ const watchCallRejected = (call) => {
7193
7260
  .filter((m) => m.user_id !== call.currentUserId)
7194
7261
  .every((m) => rejectedBy[m.user_id]);
7195
7262
  if (everyoneElseRejected) {
7196
- console.log('everyone rejected, leaving the call');
7263
+ call.logger('info', 'everyone rejected, leaving the call');
7197
7264
  yield call.leave();
7198
7265
  }
7199
7266
  }
7200
7267
  else {
7201
7268
  if (rejectedBy[eventCall.created_by.id]) {
7202
- console.log('call creator rejected, leaving call');
7269
+ call.logger('info', 'call creator rejected, leaving call');
7203
7270
  yield call.leave();
7204
7271
  }
7205
7272
  }
@@ -7607,7 +7674,7 @@ const watchCallSessionParticipantJoined = (state) => {
7607
7674
  const { user } = event;
7608
7675
  state.setMetadata((metadata) => {
7609
7676
  if (!metadata || !metadata.session) {
7610
- console.warn(`Received call.session_participant_joined event but the metadata structure is invalid.`);
7677
+ state.logger('warn', `Received call.session_participant_joined event but the metadata structure is invalid.`, event);
7611
7678
  return metadata;
7612
7679
  }
7613
7680
  const { session } = metadata;
@@ -7635,7 +7702,7 @@ const watchCallSessionParticipantLeft = (state) => {
7635
7702
  const { user } = event;
7636
7703
  state.setMetadata((metadata) => {
7637
7704
  if (!metadata || !metadata.session) {
7638
- console.warn(`Received call.session_participant_left event but the metadata structure is invalid.`);
7705
+ state.logger('warn', `Received call.session_participant_left event but the metadata structure is invalid.`, event);
7639
7706
  return metadata;
7640
7707
  }
7641
7708
  const { session } = metadata;
@@ -7780,16 +7847,18 @@ const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
7780
7847
  const hintURL = `https://hint.stream-io-video.com/`;
7781
7848
  const abortController = new AbortController();
7782
7849
  const timeoutId = setTimeout(() => abortController.abort(), 1000);
7850
+ const logger = getLogger(['call']);
7783
7851
  try {
7784
7852
  const response = yield fetch(hintURL, {
7785
7853
  method: 'HEAD',
7786
7854
  signal: abortController.signal,
7787
7855
  });
7788
7856
  const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
7857
+ logger === null || logger === void 0 ? void 0 : logger('info', `Location header: ${awsPop}`);
7789
7858
  return awsPop.substring(0, 3); // AMS1-P2 -> AMS
7790
7859
  }
7791
7860
  catch (e) {
7792
- console.error(`Failed to get location hint from ${hintURL}`, e);
7861
+ logger === null || logger === void 0 ? void 0 : logger('error', `Failed to get location hint from ${hintURL}`, e);
7793
7862
  return 'ERR';
7794
7863
  }
7795
7864
  finally {
@@ -7828,6 +7897,7 @@ const getCascadingModeParams = () => {
7828
7897
  * Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
7829
7898
  */
7830
7899
  const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIntervalInMs = 2000, }) => {
7900
+ const logger = getLogger(['stats']);
7831
7901
  const getRawStatsForTrack = (kind, selector) => __awaiter(void 0, void 0, void 0, function* () {
7832
7902
  if (kind === 'subscriber' && subscriber) {
7833
7903
  return subscriber.getStats(selector);
@@ -7836,7 +7906,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7836
7906
  return publisher.getStats(selector);
7837
7907
  }
7838
7908
  else {
7839
- console.warn(`Can't retrieve RTC stats for`, kind);
7909
+ logger('warn', `Can't retrieve RTC stats for ${kind}`);
7840
7910
  return undefined;
7841
7911
  }
7842
7912
  });
@@ -7888,7 +7958,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7888
7958
  });
7889
7959
  }
7890
7960
  catch (e) {
7891
- console.error(`Failed to collect stats for ${kind}`, participant, e);
7961
+ logger('error', `Failed to collect stats for ${kind} if ${participant.userId}`, e);
7892
7962
  }
7893
7963
  }
7894
7964
  }
@@ -7926,7 +7996,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7926
7996
  if (pollingIntervalInMs > 0) {
7927
7997
  const loop = () => __awaiter(void 0, void 0, void 0, function* () {
7928
7998
  yield run().catch((e) => {
7929
- console.log('Failed to collect stats', e);
7999
+ logger('warn', 'Failed to collect stats', e);
7930
8000
  });
7931
8001
  timeoutId = setTimeout(loop, pollingIntervalInMs);
7932
8002
  });
@@ -8527,7 +8597,7 @@ class Call {
8527
8597
  */
8528
8598
  const rejoin = () => __awaiter(this, void 0, void 0, function* () {
8529
8599
  var _g, _h, _j;
8530
- console.log(`Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
8600
+ this.logger('debug', `Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
8531
8601
  this.reconnectAttempts++;
8532
8602
  this.state.setCallingState(CallingState.RECONNECTING);
8533
8603
  // take a snapshot of the current "local participant" state
@@ -8539,7 +8609,7 @@ class Call {
8539
8609
  sfuClient.close(); // clean up previous connection
8540
8610
  yield sleep(retryInterval(this.reconnectAttempts));
8541
8611
  yield this.join(data);
8542
- console.log(`Rejoin: ${this.reconnectAttempts} successful!`);
8612
+ this.logger('info', `Rejoin: ${this.reconnectAttempts} successful!`);
8543
8613
  if (localParticipant && !isReactNative()) {
8544
8614
  const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
8545
8615
  // restore previous publishing state
@@ -8550,7 +8620,7 @@ class Call {
8550
8620
  if (screenShare)
8551
8621
  yield this.publishScreenShareStream(screenShare);
8552
8622
  }
8553
- console.log(`Rejoin: state restored ${this.reconnectAttempts}`);
8623
+ this.logger('info', `Rejoin: state restored ${this.reconnectAttempts}`);
8554
8624
  });
8555
8625
  this.rejoinPromise = rejoin;
8556
8626
  // reconnect if the connection was closed unexpectedly. example:
@@ -8570,12 +8640,12 @@ class Call {
8570
8640
  return;
8571
8641
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
8572
8642
  rejoin().catch(() => {
8573
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8643
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8574
8644
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8575
8645
  });
8576
8646
  }
8577
8647
  else {
8578
- console.log('Reconnect attempts exceeded. Giving up...');
8648
+ this.logger('error', 'Reconnect attempts exceeded. Giving up...');
8579
8649
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8580
8650
  }
8581
8651
  });
@@ -8585,15 +8655,15 @@ class Call {
8585
8655
  if (typeof window !== 'undefined' && window.addEventListener) {
8586
8656
  const handleOnOffline = () => {
8587
8657
  window.removeEventListener('offline', handleOnOffline);
8588
- console.log('Join: Going offline...');
8658
+ this.logger('warn', 'Join: Going offline...');
8589
8659
  this.state.setCallingState(CallingState.OFFLINE);
8590
8660
  };
8591
8661
  const handleOnOnline = () => {
8592
8662
  window.removeEventListener('online', handleOnOnline);
8593
8663
  if (this.state.callingState === CallingState.OFFLINE) {
8594
- console.log('Join: Going online...');
8664
+ this.logger('info', 'Join: Going online...');
8595
8665
  rejoin().catch(() => {
8596
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8666
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8597
8667
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8598
8668
  });
8599
8669
  }
@@ -8650,15 +8720,20 @@ class Call {
8650
8720
  clientDetails.sdk = getSdkInfo();
8651
8721
  // 1. wait for the signal server to be ready before sending "joinRequest"
8652
8722
  sfuClient.signalReady
8653
- .catch((err) => console.warn('Signal ready failed', err))
8723
+ .catch((err) => this.logger('error', 'Signal ready failed', err))
8654
8724
  // prepare a generic SDP and send it to the SFU.
8655
8725
  // this is a throw-away SDP that the SFU will use to determine
8656
8726
  // the capabilities of the client (codec support, etc.)
8657
8727
  .then(() => getGenericSdp('recvonly', isRedEnabled, this.streamClient.options.preferredVideoCodec))
8658
- .then((sdp) => sfuClient.join({
8659
- subscriberSdp: sdp || '',
8660
- clientDetails,
8661
- }));
8728
+ .then((sdp) => {
8729
+ const joinRequest = {
8730
+ subscriberSdp: sdp || '',
8731
+ clientDetails,
8732
+ };
8733
+ this.logger('info', 'Sending join request to SFU');
8734
+ this.logger('debug', 'Join request payload', joinRequest);
8735
+ sfuClient.join(joinRequest);
8736
+ });
8662
8737
  // 2. in parallel, wait for the SFU to send us the "joinResponse"
8663
8738
  // this will throw an error if the SFU rejects the join request or
8664
8739
  // fails to respond in time
@@ -8674,16 +8749,16 @@ class Call {
8674
8749
  this.state.setStartedAt(startedAt);
8675
8750
  this.reconnectAttempts = 0; // reset the reconnect attempts counter
8676
8751
  this.state.setCallingState(CallingState.JOINED);
8677
- console.log(`Joined call ${this.cid}`);
8752
+ this.logger('info', `Joined call ${this.cid}`);
8678
8753
  }
8679
8754
  catch (err) {
8680
8755
  // join failed, try to rejoin
8681
8756
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
8682
8757
  yield rejoin();
8683
- console.log(`Rejoin ${this.reconnectAttempts} successful!`);
8758
+ this.logger('info', `Rejoin ${this.reconnectAttempts} successful!`);
8684
8759
  }
8685
8760
  else {
8686
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8761
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8687
8762
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8688
8763
  throw new Error('Join failed');
8689
8764
  }
@@ -8708,7 +8783,8 @@ class Call {
8708
8783
  }
8709
8784
  const [videoTrack] = videoStream.getVideoTracks();
8710
8785
  if (!videoTrack) {
8711
- return console.error(`There is no video track in the stream.`);
8786
+ this.logger('error', `There is no video track to publish in the stream.`);
8787
+ return;
8712
8788
  }
8713
8789
  yield this.publisher.publishStream(videoStream, videoTrack, TrackType.VIDEO, opts);
8714
8790
  });
@@ -8731,7 +8807,8 @@ class Call {
8731
8807
  }
8732
8808
  const [audioTrack] = audioStream.getAudioTracks();
8733
8809
  if (!audioTrack) {
8734
- return console.error(`There is no audio track in the stream`);
8810
+ this.logger('error', `There is no audio track in the stream to publish`);
8811
+ return;
8735
8812
  }
8736
8813
  yield this.publisher.publishStream(audioStream, audioTrack, TrackType.AUDIO);
8737
8814
  });
@@ -8753,7 +8830,8 @@ class Call {
8753
8830
  }
8754
8831
  const [screenShareTrack] = screenShareStream.getVideoTracks();
8755
8832
  if (!screenShareTrack) {
8756
- return console.error(`There is no video track in the stream`);
8833
+ this.logger('error', `There is no video track in the screen share stream to publish`);
8834
+ return;
8757
8835
  }
8758
8836
  yield this.publisher.publishStream(screenShareStream, screenShareTrack, TrackType.SCREEN_SHARE);
8759
8837
  });
@@ -8768,7 +8846,7 @@ class Call {
8768
8846
  */
8769
8847
  this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
8770
8848
  var _k;
8771
- console.log(`stopPublish`, TrackType[trackType]);
8849
+ this.logger('info', `stopPublish ${TrackType[trackType]}`);
8772
8850
  yield ((_k = this.publisher) === null || _k === void 0 ? void 0 : _k.unpublishStream(trackType));
8773
8851
  });
8774
8852
  /**
@@ -8917,20 +8995,21 @@ class Call {
8917
8995
  const [primaryStream] = e.streams;
8918
8996
  // example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
8919
8997
  const [trackId, trackType] = primaryStream.id.split(':');
8920
- console.log(`Got remote ${trackType} track:`, e.track);
8998
+ this.logger('info', `Got remote ${trackType} track:`);
8999
+ this.logger('debug', `Track: `, e.track);
8921
9000
  const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
8922
9001
  if (!participantToUpdate) {
8923
- console.error('Received track for unknown participant', trackId, e);
9002
+ this.logger('error', `'Received track for unknown participant: ${trackId}'`, e);
8924
9003
  return;
8925
9004
  }
8926
9005
  e.track.addEventListener('mute', () => {
8927
- console.log(`Track muted:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9006
+ this.logger('info', `Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8928
9007
  });
8929
9008
  e.track.addEventListener('unmute', () => {
8930
- console.log(`Track unmuted:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9009
+ this.logger('info', `Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8931
9010
  });
8932
9011
  e.track.addEventListener('ended', () => {
8933
- console.log(`Track ended:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9012
+ this.logger('info', `Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8934
9013
  });
8935
9014
  const streamKindProp = {
8936
9015
  TRACK_TYPE_AUDIO: 'audioStream',
@@ -8938,12 +9017,12 @@ class Call {
8938
9017
  TRACK_TYPE_SCREEN_SHARE: 'screenShareStream',
8939
9018
  }[trackType];
8940
9019
  if (!streamKindProp) {
8941
- console.error('Unknown track type', trackType);
9020
+ this.logger('error', `Unknown track type: ${trackType}`);
8942
9021
  return;
8943
9022
  }
8944
9023
  const previousStream = participantToUpdate[streamKindProp];
8945
9024
  if (previousStream) {
8946
- console.log(`Cleaning up previous remote tracks`, e.track.kind);
9025
+ this.logger('info', `Cleaning up previous remote tracks: ${e.track.kind}`);
8947
9026
  previousStream.getTracks().forEach((t) => {
8948
9027
  t.stop();
8949
9028
  previousStream.removeTrack(t);
@@ -9243,6 +9322,7 @@ class Call {
9243
9322
  this.streamClient = streamClient;
9244
9323
  this.clientStore = clientStore;
9245
9324
  this.streamClientBasePath = `/call/${this.type}/${this.id}`;
9325
+ this.logger = getLogger(['call']);
9246
9326
  const callTypeConfig = CallTypes.get(type);
9247
9327
  const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
9248
9328
  if (participantSorter) {
@@ -9280,7 +9360,7 @@ class Call {
9280
9360
  const hasPermission = this.permissionsContext.hasPermission(permission);
9281
9361
  if (!hasPermission && this.publisher.isPublishing(trackType)) {
9282
9362
  this.stopPublish(trackType).catch((err) => {
9283
- console.error('Error stopping publish', trackType, err);
9363
+ this.logger('error', `Error stopping publish ${trackType}`, err);
9284
9364
  });
9285
9365
  }
9286
9366
  }
@@ -9501,12 +9581,12 @@ class StableWSConnection {
9501
9581
  return;
9502
9582
  const user = this.client.user;
9503
9583
  if (!user) {
9504
- console.error(`User not set, can't connect to WS`);
9584
+ this.client.logger('error', `User not set, can't connect to WS`);
9505
9585
  return;
9506
9586
  }
9507
9587
  const token = this.client._getToken();
9508
9588
  if (!token) {
9509
- console.error(`Token not set, can't connect authenticate`);
9589
+ this.client.logger('error', `Token not set, can't connect authenticate`);
9510
9590
  return;
9511
9591
  }
9512
9592
  const authMessage = {
@@ -9739,7 +9819,7 @@ class StableWSConnection {
9739
9819
  addConnectionEventListeners(this.onlineStatusChanged);
9740
9820
  }
9741
9821
  _log(msg, extra = {}, level = 'info') {
9742
- this.client.logger(level, 'connection:' + msg, Object.assign({ tags: ['connection'] }, extra));
9822
+ this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
9743
9823
  }
9744
9824
  /**
9745
9825
  * connect - Connect to the WS URL
@@ -10456,7 +10536,7 @@ class WSConnectionFallback {
10456
10536
  addConnectionEventListeners(this._onlineStatusChanged);
10457
10537
  }
10458
10538
  _log(msg, extra = {}, level = 'info') {
10459
- this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({ tags: ['connection_fallback', 'connection'] }, extra));
10539
+ this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({}, extra));
10460
10540
  }
10461
10541
  _setState(state) {
10462
10542
  this._log(`_setState() - ${state}`);
@@ -10516,7 +10596,7 @@ class StreamClient {
10516
10596
  * If the user id remains the same we don't throw error
10517
10597
  */
10518
10598
  if (this.userID === user.id && this.setUserPromise) {
10519
- console.warn('Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
10599
+ this.logger('warn', 'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
10520
10600
  return this.setUserPromise;
10521
10601
  }
10522
10602
  if (this.userID) {
@@ -10524,7 +10604,7 @@ class StreamClient {
10524
10604
  }
10525
10605
  if ((this._isUsingServerAuth() || this.node) &&
10526
10606
  !this.options.allowServerSideConnect) {
10527
- console.warn('Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.');
10607
+ this.logger('warn', 'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.');
10528
10608
  }
10529
10609
  // we generate the client id client side
10530
10610
  this.userID = user.id;
@@ -10587,16 +10667,12 @@ class StreamClient {
10587
10667
  throw Error('UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead');
10588
10668
  }
10589
10669
  if (((_d = this.wsConnection) === null || _d === void 0 ? void 0 : _d.isConnecting) && this.wsPromise) {
10590
- this.logger('info', 'client:openConnection() - connection already in progress', {
10591
- tags: ['connection', 'client'],
10592
- });
10670
+ this.logger('info', 'client:openConnection() - connection already in progress');
10593
10671
  return this.wsPromise;
10594
10672
  }
10595
10673
  if ((((_e = this.wsConnection) === null || _e === void 0 ? void 0 : _e.isHealthy) || ((_f = this.wsFallback) === null || _f === void 0 ? void 0 : _f.isHealthy())) &&
10596
10674
  this._hasConnectionID()) {
10597
- this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists', {
10598
- tags: ['connection', 'client'],
10599
- });
10675
+ this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
10600
10676
  return Promise.resolve();
10601
10677
  }
10602
10678
  this.clientID = `${this.userID}--${randomId()}`;
@@ -10619,9 +10695,7 @@ class StreamClient {
10619
10695
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
10620
10696
  */
10621
10697
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
10622
- this.logger('info', 'client:disconnect() - Disconnecting the client', {
10623
- tags: ['connection', 'client'],
10624
- });
10698
+ this.logger('info', 'client:disconnect() - Disconnecting the client');
10625
10699
  // remove the user specific fields
10626
10700
  delete this.user;
10627
10701
  delete this._user;
@@ -10711,7 +10785,8 @@ class StreamClient {
10711
10785
  this.dispatchEvent = (event) => {
10712
10786
  if (!event.received_at)
10713
10787
  event.received_at = new Date();
10714
- console.log(`Dispatching event: ${event.type}`, event);
10788
+ this.logger('info', `Dispatching event: ${event.type}`);
10789
+ this.logger('debug', 'Event payload:', event);
10715
10790
  this._callClientListeners(event);
10716
10791
  };
10717
10792
  this.handleEvent = (messageEvent) => {
@@ -10844,9 +10919,7 @@ class StreamClient {
10844
10919
  if (!(key in this.listeners)) {
10845
10920
  this.listeners[key] = [];
10846
10921
  }
10847
- this.logger('info', `Attaching listener for ${key} event`, {
10848
- tags: ['event', 'client'],
10849
- });
10922
+ this.logger('info', `Attaching listener for ${key} event`);
10850
10923
  this.listeners[key].push(callback);
10851
10924
  return () => {
10852
10925
  this.off(key, callback);
@@ -10864,29 +10937,26 @@ class StreamClient {
10864
10937
  if (!(key in this.listeners)) {
10865
10938
  this.listeners[key] = [];
10866
10939
  }
10867
- this.logger('info', `Removing listener for ${key} event`, {
10868
- tags: ['event', 'client'],
10869
- });
10940
+ this.logger('info', `Removing listener for ${key} event`);
10870
10941
  this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
10871
10942
  }
10872
10943
  _logApiRequest(type, url, data, config) {
10873
- this.logger('info', `client: ${type} - Request - ${url}`, {
10874
- tags: ['api', 'api_request', 'client'],
10875
- url,
10944
+ this.logger('info', `client: ${type} - Request - ${url}`);
10945
+ this.logger('debug', `client: ${type} - Request payload`, {
10876
10946
  payload: data,
10877
10947
  config,
10878
10948
  });
10879
10949
  }
10880
10950
  _logApiResponse(type, url, response) {
10881
10951
  this.logger('info', `client:${type} - Response - url: ${url} > status ${response.status}`, {
10882
- tags: ['api', 'api_response', 'client'],
10883
- url,
10952
+ response,
10953
+ });
10954
+ this.logger('debug', `client:${type} - Response payload`, {
10884
10955
  response,
10885
10956
  });
10886
10957
  }
10887
10958
  _logApiError(type, url, error) {
10888
10959
  this.logger('error', `client:${type} - Error - url: ${url}`, {
10889
- tags: ['api', 'api_response', 'client'],
10890
10960
  url,
10891
10961
  error,
10892
10962
  });
@@ -10961,7 +11031,7 @@ class StreamClient {
10961
11031
  if (this.wsFallback) {
10962
11032
  return yield this.wsFallback.connect();
10963
11033
  }
10964
- console.log('StreamClient.connect: this.wsConnection.connect()');
11034
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
10965
11035
  // if WSFallback is enabled, ws connect should timeout faster so fallback can try
10966
11036
  return yield this.wsConnection.connect(this.options.enableWSFallback
10967
11037
  ? this.defaultWSTimeoutWithFallback
@@ -10970,9 +11040,11 @@ class StreamClient {
10970
11040
  catch (err) {
10971
11041
  // run fallback only if it's WS/Network error and not a normal API error
10972
11042
  // make sure browser is online before even trying the longpoll
10973
- // @ts-ignore
10974
- if (this.options.enableWSFallback && isWSFailure(err) && isOnline()) {
10975
- this.logger('info', 'client:connect() - WS failed, fallback to longpoll', { tags: ['connection', 'client'] });
11043
+ if (this.options.enableWSFallback &&
11044
+ // @ts-ignore
11045
+ isWSFailure(err) &&
11046
+ isOnline(this.logger)) {
11047
+ this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
10976
11048
  this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
10977
11049
  this.wsConnection._destroyCurrentWSConnection();
10978
11050
  this.wsConnection.disconnect().then(); // close WS so no retry
@@ -11007,7 +11079,7 @@ class StreamClient {
11007
11079
  }
11008
11080
  getUserAgent() {
11009
11081
  return (this.userAgent ||
11010
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.13"}`);
11082
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.15"}`);
11011
11083
  }
11012
11084
  setUserAgent(userAgent) {
11013
11085
  this.userAgent = userAgent;
@@ -11076,7 +11148,10 @@ class StreamClient {
11076
11148
  */
11077
11149
  class StreamVideoClient {
11078
11150
  constructor(apiKeyOrArgs, opts) {
11151
+ var _a, _b;
11152
+ this.logLevel = 'warn';
11079
11153
  this.eventHandlersToUnregister = [];
11154
+ this.logLevels = ['debug', 'info', 'warn', 'error'];
11080
11155
  /**
11081
11156
  * Disconnects the currently connected user from the client.
11082
11157
  *
@@ -11235,11 +11310,30 @@ class StreamVideoClient {
11235
11310
  this.connectionPromise.finally(() => (this.connectionPromise = undefined));
11236
11311
  return this.connectionPromise;
11237
11312
  });
11313
+ this.filterLogs = (logMethod) => {
11314
+ return (logLevel, messeage, extraData, tags) => {
11315
+ if (this.logLevels.indexOf(logLevel) >=
11316
+ this.logLevels.indexOf(this.logLevel)) {
11317
+ logMethod(logLevel, messeage, extraData, tags);
11318
+ }
11319
+ };
11320
+ };
11321
+ let defaultLogger = logToConsole;
11238
11322
  if (typeof apiKeyOrArgs === 'string') {
11239
- this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign({ persistUserOnConnectionFailure: true }, opts));
11323
+ this.logLevel = (opts === null || opts === void 0 ? void 0 : opts.logLevel) || this.logLevel;
11324
+ this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || defaultLogger;
11240
11325
  }
11241
11326
  else {
11242
- this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options));
11327
+ this.logLevel = ((_a = apiKeyOrArgs.options) === null || _a === void 0 ? void 0 : _a.logLevel) || this.logLevel;
11328
+ this.logger = ((_b = apiKeyOrArgs.options) === null || _b === void 0 ? void 0 : _b.logger) || defaultLogger;
11329
+ }
11330
+ setLogger(this.filterLogs(defaultLogger));
11331
+ const clientLogger = getLogger(['client']);
11332
+ if (typeof apiKeyOrArgs === 'string') {
11333
+ this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, opts), { logLevel: this.logLevel, logger: clientLogger }));
11334
+ }
11335
+ else {
11336
+ this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options), { logLevel: this.logLevel, logger: clientLogger }));
11243
11337
  this.user = apiKeyOrArgs.user;
11244
11338
  this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
11245
11339
  if (this.user) {
@@ -11301,7 +11395,7 @@ class StreamVideoClient {
11301
11395
  },
11302
11396
  sort: [{ field: 'cid', direction: 1 }],
11303
11397
  }).catch((err) => {
11304
- console.warn('Failed to re-watch calls', err);
11398
+ this.logger('error', 'Failed to re-watch calls', err);
11305
11399
  });
11306
11400
  }
11307
11401
  }
@@ -11311,7 +11405,7 @@ class StreamVideoClient {
11311
11405
  return;
11312
11406
  const { call, members } = event;
11313
11407
  if (userToConnect.id === call.created_by.id) {
11314
- console.warn('Received `call.created` sent by the current user');
11408
+ this.logger('warn', 'Received `call.created` sent by the current user');
11315
11409
  return;
11316
11410
  }
11317
11411
  this.writeableStateStore.registerCall(new Call({
@@ -11328,7 +11422,7 @@ class StreamVideoClient {
11328
11422
  return;
11329
11423
  const { call, members } = event;
11330
11424
  if (userToConnect.id === call.created_by.id) {
11331
- console.warn('Received `call.ring` sent by the current user');
11425
+ this.logger('warn', 'Received `call.ring` sent by the current user');
11332
11426
  return;
11333
11427
  }
11334
11428
  // The call might already be tracked by the client,
@@ -11395,7 +11489,10 @@ const getDevices = (constraints) => {
11395
11489
  });
11396
11490
  })
11397
11491
  .catch((error) => {
11398
- console.error('Failed to get devices', error);
11492
+ const logger = getLogger(['devices']);
11493
+ if (logger) {
11494
+ logger('error', 'Failed to get devices', error);
11495
+ }
11399
11496
  subscriber.error(error);
11400
11497
  });
11401
11498
  });
@@ -11466,11 +11563,15 @@ const getAudioOutputDevices = () => {
11466
11563
  return audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audiooutput')));
11467
11564
  };
11468
11565
  const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
11566
+ var _a;
11469
11567
  try {
11470
11568
  return yield navigator.mediaDevices.getUserMedia(constraints);
11471
11569
  }
11472
11570
  catch (e) {
11473
- console.error(`Failed get user media`, constraints, e);
11571
+ (_a = getLogger(['devices'])) === null || _a === void 0 ? void 0 : _a('error', `Failed get user media`, {
11572
+ error: e,
11573
+ constraints: constraints,
11574
+ });
11474
11575
  throw e;
11475
11576
  }
11476
11577
  });
@@ -11513,11 +11614,12 @@ const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, f
11513
11614
  * @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
11514
11615
  */
11515
11616
  const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
11617
+ var _b;
11516
11618
  try {
11517
11619
  return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
11518
11620
  }
11519
11621
  catch (e) {
11520
- console.error('Failed to get screen share stream', e);
11622
+ (_b = getLogger(['devices'])) === null || _b === void 0 ? void 0 : _b('error', 'Failed to get screen share stream', e);
11521
11623
  throw e;
11522
11624
  }
11523
11625
  });
@@ -11700,5 +11802,5 @@ var browsers = /*#__PURE__*/Object.freeze({
11700
11802
  isSafari: isSafari
11701
11803
  });
11702
11804
 
11703
- export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
11805
+ export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getLogger, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logToConsole, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setLogger, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
11704
11806
  //# sourceMappingURL=index.browser.es.js.map