Skip to content

Commit ecbd562

Browse files
authored
Improve message logging from communications module (#2514)
* fix ids in logging * use new logger for child messages * changefile * Make shared message id printer * Double id string
1 parent f403a09 commit ecbd562

File tree

3 files changed

+108
-42
lines changed

3 files changed

+108
-42
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"cSpell.words": ["adal", "ipados", "teamspace", "uninitialize", "xvfb"],
2+
"cSpell.words": ["adal", "frameless", "ipados", "teamspace", "uninitialize", "xvfb"],
33
"editor.defaultFormatter": "esbenp.prettier-vscode",
44
"eslint.workingDirectories": [
55
"./apps/ssr-test-app/",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Updated logging for messages to be clearer",
4+
"packageName": "@microsoft/teams-js",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/teams-js/src/internal/communication.ts

Lines changed: 100 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function initializeCommunication(
8787
apiVersionTag: string,
8888
): Promise<InitializeResponse> {
8989
// Listen for messages post to our window
90-
CommunicationPrivate.messageListener = async (evt: DOMMessageEvent): Promise<void> => await processMessage(evt);
90+
CommunicationPrivate.messageListener = (evt: DOMMessageEvent): Promise<void> => processIncomingMessage(evt);
9191

9292
// If we are in an iframe, our parent window is the one hosting us (i.e., window.parent); otherwise,
9393
// it's the window that opened us (i.e., window.opener)
@@ -108,7 +108,7 @@ export function initializeCommunication(
108108
const extendedWindow = Communication.currentWindow as unknown as ExtendedWindow;
109109
if (extendedWindow.nativeInterface) {
110110
GlobalVars.isFramelessWindow = true;
111-
extendedWindow.onNativeMessage = handleParentMessage;
111+
extendedWindow.onNativeMessage = handleIncomingMessageFromParent;
112112
} else {
113113
// at this point we weren't able to find a parent to talk to, no way initialization will succeed
114114
return Promise.reject(new Error('Initialization Failed. No Parent window found.'));
@@ -368,7 +368,9 @@ export function sendNestedAuthRequestToTopWindow(message: string): NestedAppAuth
368368
const targetWindow = Communication.topWindow;
369369
const request = createNestedAppAuthRequest(message);
370370

371-
logger('Message %i information: %o', request.uuid, { actionName: request.func });
371+
logger('Message %s information: %o', getMessageIdsAsLogString(request), {
372+
actionName: request.func,
373+
});
372374

373375
return sendRequestToTargetWindowHelper(targetWindow, request) as NestedAppAuthRequest;
374376
}
@@ -389,7 +391,11 @@ function sendRequestToTargetWindowHelper(
389391

390392
if (GlobalVars.isFramelessWindow) {
391393
if (Communication.currentWindow && Communication.currentWindow.nativeInterface) {
392-
logger(`Sending message %i to ${targetWindowName} via framelessPostMessage interface`, request.uuidAsString);
394+
logger(
395+
'Sending message %s to %s via framelessPostMessage interface',
396+
getMessageIdsAsLogString(request),
397+
targetWindowName,
398+
);
393399
(Communication.currentWindow as ExtendedWindow).nativeInterface.framelessPostMessage(JSON.stringify(request));
394400
}
395401
} else {
@@ -398,10 +404,10 @@ function sendRequestToTargetWindowHelper(
398404
// If the target window isn't closed and we already know its origin, send the message right away; otherwise,
399405
// queue the message and send it after the origin is established
400406
if (targetWindow && targetOrigin) {
401-
logger(`Sending message %i to ${targetWindowName} via postMessage`, request.uuidAsString);
407+
logger('Sending message %s to %s via postMessage', getMessageIdsAsLogString(request), targetWindowName);
402408
targetWindow.postMessage(request, targetOrigin);
403409
} else {
404-
logger(`Adding message %i to ${targetWindowName} message queue`, request.uuidAsString);
410+
logger('Adding message %s to %s message queue', getMessageIdsAsLogString(request), targetWindowName);
405411
getTargetMessageQueue(targetWindow).push(messageRequest);
406412
}
407413
}
@@ -424,21 +430,24 @@ function sendMessageToParentHelper(
424430
const targetWindow = Communication.parentWindow;
425431
const request = createMessageRequest(apiVersionTag, actionName, args);
426432

427-
logger('Message %i information: %o', request.uuid, { actionName, args });
433+
logger('Message %s information: %o', getMessageIdsAsLogString(request), { actionName, args });
428434

429435
return sendRequestToTargetWindowHelper(targetWindow, request);
430436
}
431437

432-
const processMessageLogger = communicationLogger.extend('processMessage');
438+
const processIncomingMessageLogger = communicationLogger.extend('processIncomingMessage');
433439

434440
/**
435441
* @internal
436442
* Limited to Microsoft-internal use
437443
*/
438-
async function processMessage(evt: DOMMessageEvent): Promise<void> {
444+
async function processIncomingMessage(evt: DOMMessageEvent): Promise<void> {
439445
// Process only if we received a valid message
440446
if (!evt || !evt.data || typeof evt.data !== 'object') {
441-
processMessageLogger('Unrecognized message format received by app, message being ignored. Message: %o', evt);
447+
processIncomingMessageLogger(
448+
'Unrecognized message format received by app, message being ignored. Message: %o',
449+
evt,
450+
);
442451
return;
443452
}
444453

@@ -448,20 +457,23 @@ async function processMessage(evt: DOMMessageEvent): Promise<void> {
448457
const messageSource = evt.source || (evt.originalEvent && evt.originalEvent.source);
449458
const messageOrigin = evt.origin || (evt.originalEvent && evt.originalEvent.origin);
450459

451-
return shouldProcessMessage(messageSource, messageOrigin).then((result) => {
460+
return shouldProcessIncomingMessage(messageSource, messageOrigin).then((result) => {
452461
if (!result) {
453-
processMessageLogger(
454-
'Message being ignored by app because it is either coming from the current window or a different window with an invalid origin',
462+
processIncomingMessageLogger(
463+
'Message being ignored by app because it is either coming from the current window or a different window with an invalid origin, message: %o, source: %o, origin: %o',
464+
evt,
465+
messageSource,
466+
messageOrigin,
455467
);
456468
return;
457469
}
458470
// Update our parent and child relationships based on this message
459471
updateRelationships(messageSource, messageOrigin);
460472
// Handle the message
461473
if (messageSource === Communication.parentWindow) {
462-
handleParentMessage(evt);
474+
handleIncomingMessageFromParent(evt);
463475
} else if (messageSource === Communication.childWindow) {
464-
handleChildMessage(evt);
476+
handleIncomingMessageFromChild(evt);
465477
}
466478
});
467479
}
@@ -511,7 +523,7 @@ function processAuthBridgeMessage(evt: MessageEvent, onMessageReceived: (respons
511523
return;
512524
}
513525

514-
if (!shouldProcessMessage(messageSource, messageOrigin)) {
526+
if (!shouldProcessIncomingMessage(messageSource, messageOrigin)) {
515527
logger(
516528
'Message being ignored by app because it is either coming from the current window or a different window with an invalid origin',
517529
);
@@ -542,7 +554,7 @@ function processAuthBridgeMessage(evt: MessageEvent, onMessageReceived: (respons
542554
onMessageReceived(message);
543555
}
544556

545-
const shouldProcessMessageLogger = communicationLogger.extend('shouldProcessMessage');
557+
const shouldProcessIncomingMessageLogger = communicationLogger.extend('shouldProcessIncomingMessage');
546558

547559
/**
548560
* @hidden
@@ -551,11 +563,11 @@ const shouldProcessMessageLogger = communicationLogger.extend('shouldProcessMess
551563
* @internal
552564
* Limited to Microsoft-internal use
553565
*/
554-
async function shouldProcessMessage(messageSource: Window, messageOrigin: string): Promise<boolean> {
566+
async function shouldProcessIncomingMessage(messageSource: Window, messageOrigin: string): Promise<boolean> {
555567
// Process if message source is a different window and if origin is either in
556568
// Teams' pre-known whitelist or supplied as valid origin by user during initialization
557569
if (Communication.currentWindow && messageSource === Communication.currentWindow) {
558-
shouldProcessMessageLogger('Should not process message because it is coming from the current window');
570+
shouldProcessIncomingMessageLogger('Should not process message because it is coming from the current window');
559571
return false;
560572
} else if (
561573
Communication.currentWindow &&
@@ -569,13 +581,13 @@ async function shouldProcessMessage(messageSource: Window, messageOrigin: string
569581
try {
570582
messageOriginURL = new URL(messageOrigin);
571583
} catch (_) {
572-
shouldProcessMessageLogger('Message has an invalid origin of %s', messageOrigin);
584+
shouldProcessIncomingMessageLogger('Message has an invalid origin of %s', messageOrigin);
573585
return false;
574586
}
575587

576588
const isOriginValid = await validateOrigin(messageOriginURL);
577589
if (!isOriginValid) {
578-
shouldProcessMessageLogger('Message has an invalid origin of %s', messageOrigin);
590+
shouldProcessIncomingMessageLogger('Message has an invalid origin of %s', messageOrigin);
579591
}
580592
return isOriginValid;
581593
}
@@ -619,14 +631,14 @@ function updateRelationships(messageSource: Window, messageOrigin: string): void
619631
flushMessageQueue(Communication.childWindow);
620632
}
621633

622-
const handleParentMessageLogger = communicationLogger.extend('handleParentMessage');
634+
const handleIncomingMessageFromParentLogger = communicationLogger.extend('handleIncomingMessageFromParent');
623635

624636
/**
625637
* @internal
626638
* Limited to Microsoft-internal use
627639
*/
628640
function retrieveMessageUUIDFromResponse(response: MessageResponse): MessageUUID | undefined {
629-
const logger = handleParentMessageLogger;
641+
const logger = handleIncomingMessageFromParentLogger;
630642
if (response.uuid) {
631643
const responseUUID = response.uuid;
632644
const callbackUUID = retrieveMessageUUIDFromCallback(CommunicationPrivate.callbacks, responseUUID);
@@ -644,10 +656,7 @@ function retrieveMessageUUIDFromResponse(response: MessageResponse): MessageUUID
644656
} else {
645657
return CommunicationPrivate.legacyMessageIdsToUuidMap[response.id];
646658
}
647-
logger(
648-
`Received a message with uuid: ${response.uuid?.toString()} and legacyId: %i that failed to produce a callbackId`,
649-
response.id,
650-
);
659+
logger('Received message %s that failed to produce a callbackId', getMessageIdsAsLogString(response));
651660
return undefined;
652661
}
653662

@@ -657,7 +666,7 @@ function retrieveMessageUUIDFromResponse(response: MessageResponse): MessageUUID
657666
*
658667
* This function is used to compare a new MessageUUID object value to the key values in the specified callback and retrieving that key
659668
* We use this because two objects with the same value are not considered equivalent therefore we can't use the new MessageUUID object
660-
* as a key to retrieve the value assosciated with it and should use this function instead.
669+
* as a key to retrieve the value associated with it and should use this function instead.
661670
*/
662671
function retrieveMessageUUIDFromCallback(
663672
map: Map<MessageUUID, Function>,
@@ -695,8 +704,8 @@ function removeMessageHandlers(message: MessageResponse, map: Map<MessageUUID, F
695704
* @internal
696705
* Limited to Microsoft-internal use
697706
*/
698-
function handleParentMessage(evt: DOMMessageEvent): void {
699-
const logger = handleParentMessageLogger;
707+
function handleIncomingMessageFromParent(evt: DOMMessageEvent): void {
708+
const logger = handleIncomingMessageFromParentLogger;
700709

701710
if ('id' in evt.data && typeof evt.data.id === 'number') {
702711
// Call any associated Communication.callbacks
@@ -705,37 +714,49 @@ function handleParentMessage(evt: DOMMessageEvent): void {
705714
const callbackId = retrieveMessageUUIDFromResponse(message);
706715
if (callbackId) {
707716
const callback = CommunicationPrivate.callbacks.get(callbackId);
708-
logger('Received a response from parent for message %i', callbackId);
717+
logger('Received a response from parent for message %s', callbackId.toString());
709718
if (callback) {
710-
logger('Invoking the registered callback for message %i with arguments %o', callbackId, message.args);
719+
logger(
720+
'Invoking the registered callback for message %s with arguments %o',
721+
callbackId.toString(),
722+
message.args,
723+
);
711724
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
712725
// @ts-ignore
713726
callback.apply(null, [...message.args, message.isPartialResponse]);
714727

715728
// Remove the callback to ensure that the callback is called only once and to free up memory if response is a complete response
716729
if (!isPartialResponse(evt)) {
717-
logger('Removing registered callback for message %i', callbackId);
730+
logger('Removing registered callback for message %s', callbackId.toString());
718731
removeMessageHandlers(message, CommunicationPrivate.callbacks);
719732
}
720733
}
721734
const promiseCallback = CommunicationPrivate.promiseCallbacks.get(callbackId);
722735
if (promiseCallback) {
723-
logger('Invoking the registered promise callback for message %i with arguments %o', callbackId, message.args);
736+
logger(
737+
'Invoking the registered promise callback for message %s with arguments %o',
738+
callbackId.toString(),
739+
message.args,
740+
);
724741
promiseCallback(message.args);
725742

726-
logger('Removing registered promise callback for message %i', callbackId);
743+
logger('Removing registered promise callback for message %s', callbackId.toString());
727744
removeMessageHandlers(message, CommunicationPrivate.promiseCallbacks);
728745
}
729746
const portCallback = CommunicationPrivate.portCallbacks.get(callbackId);
730747
if (portCallback) {
731-
logger('Invoking the registered port callback for message %i with arguments %o', callbackId, message.args);
748+
logger(
749+
'Invoking the registered port callback for message %s with arguments %o',
750+
callbackId.toString(),
751+
message.args,
752+
);
732753
let port: MessagePort | undefined;
733754
if (evt.ports && evt.ports[0] instanceof MessagePort) {
734755
port = evt.ports[0];
735756
}
736757
portCallback(port, message.args);
737758

738-
logger('Removing registered port callback for message %i', callbackId);
759+
logger('Removing registered port callback for message %s', callbackId.toString());
739760
removeMessageHandlers(message, CommunicationPrivate.portCallbacks);
740761
}
741762
if (message.uuid) {
@@ -745,7 +766,7 @@ function handleParentMessage(evt: DOMMessageEvent): void {
745766
} else if ('func' in evt.data && typeof evt.data.func === 'string') {
746767
// Delegate the request to the proper handler
747768
const message = evt.data as MessageRequest;
748-
logger('Received an action message %s from parent', message.func);
769+
logger('Received a message from parent %s, action: "%s"', getMessageIdsAsLogString(message), message.func);
749770
callHandler(message.func, message.args);
750771
} else {
751772
logger('Received an unknown message: %O', evt);
@@ -760,28 +781,47 @@ function isPartialResponse(evt: DOMMessageEvent): boolean {
760781
return evt.data.isPartialResponse === true;
761782
}
762783

784+
const handleIncomingMessageFromChildLogger = communicationLogger.extend('handleIncomingMessageFromChild');
785+
763786
/**
764787
* @internal
765788
* Limited to Microsoft-internal use
766789
*/
767-
function handleChildMessage(evt: DOMMessageEvent): void {
790+
function handleIncomingMessageFromChild(evt: DOMMessageEvent): void {
768791
if ('id' in evt.data && 'func' in evt.data) {
769792
// Try to delegate the request to the proper handler, if defined
770793
const message = deserializeMessageRequest(evt.data as SerializedMessageRequest);
771794
const [called, result] = callHandler(message.func, message.args);
772795
if (called && typeof result !== 'undefined') {
796+
handleIncomingMessageFromChildLogger(
797+
'Returning message %s from child back to child, action: %s.',
798+
getMessageIdsAsLogString(message),
799+
message.func,
800+
);
801+
773802
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
774803
// @ts-ignore
775804
sendMessageResponseToChild(message.id, message.uuid, Array.isArray(result) ? result : [result]);
776805
} else {
777806
// No handler, proxy to parent
807+
808+
handleIncomingMessageFromChildLogger(
809+
'Relaying message %s from child to parent, action: %s. Relayed message will have a new id.',
810+
getMessageIdsAsLogString(message),
811+
message.func,
812+
);
813+
778814
sendMessageToParent(
779815
getApiVersionTag(ApiVersionNumber.V_2, ApiName.Tasks_StartTask),
780816
message.func,
781817
message.args,
782818
(...args: any[]): void => {
783819
if (Communication.childWindow) {
784820
const isPartialResponse = args.pop();
821+
handleIncomingMessageFromChildLogger(
822+
'Message from parent being relayed to child, id: %s',
823+
getMessageIdsAsLogString(message),
824+
);
785825
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
786826
// @ts-ignore
787827
sendMessageResponseToChild(message.id, message.uuid, args, isPartialResponse);
@@ -869,8 +909,9 @@ function flushMessageQueue(targetWindow: Window | any): void {
869909

870910
/* eslint-disable-next-line strict-null-checks/all */ /* Fix tracked by 5730662 */
871911
flushMessageQueueLogger(
872-
'Flushing message %i from ' + target + ' message queue via postMessage.',
873-
request?.uuidAsString,
912+
'Flushing message %s from %s message queue via postMessage.',
913+
getMessageIdsAsLogString(request),
914+
target,
874915
);
875916

876917
targetWindow.postMessage(request, targetOrigin);
@@ -1020,3 +1061,21 @@ function createMessageEvent(func: string, args?: any[]): MessageRequest {
10201061
args: args || [],
10211062
};
10221063
}
1064+
1065+
function getMessageIdsAsLogString(
1066+
message:
1067+
| SerializedMessageRequest
1068+
| SerializedMessageResponse
1069+
| MessageRequestWithRequiredProperties
1070+
| MessageRequest
1071+
| MessageResponse
1072+
| NestedAppAuthRequest,
1073+
): string {
1074+
if ('uuidAsString' in message) {
1075+
return `${message.uuidAsString} (legacy id: ${message.id})`;
1076+
} else if ('uuid' in message && message.uuid !== undefined) {
1077+
return `${message.uuid.toString()} (legacy id: ${message.id})`;
1078+
} else {
1079+
return `legacy id: ${message.id} (no uuid)`;
1080+
}
1081+
}

0 commit comments

Comments
 (0)