UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

1 lines 34.2 kB
{"version":3,"sources":["../../../packages/core/diagnostics/logging.ts"],"names":[],"mappings":"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","file":"logging.d.ts","sourcesContent":["/* eslint-disable no-console */\r\nimport { Subscription } from 'rxjs';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { GatewayConnection, GatewayRequest } from '../data/gateway-connection';\r\nimport { Http } from '../data/http';\r\nimport { Net } from '../data/net';\r\nimport { Strings } from '../generated/strings';\r\nimport { RpcLogClient } from '../rpc/log/rpc-log-client';\r\nimport { RpcLogRecord } from '../rpc/log/rpc-log-model';\r\nimport { RpcLogSubjectServer } from '../rpc/log/rpc-log-subject-server';\r\nimport { Rpc } from '../rpc/rpc';\r\nimport { RpcTelemetryClient } from '../rpc/telemetry/rpc-telemetry-client';\r\nimport { RpcTelemetryRecord } from '../rpc/telemetry/rpc-telemetry-model';\r\nimport { RpcTelemetrySubjectServer } from '../rpc/telemetry/rpc-telemetry-subject-server';\r\nimport { LogLevel } from './log-level';\r\nimport { LogRecord } from './log-record';\r\nimport { LoggingConstants } from './logging-constants';\r\nimport { TelemetryControlType } from './telemetry-control-type';\r\nimport { TelemetryRecord } from './telemetry-record';\r\n\r\n/**\r\n * Logger set for log and telemetry.\r\n */\r\ninterface LoggerSet<T> {\r\n /**\r\n * Max record to send to gateway. If it reaches then sends to gateway.\r\n */\r\n maxRecordLength: number;\r\n\r\n /**\r\n * Max wait time milliseconds. If it reaches then sends to gateway.\r\n */\r\n maxWaitTimeMs: number;\r\n\r\n /**\r\n * The api url.\r\n */\r\n api: string;\r\n\r\n /**\r\n * Subscription to rpc channel observable.\r\n */\r\n rpcSubscription?: Subscription;\r\n\r\n /**\r\n * Buffer.\r\n */\r\n buffer?: T[];\r\n\r\n /**\r\n * Timer object.\r\n */\r\n timer?: any;\r\n}\r\n\r\n/**\r\n * Logging class.\r\n * @dynamic\r\n */\r\nexport class Logging {\r\n private static logMaxRecordLength = 20;\r\n private static logMaxWaitTimeMs = 30000;\r\n private static telemetryMaxRecordLength = 100;\r\n private static telemetryMaxWaitTimeMs = 60000;\r\n private static testMode = 'test';\r\n private static instance: Logging;\r\n private static errorLogHeaderStyle = 'font-weight: bold; color: #E81123;';\r\n private static warnLogHeaderStyle = 'font-weight: bold; color: #FF8C00;';\r\n private static successLogHeaderStyle = 'font-weight: bold; color: ##288928;';\r\n private static infoLogHeaderStyle = 'font-weight: bold; color: #0078D7;';\r\n private static verboseLogHeaderStyle = 'color: #999';\r\n\r\n private logSubjectServer: RpcLogSubjectServer;\r\n private telemetrySubjectServer: RpcTelemetrySubjectServer;\r\n private gateway: GatewayConnection;\r\n private http: Http;\r\n private rpc: Rpc;\r\n private logSet: LoggerSet<RpcLogRecord>;\r\n private telemetrySet: LoggerSet<RpcTelemetryRecord>;\r\n\r\n private thresholdOfLogLevel: LogLevel = LogLevel.Informational;\r\n private verboseTelemetry = false;\r\n\r\n /**\r\n * Log a logging event.\r\n *\r\n * @param record the log record to send the gateway.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static log(record: LogRecord): Promise<any> {\r\n return Logging.current.logInternal(record);\r\n }\r\n\r\n /**\r\n * Log a critical logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logCritical(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Critical, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log an error logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logError(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Error, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log a warning logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logWarning(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Warning, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log a success logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logSuccess(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Success, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log a informational logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logInformational(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Informational, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log a verbose logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logVerbose(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Verbose, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Log a debug logging event.\r\n *\r\n * @param source The record originator of event within a module.\r\n * @param message The message of event.\r\n * @param params The parameters object which will be serialized.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static logDebug(source: string, message: string, params?: any): Promise<any> {\r\n return Logging.current.logInternal({ level: LogLevel.Debug, source, message, params: params });\r\n }\r\n\r\n /**\r\n * Trace a telemetry event.\r\n *\r\n * @param record the telemetry record to send the gateway.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static trace(record: TelemetryRecord): Promise<any> {\r\n return Logging.current.telemetryInternal(record);\r\n }\r\n\r\n /**\r\n * Trace a user action telemetry event.\r\n *\r\n * @param data additional data.\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceUserAction(data: any): Promise<any> {\r\n return Logging.trace({\r\n view: LoggingConstants.views.smeUIControl,\r\n instance: LoggingConstants.empty,\r\n action: LoggingConstants.actions.click,\r\n data: data\r\n });\r\n }\r\n\r\n /**\r\n * Trace a telemetry event for a button click.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceButton(controlName: string, controlId?: string, nodeName?: string, nodeType?: string): Promise<any> {\r\n return Logging.traceButtonClick(TelemetryControlType.Button, controlName, controlId, nodeName, nodeType);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event for a action pane button click.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceActionPaneButton(controlName: string, controlId?: string, nodeName?: string, nodeType?: string): Promise<any> {\r\n return Logging.traceButtonClick(TelemetryControlType.ActionPaneButton, controlName, controlId, nodeName, nodeType);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event for a action bar button click.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceActionBarButton(controlName: string, controlId?: string, nodeName?: string, nodeType?: string): Promise<any> {\r\n return Logging.traceButtonClick(TelemetryControlType.ActionBarButton, controlName, controlId, nodeName, nodeType);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event on a sme control.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param additionalData Additional key value pairs that can be sent to telemetry.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceControl(\r\n controlType: TelemetryControlType,\r\n controlName: string,\r\n controlId?: string,\r\n additionalData?: any,\r\n nodeName?: string,\r\n nodeType?: string): Promise<any> {\r\n let data = {};\r\n\r\n if (additionalData) {\r\n data = additionalData;\r\n }\r\n data[controlType] = controlType;\r\n data[controlName] = controlName;\r\n data[controlId] = controlId;\r\n const nodeId = Logging.getFormattedNodeId(nodeName, nodeType);\r\n if (nodeId) {\r\n data[LoggingConstants.dataFields.nodeId] = nodeId;\r\n }\r\n\r\n return Logging.traceUserAction(data);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event on click of an external link.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param url External link that was clicked.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceExternalLink(\r\n controlName: string,\r\n url: string,\r\n controlId?: string,\r\n nodeName?: string,\r\n nodeType?: string): Promise<any> {\r\n const data = {\r\n controlType: TelemetryControlType.ExternalLink,\r\n controlName: controlName,\r\n controlId: controlId,\r\n url: url\r\n };\r\n\r\n const nodeId = Logging.getFormattedNodeId(nodeName, nodeType);\r\n if (nodeId) {\r\n data[LoggingConstants.dataFields.nodeId] = nodeId;\r\n }\r\n\r\n return Logging.traceUserAction(data);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event on click of an internal link.\r\n *\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param route rpc route.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceInternalLink(\r\n controlName: string,\r\n route: string,\r\n controlId?: string,\r\n nodeName?: string,\r\n nodeType?: string): Promise<any> {\r\n const data = {\r\n controlType: TelemetryControlType.InternalLink,\r\n controlName: controlName,\r\n controlId: controlId,\r\n route: route\r\n };\r\n\r\n const nodeId = Logging.getFormattedNodeId(nodeName, nodeType);\r\n if (nodeId) {\r\n data[LoggingConstants.dataFields.nodeId] = nodeId;\r\n }\r\n\r\n return Logging.traceUserAction(data);\r\n }\r\n\r\n /**\r\n * Trace a telemetry event when an async task returns.\r\n *\r\n * @param eventLocation UI location of the event being recorded.\r\n * ex) createVmForm, RegisterAadDialog, stopServiceConfirmationDialog...\r\n * @param eventLabel Description of what event is being logged.\r\n * ex) 'Registered with Azure', 'Added a connection', 'Failed Azure backup'\r\n * @param result Result of event.\r\n * @param additionalData Additional key value pairs that can be sent to telemetry.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n public static traceAsyncResult(\r\n eventLocation: string,\r\n eventLabel: string,\r\n result: 'Success' | 'Error' | 'Failure',\r\n additionalData?: any,\r\n nodeName?: string,\r\n nodeType?: string): Promise<any> {\r\n let data = {};\r\n if (additionalData) {\r\n data = additionalData;\r\n }\r\n\r\n data[LoggingConstants.dataFields.eventLocation] = eventLocation;\r\n data[LoggingConstants.dataFields.eventLabel] = eventLabel;\r\n data[LoggingConstants.dataFields.result] = result;\r\n\r\n const nodeId = Logging.getFormattedNodeId(nodeName, nodeType);\r\n if (nodeId) {\r\n data[LoggingConstants.dataFields.nodeId] = nodeId;\r\n }\r\n\r\n return Logging.traceUserAction(data);\r\n }\r\n\r\n /**\r\n * Log a raw object into the console at debug level of mode.\r\n */\r\n public static debug(object: any): void {\r\n if (Logging.current.consoleLogLevel >= LogLevel.Debug) {\r\n console.log(object);\r\n }\r\n }\r\n\r\n /**\r\n * Configure logging mode.\r\n *\r\n * @param thresholdOfLogLevel the log level for gateway.\r\n * @param verboseTelemetry if true, optional telemerty will be collected.\r\n */\r\n public static configureLog(thresholdOfLogLevel: LogLevel, verboseTelemetry: boolean): void {\r\n Logging.current.thresholdOfLogLevel = thresholdOfLogLevel;\r\n Logging.current.verboseTelemetry = verboseTelemetry;\r\n }\r\n\r\n /**\r\n * Wrapper method for tracing a telemetry event for a button click.\r\n *\r\n * @param controlType Type of button that is being recorded\r\n * @param controlName Describes which control was used.\r\n * ex) For a button that says 'Set up' the control name can be 'Set up' to distinguish that from a cancel button.\r\n * @param controlId Unique identifier when a control appears more than once. Specific to how implementation handles uniqueness.\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return Promise<any> settle to resolve if buffered.\r\n */\r\n private static traceButtonClick(\r\n controlType: TelemetryControlType.ActionBarButton | TelemetryControlType.ActionPaneButton | TelemetryControlType.Button,\r\n controlName: string,\r\n controlId?: string,\r\n nodeName?: string,\r\n nodeType?: string): Promise<any> {\r\n const data = {\r\n controlType: controlType,\r\n controlName: controlName,\r\n controlId: controlId\r\n };\r\n\r\n const nodeId = Logging.getFormattedNodeId(nodeName, nodeType);\r\n if (nodeId) {\r\n data[LoggingConstants.dataFields.nodeId] = nodeId;\r\n }\r\n\r\n return Logging.traceUserAction(data);\r\n }\r\n\r\n /**\r\n * Format node information for telemetry\r\n *\r\n * @param nodeName the name of the node currently connected to (this.appContextService.activeConnection.nodeName)\r\n * @param nodeType the type of node currently connected to (this.appContextService.connectionManager.activeConnection.type)\r\n * @return string\r\n */\r\n private static getFormattedNodeId(nodeName?: string, nodeType?: string): string {\r\n if (nodeType && nodeName) {\r\n return nodeType + '!' + nodeName;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the level of current logging.\r\n */\r\n public get consoleLogLevel(): LogLevel {\r\n const global: MsftSme.SMEWindow = <any>window;\r\n return <LogLevel>(global.MsftSme && global.MsftSme.Init && global.MsftSme.Init.logLevel) || LogLevel.Warning;\r\n }\r\n\r\n /**\r\n * Gets the session Id of shell.\r\n */\r\n private get sessionId(): string {\r\n const global: MsftSme.SMEWindow = <any>window;\r\n return global.MsftSme && global.MsftSme.Init && global.MsftSme.Init.sessionId || Logging.testMode;\r\n }\r\n\r\n /**\r\n * Gets the name of current shell or module.\r\n */\r\n private get nameOfModule(): string {\r\n const global: MsftSme.SMEWindow = <any>window;\r\n return global.MsftSme && global.MsftSme.Init && global.MsftSme.Init.moduleName || Logging.testMode;\r\n }\r\n\r\n /**\r\n * Initializes a new instance of the Logging class.\r\n */\r\n constructor() {\r\n this.http = new Http();\r\n this.logSet = {\r\n maxWaitTimeMs: Logging.logMaxWaitTimeMs,\r\n maxRecordLength: Logging.logMaxRecordLength,\r\n api: '/log'\r\n };\r\n this.telemetrySet = {\r\n maxWaitTimeMs: Logging.telemetryMaxWaitTimeMs,\r\n maxRecordLength: Logging.telemetryMaxRecordLength,\r\n api: '/telemetry'\r\n };\r\n }\r\n\r\n /**\r\n * Gets the current logging instance.\r\n */\r\n public static get current(): Logging {\r\n if (Logging.instance) {\r\n return Logging.instance;\r\n }\r\n\r\n Logging.instance = new Logging();\r\n return Logging.instance;\r\n }\r\n\r\n /**\r\n * Flush the regular log set, immediately submitting the logs to the gateway\r\n */\r\n public static flushLogs() {\r\n Logging.current.flush(Logging.current.logSet);\r\n }\r\n\r\n /**\r\n * Flush the telemetry log set, immediately submitting the logs to the gateway\r\n */\r\n public static flushTelemetry() {\r\n Logging.current.flush(Logging.current.telemetrySet);\r\n }\r\n\r\n /**\r\n * Register Rpc object to logging instance.\r\n *\r\n * @param rpc the rpc instance.\r\n */\r\n public registerRpc(rpc: Rpc, gateway: GatewayConnection): void {\r\n this.rpc = rpc;\r\n this.gateway = gateway;\r\n\r\n // start subscribing once after the rpc is ready on the shell.\r\n this.rpc.stateChanged\r\n .pipe(\r\n filter(active => active),\r\n take(1))\r\n .subscribe(() => {\r\n if (this.rpc.isShell) {\r\n this.logSubjectServer = new RpcLogSubjectServer(this.rpc);\r\n this.logSet.rpcSubscription = this.logSubjectServer.subject\r\n .subscribe(data => {\r\n this.logGateway<RpcLogRecord>(this.logSet, data.data);\r\n data.deferred.resolve();\r\n });\r\n this.telemetrySubjectServer = new RpcTelemetrySubjectServer(this.rpc);\r\n this.telemetrySet.rpcSubscription = this.telemetrySubjectServer.subject\r\n .subscribe(data => {\r\n this.logGateway<RpcTelemetryRecord>(this.telemetrySet, data.data);\r\n data.deferred.resolve();\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Dispose the set of rpc forwarding pipes.\r\n */\r\n public dispose(): void {\r\n this.disposeSet<RpcLogRecord>(this.logSet);\r\n this.disposeSet<RpcTelemetryRecord>(this.telemetrySet);\r\n }\r\n\r\n /**\r\n * Log a record.\r\n *\r\n * @param record the log record.\r\n * @return Promise<any> the promise object.\r\n */\r\n private logInternal(record: LogRecord): Promise<any> {\r\n const now = new Date();\r\n if (record.level <= this.consoleLogLevel) {\r\n let headerStyle = Logging.verboseLogHeaderStyle;\r\n if (record.level <= LogLevel.Error) {\r\n headerStyle = Logging.errorLogHeaderStyle;\r\n } else if (record.level <= LogLevel.Warning) {\r\n headerStyle = Logging.warnLogHeaderStyle;\r\n } else if (record.level <= LogLevel.Success) {\r\n headerStyle = Logging.successLogHeaderStyle;\r\n } else if (record.level <= LogLevel.Informational) {\r\n headerStyle = Logging.infoLogHeaderStyle;\r\n }\r\n\r\n const logSeparator = '--';\r\n const customHeader = record.consoleGroupHeader ? ` ${logSeparator} ${record.consoleGroupHeader}` : '';\r\n if (MsftSme.isEdge() || MsftSme.isInternetExplorer()) {\r\n // Microsoft Edge and IE don't support styles in group headers. so remove if running on Microsoft Edge\r\n // Since there is no color support, also log the severity\r\n console.groupCollapsed(\r\n `${LogLevel[record.level]} ${logSeparator} ${this.nameOfModule} ${logSeparator} ${record.source}${customHeader}`\r\n );\r\n } else {\r\n console.groupCollapsed(`%c${this.nameOfModule} ${logSeparator} ${record.source}${customHeader}`, headerStyle);\r\n }\r\n\r\n console.log(`logLevel: ${LogLevel[record.level]}`);\r\n console.log(`timestamp: ${now.toISOString()}`);\r\n if (record.message) {\r\n if (MsftSme.isObject(record.message)) {\r\n console.log('message:');\r\n console.log({ ...record.message });\r\n } else {\r\n console.log(`message: ${record.message}`);\r\n }\r\n }\r\n\r\n if (record.params) {\r\n console.group('params');\r\n console.log({ ...record.params });\r\n console.groupEnd();\r\n }\r\n\r\n if (record.localParams) {\r\n console.group('params');\r\n console.log({ ...record.localParams });\r\n console.groupEnd();\r\n delete record['localParams'];\r\n }\r\n\r\n if (record.stack) {\r\n console.group('stack');\r\n console.log(record.stack);\r\n console.groupEnd();\r\n }\r\n\r\n console.groupEnd();\r\n }\r\n\r\n if (record.level <= this.thresholdOfLogLevel && this.sessionId !== Logging.testMode) {\r\n if (MsftSme.isObject(record.message)) {\r\n // ensure message is a string.\r\n record.message = JSON.stringify(record.message);\r\n }\r\n\r\n const rpcRecord: RpcLogRecord = {\r\n ...record,\r\n ...{ sessionId: this.sessionId, timestamp: now.getTime(), sourceName: this.nameOfModule }\r\n };\r\n if (this.rpc && this.rpc.stateActive && !this.rpc.isShell) {\r\n return RpcLogClient.log(this.rpc, rpcRecord);\r\n }\r\n\r\n this.logGateway<RpcLogRecord>(this.logSet, rpcRecord);\r\n }\r\n\r\n return Promise.resolve();\r\n }\r\n\r\n /**\r\n * Log a telemerty record.\r\n *\r\n * @param record the telemetry record.\r\n * @return Promise<any> the promise object.\r\n */\r\n private telemetryInternal(record: TelemetryRecord): Promise<any> {\r\n if (((!this.verboseTelemetry && !record.optional) || this.verboseTelemetry) && this.sessionId !== Logging.testMode) {\r\n const rpcRecord = { ...record, ...{ sessionId: this.sessionId, timestamp: Date.now(), sourceName: this.nameOfModule } };\r\n if (this.rpc && this.rpc.stateActive && !this.rpc.isShell) {\r\n return RpcTelemetryClient.telemetry(this.rpc, rpcRecord);\r\n }\r\n\r\n this.logGateway<RpcTelemetryRecord>(this.telemetrySet, rpcRecord);\r\n }\r\n\r\n return Promise.resolve();\r\n }\r\n\r\n /**\r\n * Dispose the set.\r\n *\r\n * @param set the logger set.\r\n */\r\n private disposeSet<T>(set: LoggerSet<T>): void {\r\n if (set.rpcSubscription) {\r\n set.rpcSubscription.unsubscribe();\r\n set.rpcSubscription = null;\r\n }\r\n }\r\n\r\n /**\r\n * Log to the gateway.\r\n *\r\n * @param set the logger set.\r\n * @param data the record data.\r\n */\r\n private logGateway<T>(set: LoggerSet<T>, data: T): void {\r\n if (set.timer == null) {\r\n set.buffer = [];\r\n set.timer = setTimeout(() => this.submitRecords<T>(set), set.maxWaitTimeMs);\r\n }\r\n\r\n set.buffer.push(data);\r\n if (set.buffer.length >= set.maxRecordLength) {\r\n clearTimeout(set.timer);\r\n this.submitRecords(set);\r\n set.timer = setTimeout(() => this.submitRecords<T>(set), set.maxWaitTimeMs);\r\n }\r\n }\r\n\r\n /**\r\n * Flush a log set, immediately submitting the logs to the gateway\r\n */\r\n private flush<T>(set: LoggerSet<T>) {\r\n if (set && set.buffer && set.buffer.length > 0) {\r\n this.submitRecords(set);\r\n }\r\n }\r\n\r\n /**\r\n * Submit records to the gateway.\r\n */\r\n private submitRecords<T>(set: LoggerSet<T>): void {\r\n // Disabled gateway can't log anything in gateway.\r\n if (set.buffer.length > 0 && this.gateway && !this.gateway.disabled) {\r\n this.gateway.post(set.api, set.buffer, <GatewayRequest>{ maxRetryCount: 0 }).subscribe({\r\n error: error => {\r\n const message = MsftSme.getStrings<Strings>().MsftSmeShell.Core.Error.LoggingUnableSubmit.message;\r\n console.error(message.format(Net.getErrorMessage(error)));\r\n }\r\n });\r\n }\r\n\r\n set.timer = null;\r\n set.buffer = [];\r\n }\r\n}\r\n"]}