Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(container-loader): Allow setting the container's logger at load time #13779

Merged
merged 11 commits into from
Feb 3, 2023
2 changes: 2 additions & 0 deletions api-report/container-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComp

// @public (undocumented)
export interface IContainerConfig {
baseLogger?: ITelemetryBaseLogger;
// (undocumented)
canReconnect?: boolean;
clientDetailsOverride?: IClientDetails;
Expand All @@ -137,6 +138,7 @@ export interface IContainerConfig {

// @public (undocumented)
export interface IContainerLoadOptions {
baseLogger?: ITelemetryBaseLogger;
canReconnect?: boolean;
clientDetailsOverride?: IClientDetails;
loadMode?: IContainerLoadMode;
Expand Down
3 changes: 3 additions & 0 deletions packages/common/container-definitions/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ export enum LoaderHeader {
* otherwise, version sha to load snapshot
*/
version = "version",

// TODO #AB3350: This is a breaking change; it will be enabled in the "next" branch
// baseLogger = "fluid-base-logger"
}

export interface IContainerLoadMode {
Expand Down
75 changes: 46 additions & 29 deletions packages/loader/container-loader/src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import merge from "lodash/merge";
import { v4 as uuid } from "uuid";
import {
ITelemetryBaseLogger,
ITelemetryLogger,
ITelemetryProperties,
TelemetryEventCategory,
Expand Down Expand Up @@ -123,6 +124,11 @@ export interface IContainerLoadOptions {
* Loads the Container in paused state if true, unpaused otherwise.
*/
loadMode?: IContainerLoadMode;
/**
* A logger that the container will use for logging operations. If not provided, the container will
* use the loader's logger, `Loader.services.subLogger`.
*/
baseLogger?: ITelemetryBaseLogger;
}

export interface IContainerConfig {
Expand All @@ -136,6 +142,11 @@ export interface IContainerConfig {
* Serialized state from a previous instance of this container
*/
serializedContainerState?: IPendingContainerState;
/**
* A logger that the container will use for logging operations. If not provided, the container will
* use the loader's logger, `Loader.services.subLogger`.
*/
baseLogger?: ITelemetryBaseLogger;
}

/**
Expand Down Expand Up @@ -288,6 +299,7 @@ export class Container
resolvedUrl: loadOptions.resolvedUrl,
canReconnect: loadOptions.canReconnect,
serializedContainerState: pendingLocalState,
baseLogger: loadOptions.baseLogger,
},
protocolHandlerBuilder,
);
Expand Down Expand Up @@ -625,36 +637,41 @@ export class Container
}`;
// Need to use the property getter for docId because for detached flow we don't have the docId initially.
// We assign the id later so property getter is used.
this.subLogger = ChildLogger.create(loader.services.subLogger, undefined, {
all: {
clientType, // Differentiating summarizer container from main container
containerId: uuid(),
docId: () => this._resolvedUrl?.id ?? undefined,
containerAttachState: () => this._attachState,
containerLifecycleState: () => this._lifecycleState,
containerConnectionState: () => ConnectionState[this.connectionState],
serializedContainer: config.serializedContainerState !== undefined,
},
// we need to be judicious with our logging here to avoid generating too much data
// all data logged here should be broadly applicable, and not specific to a
// specific error or class of errors
error: {
// load information to associate errors with the specific load point
dmInitialSeqNumber: () => this._deltaManager?.initialSequenceNumber,
dmLastProcessedSeqNumber: () => this._deltaManager?.lastSequenceNumber,
dmLastKnownSeqNumber: () => this._deltaManager?.lastKnownSeqNumber,
containerLoadedFromVersionId: () => this.loadedFromVersion?.id,
containerLoadedFromVersionDate: () => this.loadedFromVersion?.date,
// message information to associate errors with the specific execution state
// dmLastMsqSeqNumber: if present, same as dmLastProcessedSeqNumber
dmLastMsqSeqNumber: () => this.deltaManager?.lastMessage?.sequenceNumber,
dmLastMsqSeqTimestamp: () => this.deltaManager?.lastMessage?.timestamp,
dmLastMsqSeqClientId: () => this.deltaManager?.lastMessage?.clientId,
dmLastMsgClientSeq: () => this.deltaManager?.lastMessage?.clientSequenceNumber,
connectionStateDuration: () =>
performance.now() - this.connectionTransitionTimes[this.connectionState],
this.subLogger = ChildLogger.create(
// If a baseLogger was provided, use it; otherwise use the loader's logger.
config.baseLogger ?? loader.services.subLogger,
undefined,
{
all: {
clientType, // Differentiating summarizer container from main container
containerId: uuid(),
docId: () => this._resolvedUrl?.id ?? undefined,
containerAttachState: () => this._attachState,
containerLifecycleState: () => this._lifecycleState,
containerConnectionState: () => ConnectionState[this.connectionState],
serializedContainer: config.serializedContainerState !== undefined,
},
// we need to be judicious with our logging here to avoid generating too much data
// all data logged here should be broadly applicable, and not specific to a
// specific error or class of errors
error: {
// load information to associate errors with the specific load point
dmInitialSeqNumber: () => this._deltaManager?.initialSequenceNumber,
dmLastProcessedSeqNumber: () => this._deltaManager?.lastSequenceNumber,
dmLastKnownSeqNumber: () => this._deltaManager?.lastKnownSeqNumber,
containerLoadedFromVersionId: () => this.loadedFromVersion?.id,
containerLoadedFromVersionDate: () => this.loadedFromVersion?.date,
// message information to associate errors with the specific execution state
// dmLastMsqSeqNumber: if present, same as dmLastProcessedSeqNumber
dmLastMsqSeqNumber: () => this.deltaManager?.lastMessage?.sequenceNumber,
dmLastMsqSeqTimestamp: () => this.deltaManager?.lastMessage?.timestamp,
dmLastMsqSeqClientId: () => this.deltaManager?.lastMessage?.clientId,
dmLastMsgClientSeq: () => this.deltaManager?.lastMessage?.clientSequenceNumber,
connectionStateDuration: () =>
performance.now() - this.connectionTransitionTimes[this.connectionState],
},
},
});
);

// Prefix all events in this file with container-loader
this.mc = loggerToMonitoringContext(ChildLogger.create(this.subLogger, "Container"));
Expand Down
1 change: 1 addition & 0 deletions packages/loader/container-loader/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ export class Loader implements IHostLoader {
resolvedUrl: resolved,
version: request.headers?.[LoaderHeader.version] ?? undefined,
loadMode: request.headers?.[LoaderHeader.loadMode],
baseLogger: request.headers?.["fluid-base-logger"],
},
pendingLocalState,
this.protocolHandlerBuilder,
Expand Down