/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import { type ITelemetryBaseEvent, type ITelemetryBaseLogger, LogLevel, type Tagged, type TelemetryBaseEventPropertyType } from "@fluidframework/core-interfaces"; import type { ITelemetryLoggerExt, ITelemetryPropertiesExt, TelemetryLoggerExt, TelemetryEventPropertyTypeExt } from "./telemetryTypes.js"; import type { ITelemetryErrorEventExt, ITelemetryGenericEventExt, ITelemetryPerformanceEventExt } from "./telemetryTypesUndeprecated.js"; /** * Type erase a {@link TelemetryLoggerExt} to an {@link ITelemetryLoggerExt}. * @internal */ export declare function toITelemetryLoggerExt(logger: TelemetryLoggerExt): ITelemetryLoggerExt; /** * Un-type-erase the {@link ITelemetryLoggerExt}. * @remarks * This is the extraction helper as documented by {@link @fluidframework/core-interfaces#BrandedType}. * * @typeParam options - options for the extraction, currently only supports making * the output possibly undefined (when `PossiblyUndefined: true`), which is useful * for cases where we want to allow passing `undefined` through. * * @privateRemarks `ITelemetryLoggerExt` is not currently a branded type, but will * be when the breaking change is made. At that time, use of this helper will be * required. * * @internal */ export declare function extractTelemetryLoggerExt(input: ITelemetryLoggerExt | TelemetryLoggerExt | (options["PossiblyUndefined"] extends true ? undefined : never)): TelemetryLoggerExt | (options["PossiblyUndefined"] extends true ? undefined : never); /** * Broad classifications to be applied to individual properties as they're prepared to be logged to telemetry. * * @privateRemarks Please do not modify existing entries, to maintain backwards compatibility. * * @internal */ export declare enum TelemetryDataTag { /** * Data containing terms or IDs from code packages that may have been dynamically loaded */ CodeArtifact = "CodeArtifact", /** * Personal data of a variety of classifications that pertains to the user */ UserData = "UserData" } /** * @legacy * @beta */ export type TelemetryEventPropertyTypes = ITelemetryPropertiesExt[string]; /** * @legacy * @beta */ export type ITelemetryLoggerPropertyBag = Record TelemetryEventPropertyTypes)>; /** * @legacy * @beta * * @privateRemarks * This is exposed to support {@link createChildLogger} properties parameter. */ export interface ITelemetryLoggerPropertyBags { all?: ITelemetryLoggerPropertyBag; error?: ITelemetryLoggerPropertyBag; } /** * Attempts to parse number from string. * If it fails, it will return the original string. * * @remarks * Used to make telemetry data typed (and support math operations, like comparison), * in places where we do expect numbers (like contentsize/duration property in http header). * * @internal */ export declare function numberFromString(str: string | null | undefined): string | number | undefined; /** * @internal */ export declare function formatTick(tick: number): number; /** * String used to concatenate the namespace of parent loggers and their child loggers. * @internal */ export declare const eventNamespaceSeparator = ":"; /** * TelemetryLogger class contains various helper telemetry methods, * encoding in one place schemas for various types of Fluid telemetry events. * Creates sub-logger that appends properties to all events */ export declare abstract class TelemetryLogger implements TelemetryLoggerExt { protected readonly namespace?: string | undefined; protected readonly properties?: ITelemetryLoggerPropertyBags | undefined; /** * {@inheritDoc eventNamespaceSeparator} */ static readonly eventNamespaceSeparator = ":"; static sanitizePkgName(name: string): string; /** * Take an unknown error object and add the appropriate info from it to the event. Message and stack will be copied * over from the error object, along with other telemetry properties if it's an ILoggingError. * @param event - Event being logged * @param error - Error to extract info from * @param fetchStack - Whether to fetch the current callstack if error.stack is undefined */ static prepareErrorObject(event: ITelemetryBaseEvent, error: unknown, fetchStack: boolean): void; constructor(namespace?: string | undefined, properties?: ITelemetryLoggerPropertyBags | undefined); /** * Send an event with the logger * * @param event - the event to send */ abstract send(event: ITelemetryBaseEvent, logLevel?: LogLevel): void; /** * Send a telemetry event with the logger * * @param event - the event to send * @param error - optional error object to log * @param logLevel - optional level of the log. If the event's category is `error`, * the logLevel will be upgraded to {@link @fluidframework/core-interfaces#LogLevelConst.essential | LogLevel.essential}. */ sendTelemetryEvent(event: ITelemetryGenericEventExt, error?: unknown, logLevel?: typeof LogLevel.verbose | typeof LogLevel.info): void; /** * Send a telemetry event with the logger * * @param event - the event to send * @param error - optional error object to log * @param logLevel - level of the log. */ private sendTelemetryEventCore; /** * Send an error telemetry event with the logger * * @param event - the event to send * @param error - optional error object to log */ sendErrorEvent(event: ITelemetryErrorEventExt, error?: unknown): void; /** * Send a performance telemetry event with the logger * * @param event - Event to send * @param error - optional error object to log * @param logLevel - optional level of the log. If the event's category is `error`, * the logLevel will be upgraded to {@link @fluidframework/core-interfaces#LogLevelConst.essential | LogLevel.essential}. */ sendPerformanceEvent(event: ITelemetryPerformanceEventExt, error?: unknown, logLevel?: typeof LogLevel.verbose | typeof LogLevel.info): void; protected prepareEvent(event: ITelemetryBaseEvent): ITelemetryBaseEvent; private extendProperties; } /** * @deprecated 0.56, remove TaggedLoggerAdapter once its usage is removed from * container-runtime. Issue: #8191 * TaggedLoggerAdapter class can add tag handling to your logger. * * @internal */ export declare class TaggedLoggerAdapter implements ITelemetryBaseLogger { private readonly logger; constructor(logger: ITelemetryBaseLogger); /** * {@inheritDoc @fluidframework/core-interfaces#ITelemetryBaseLogger.send} */ send(eventWithTagsMaybe: ITelemetryBaseEvent): void; } /** * Create a child logger based on the provided props object. * * @remarks * Passing in no props object (i.e. undefined) will return a logger that is effectively a no-op. * * @param props - logger is the base logger the child will log to after it's processing, namespace will be prefixed to all event names, properties are default properties that will be applied events. * * @internal * * @privateRemarks * Return type is both TelemetryLoggerExt and ITelemetryLoggerExt to allow for * easier internal usage without needing to type erase or un-type-erase the * logger. * * If always creating a child logger for direct external exposure, consider * using {@link createChildLogger} from /legacy API instead, which returns * exactly an {@link ITelemetryLoggerExt}. */ export declare function createChildLogger(props?: { logger?: ITelemetryBaseLogger; namespace?: string; properties?: ITelemetryLoggerPropertyBags; }): TelemetryLoggerExt & ITelemetryLoggerExt; /** * ChildLogger class contains various helper telemetry methods, * encoding in one place schemas for various types of Fluid telemetry events. * Creates sub-logger that appends properties to all events. */ export declare class ChildLogger extends TelemetryLogger { protected readonly baseLogger: ITelemetryBaseLogger; /** * Create child logger * @param baseLogger - Base logger to use to output events. If undefined, proper child logger * is created, but it does not send telemetry events anywhere. * @param namespace - Telemetry event name prefix to add to all events * @param properties - Base properties to add to all events */ static create(baseLogger?: ITelemetryBaseLogger, namespace?: string, properties?: ITelemetryLoggerPropertyBags): TelemetryLogger; private constructor(); get minLogLevel(): LogLevel | undefined; private shouldFilterOutEvent; /** * Send an event with the logger * * @param event - the event to send */ send(event: ITelemetryBaseEvent, logLevel?: LogLevel): void; } /** * Input properties for {@link createMultiSinkLogger}. * * @internal */ export interface MultiSinkLoggerProperties { /** * Will be prefixed to all event names. */ namespace?: string; /** * Default properties that will be applied to all events flowing through this logger. */ properties?: ITelemetryLoggerPropertyBags; /** * The base loggers that this logger will forward the logs to, after it processes them. */ loggers?: (ITelemetryBaseLogger | undefined)[]; /** * If true, the logger will attempt to copy the custom properties (if they are of a known type, i.e. one from this package) of all the base loggers passed to it, to apply them itself to logs that flow through. */ tryInheritProperties?: true; } /** * Create a logger which logs to multiple other loggers based on the provided props object. * * @internal */ export declare function createMultiSinkLogger(props: MultiSinkLoggerProperties): TelemetryLoggerExt; /** * Multi-sink logger * Takes multiple ITelemetryBaseLogger objects (sinks) and logs all events into each sink */ export declare class MultiSinkLogger extends TelemetryLogger { protected loggers: ITelemetryBaseLogger[]; private _minLogLevelOfAllLoggers; /** * Create multiple sink logger (i.e. logger that sends events to multiple sinks) * @param namespace - Telemetry event name prefix to add to all events * @param properties - Base properties to add to all events * @param loggers - The list of loggers to use as sinks * @param tryInheritProperties - Will attempted to copy those loggers properties to this loggers if they are of a known type e.g. one from this package */ constructor(namespace?: string, properties?: ITelemetryLoggerPropertyBags, loggers?: ITelemetryBaseLogger[], tryInheritProperties?: true); get minLogLevel(): LogLevel; private calculateMinLogLevel; /** * Add logger to send all events to * @param logger - Logger to add */ addLogger(logger?: ITelemetryBaseLogger): void; /** * Send an event to the loggers * * @param event - the event to send to all the registered logger */ send(event: ITelemetryBaseEvent, logLevel?: LogLevel): void; } /** * Describes what events {@link PerformanceEvent} should log. * * @remarks * By default, all events are logged, but the client can override this behavior. * * For example, there is rarely a need to record a start event, as we're really after * success / failure tracking, including duration (on success). * * @internal */ export interface IPerformanceEventMarkers { start?: true; end?: true; cancel?: "generic" | "error"; /** * If specified, _end events whose duration is greater than this threshold are logged as essential. */ endEventEssentialDurationThresholdMs?: number; } /** * Helper class to log performance events. * * @internal */ export declare class PerformanceEvent { private readonly logger; private readonly markers; private readonly emitLogs; private readonly logLevel; /** * Creates an instance of {@link PerformanceEvent} and starts measurements * @param logger - the logger to be used for publishing events * @param event - the logging event details which will be published with the performance measurements * @param markers - See {@link IPerformanceEventMarkers} * @param recordHeapSize - whether or not to also record memory performance * @param emitLogs - should this instance emit logs. If set to false, logs will not be emitted to the logger, * but measurements will still be performed and any specified markers will be generated. * @param logLevel - optional {@link LogLevel} for events emitted by this performance event. * If unspecified, {@link @fluidframework/core-interfaces#LogLevelConst.essential | LogLevel.essential} will be used. * @returns An instance of {@link PerformanceEvent} */ static start(logger: TelemetryLoggerExt | ITelemetryLoggerExt, event: ITelemetryGenericEventExt, markers?: IPerformanceEventMarkers, emitLogs?: boolean, logLevel?: typeof LogLevel.verbose | typeof LogLevel.info): PerformanceEvent; /** * Measure a synchronous task * @param logger - the logger to be used for publishing events * @param event - the logging event details which will be published with the performance measurements * @param callback - the task to be executed and measured * @param markers - See {@link IPerformanceEventMarkers} * @param sampleThreshold - events with the same name and category will be sent to the logger * only when we hit this many executions of the task. If unspecified, all events will be sent. * @param logLevel - optional {@link LogLevel} for events emitted by this performance event. * If unspecified, {@link @fluidframework/core-interfaces#LogLevelConst.essential | LogLevel.essential} will be used. * @returns The results of the executed task * * @remarks Note that if the "same" event (category + eventName) would be emitted by different * tasks (`callback`), `sampleThreshold` is still applied only based on the event's category + eventName, * so executing either of the tasks will increase the internal counter and they * effectively "share" the sampling rate for the event. */ static timedExec(logger: TelemetryLoggerExt, event: ITelemetryGenericEventExt, callback: (event: PerformanceEvent) => T, markers?: IPerformanceEventMarkers, sampleThreshold?: number, logLevel?: typeof LogLevel.verbose | typeof LogLevel.info): T; /** * Measure an asynchronous task * @param logger - the logger to be used for publishing events * @param event - the logging event details which will be published with the performance measurements * @param callback - the task to be executed and measured * @param markers - See {@link IPerformanceEventMarkers} * @param recordHeapSize - whether or not to also record memory performance * @param sampleThreshold - events with the same name and category will be sent to the logger * only when we hit this many executions of the task. If unspecified, all events will be sent. * @param logLevel - optional {@link LogLevel} for events emitted by this performance event. * If unspecified, {@link @fluidframework/core-interfaces#LogLevelConst.essential | LogLevel.essential} will be used. * @returns The results of the executed task * * @remarks Note that if the "same" event (category + eventName) would be emitted by different * tasks (`callback`), `sampleThreshold` is still applied only based on the event's category + eventName, * so executing either of the tasks will increase the internal counter and they * effectively "share" the sampling rate for the event. */ static timedExecAsync(logger: TelemetryLoggerExt | ITelemetryLoggerExt, event: ITelemetryGenericEventExt, callback: (event: PerformanceEvent) => Promise, markers?: IPerformanceEventMarkers, sampleThreshold?: number, logLevel?: typeof LogLevel.verbose | typeof LogLevel.info): Promise; get duration(): number; private event?; private readonly startTime; private startMark?; private constructor(); reportProgress(props?: ITelemetryPropertiesExt, eventNameSuffix?: string): void; private autoEnd; end(props?: ITelemetryPropertiesExt): void; private performanceEndMark; cancel(props?: ITelemetryPropertiesExt, error?: unknown): void; /** * Report the event, if it hasn't already been reported. */ reportEvent(eventNameSuffix: string, props?: ITelemetryPropertiesExt, error?: unknown): void; /** * Get the LogLevel for performance events. * @param eventNameSuffix - The suffix of the event name. * @param event - The telemetry performance event. * @returns The log level for the event. * */ private getLogLevel; private static readonly eventHits; private static shouldReport; } /** * Takes in value, and does one of 4 things. * if value is of primitive type - returns the original value. * If the value is a flat array or object - returns a stringified version of the array/object. * If the value is an object of type Tagged - returns the object * with its values recursively converted to base property Type. * If none of these cases are reached - returns an error string * @param x - value passed in to convert to a base property type */ export declare function convertToBasePropertyType(x: TelemetryEventPropertyTypeExt | Tagged): TelemetryBaseEventPropertyType | Tagged; /** * Tags all given `values` with the same `tag`. * * @param tag - The tag with which all `values` will be annotated. * @param values - The values to be tagged. * * @remarks * It supports properties of type {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType}, * as well as callbacks that return that type. * * @example Sample usage * ```typescript * { * // ...Other properties being added to a telemetry event * ...tagData("someTag", {foo: 1, bar: 2}), * // ... * } * ``` * This will result in `foo` and `bar` added to the event with their values tagged. * * @internal */ export declare const tagData: TelemetryBaseEventPropertyType)>>(tag: T, values: V) => { [P in keyof V]: (V[P] extends () => TelemetryBaseEventPropertyType ? () => { value: ReturnType; tag: T; } : { value: Exclude; tag: T; }) | (V[P] extends undefined ? undefined : never); }; /** * Tags all provided `values` as {@link TelemetryDataTag.CodeArtifact}. * * @param values - The values to be tagged. * * @remarks * It supports properties of type {@link @fluidframework/core-interfaces#TelemetryBaseEventPropertyType}, * as well as callbacks that return that type. * * @example Sample usage * ```typescript * { * // ...Other properties being added to a telemetry event * ...tagCodeArtifacts("someTag", {foo: 1, bar: 2}), * // ... * } * ``` * This will result in `foo` and `bar` added to the event with their values tagged as {@link TelemetryDataTag.CodeArtifact}. * * @see {@link tagData} * * @internal */ export declare const tagCodeArtifacts: TelemetryBaseEventPropertyType)>>(values: T) => { [P in keyof T]: (T[P] extends () => TelemetryBaseEventPropertyType ? () => { value: ReturnType; tag: TelemetryDataTag.CodeArtifact; } : { value: Exclude; tag: TelemetryDataTag.CodeArtifact; }) | (T[P] extends undefined ? undefined : never); }; //# sourceMappingURL=logger.d.ts.map