@fluidframework/telemetry-utils 2.0.0-dev-rc.1.0.0.228517 → 2.0.0-dev-rc.2.0.0.245554
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.
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -2
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/telemetry-utils.api.md +14 -33
- package/dist/config.d.ts +14 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -4
- package/dist/config.js.map +1 -1
- package/dist/error.d.ts +2 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +9 -9
- package/dist/error.js.map +1 -1
- package/dist/errorLogging.d.ts +4 -4
- package/dist/errorLogging.d.ts.map +1 -1
- package/dist/errorLogging.js +19 -60
- package/dist/errorLogging.js.map +1 -1
- package/dist/eventEmitterWithErrorHandling.d.ts +1 -1
- package/dist/eventEmitterWithErrorHandling.js +1 -1
- package/dist/eventEmitterWithErrorHandling.js.map +1 -1
- package/dist/events.d.ts +2 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/fluidErrorBase.d.ts +4 -3
- package/dist/fluidErrorBase.d.ts.map +1 -1
- package/dist/fluidErrorBase.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -59
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -23
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +12 -29
- package/dist/logger.js.map +1 -1
- package/dist/mockLogger.d.ts +1 -1
- package/dist/mockLogger.d.ts.map +1 -1
- package/dist/mockLogger.js +2 -2
- package/dist/mockLogger.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/sampledTelemetryHelper.d.ts +4 -4
- package/dist/sampledTelemetryHelper.d.ts.map +1 -1
- package/dist/sampledTelemetryHelper.js +1 -1
- package/dist/sampledTelemetryHelper.js.map +1 -1
- package/dist/telemetry-utils-alpha.d.ts +7 -15
- package/dist/telemetry-utils-beta.d.ts +7 -32
- package/dist/telemetry-utils-public.d.ts +7 -32
- package/dist/telemetry-utils-untrimmed.d.ts +25 -50
- package/dist/thresholdCounter.d.ts +1 -1
- package/dist/thresholdCounter.d.ts.map +1 -1
- package/dist/thresholdCounter.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/utils.d.ts +1 -20
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -27
- package/dist/utils.js.map +1 -1
- package/lib/config.d.ts +14 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +15 -1
- package/lib/config.js.map +1 -1
- package/lib/error.d.ts +2 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +1 -1
- package/lib/error.js.map +1 -1
- package/lib/errorLogging.d.ts +4 -4
- package/lib/errorLogging.d.ts.map +1 -1
- package/lib/errorLogging.js +15 -56
- package/lib/errorLogging.js.map +1 -1
- package/lib/eventEmitterWithErrorHandling.d.ts +1 -1
- package/lib/eventEmitterWithErrorHandling.js +1 -1
- package/lib/eventEmitterWithErrorHandling.js.map +1 -1
- package/lib/events.d.ts +2 -3
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js.map +1 -1
- package/lib/fluidErrorBase.d.ts +4 -3
- package/lib/fluidErrorBase.d.ts.map +1 -1
- package/lib/fluidErrorBase.js.map +1 -1
- package/lib/index.d.ts +12 -12
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -11
- package/lib/index.js.map +1 -1
- package/lib/logger.d.ts +7 -23
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +3 -19
- package/lib/logger.js.map +1 -1
- package/lib/mockLogger.d.ts +1 -1
- package/lib/mockLogger.d.ts.map +1 -1
- package/lib/mockLogger.js +1 -1
- package/lib/mockLogger.js.map +1 -1
- package/lib/sampledTelemetryHelper.d.ts +4 -4
- package/lib/sampledTelemetryHelper.d.ts.map +1 -1
- package/lib/sampledTelemetryHelper.js +1 -1
- package/lib/sampledTelemetryHelper.js.map +1 -1
- package/lib/{telemetry-utils-alpha.d.mts → telemetry-utils-alpha.d.ts} +7 -15
- package/lib/{telemetry-utils-beta.d.mts → telemetry-utils-beta.d.ts} +7 -32
- package/lib/{telemetry-utils-public.d.mts → telemetry-utils-public.d.ts} +7 -32
- package/lib/{telemetry-utils-untrimmed.d.mts → telemetry-utils-untrimmed.d.ts} +25 -50
- package/lib/test/EventEmitterWithErrorHandling.spec.js +86 -0
- package/lib/test/EventEmitterWithErrorHandling.spec.js.map +1 -0
- package/lib/test/childLogger.spec.js +233 -0
- package/lib/test/childLogger.spec.js.map +1 -0
- package/lib/test/config.spec.js +229 -0
- package/lib/test/config.spec.js.map +1 -0
- package/lib/test/error.spec.js +161 -0
- package/lib/test/error.spec.js.map +1 -0
- package/lib/test/errorLogging.spec.js +801 -0
- package/lib/test/errorLogging.spec.js.map +1 -0
- package/lib/test/errorTypeLoggingTest.spec.js +107 -0
- package/lib/test/errorTypeLoggingTest.spec.js.map +1 -0
- package/lib/test/mockLogger.spec.js +164 -0
- package/lib/test/mockLogger.spec.js.map +1 -0
- package/lib/test/multiSinkLogger.spec.js +84 -0
- package/lib/test/multiSinkLogger.spec.js.map +1 -0
- package/lib/test/performanceEvent.spec.js +86 -0
- package/lib/test/performanceEvent.spec.js.map +1 -0
- package/lib/test/sampledTelemetryHelper.spec.js +169 -0
- package/lib/test/sampledTelemetryHelper.spec.js.map +1 -0
- package/lib/test/telemetryLogger.spec.js +357 -0
- package/lib/test/telemetryLogger.spec.js.map +1 -0
- package/lib/test/thresholdCounter.spec.js +51 -0
- package/lib/test/thresholdCounter.spec.js.map +1 -0
- package/lib/test/types/validateTelemetryUtilsPrevious.generated.js +132 -0
- package/lib/test/types/validateTelemetryUtilsPrevious.generated.js.map +1 -0
- package/lib/test/utils.spec.js +284 -0
- package/lib/test/utils.spec.js.map +1 -0
- package/lib/thresholdCounter.d.ts +1 -1
- package/lib/thresholdCounter.d.ts.map +1 -1
- package/lib/thresholdCounter.js.map +1 -1
- package/lib/utils.d.ts +1 -20
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -24
- package/lib/utils.js.map +1 -1
- package/package.json +75 -26
- package/src/config.ts +20 -2
- package/src/error.ts +2 -2
- package/src/errorLogging.ts +27 -68
- package/src/eventEmitterWithErrorHandling.ts +1 -1
- package/src/events.ts +2 -4
- package/src/fluidErrorBase.ts +4 -3
- package/src/index.ts +13 -13
- package/src/logger.ts +12 -28
- package/src/mockLogger.ts +2 -2
- package/src/sampledTelemetryHelper.ts +10 -11
- package/src/thresholdCounter.ts +1 -1
- package/src/utils.ts +3 -36
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -3
- package/tsconfig.esnext.json +0 -7
- /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
package/lib/mockLogger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tLogLevel,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { ITelemetryLoggerExt, ITelemetryPropertiesExt } from \"./telemetryTypes\";\nimport { createChildLogger } from \"./logger\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n *\n * @internal\n */\nexport class MockLogger implements ITelemetryBaseLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor(public readonly minLogLevel?: LogLevel) {}\n\n\tclear(): void {\n\t\tthis.events = [];\n\t}\n\n\ttoTelemetryLogger(): ITelemetryLoggerExt {\n\t\treturn createChildLogger({ logger: this });\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/**\n\t * Asserts that matchEvents is true, and prints the actual/expected output if not.\n\t */\n\tassertMatch(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/**\n\t * Asserts that matchAnyEvent is true, and prints the actual/expected output if not.\n\t */\n\tassertMatchAny(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\treturn (\n\t\t\texpectedEvents.length === this.events.length &&\n\t\t\tthis.matchEvents(expectedEvents, inlineDetailsProp)\n\t\t);\n\t}\n\n\t/**\n\t * Asserts that matchEvents is true, and prints the actual/expected output if not\n\t */\n\tassertMatchStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not\n\t */\n\tassertMatchNone(\n\t\tdisallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean,\n\t): number {\n\t\tlet iExpectedEvent = 0;\n\t\tfor (const event of this.events) {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t}\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t\tinlineDetailsProp: boolean,\n\t): boolean {\n\t\tconst { details, ...actualForMatching } = actual;\n\t\t// \"details\" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.\n\t\t// Some of the properties in the expected event may be inside \"details\". So, if inlineDetailsProp is true,\n\t\t// extract the properties from \"details\" in the actual event and inline them in the actual event.\n\t\tif (inlineDetailsProp && details !== undefined) {\n\t\t\tassert(\n\t\t\t\ttypeof details === \"string\",\n\t\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t\t0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,\n\t\t\t);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconst detailsExpanded = JSON.parse(details);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\treturn matchObjects({ ...actualForMatching, ...detailsExpanded }, expected);\n\t\t}\n\t\treturn matchObjects(actual, expected);\n\t}\n}\n\nfunction matchObjects(actual: ITelemetryPropertiesExt, expected: ITelemetryPropertiesExt): boolean {\n\tfor (const [expectedKey, expectedValue] of Object.entries(expected)) {\n\t\tconst actualValue = actual[expectedKey];\n\t\tif (\n\t\t\t!Array.isArray(expectedValue) &&\n\t\t\texpectedValue !== null &&\n\t\t\ttypeof expectedValue === \"object\"\n\t\t) {\n\t\t\tif (\n\t\t\t\tArray.isArray(actualValue) ||\n\t\t\t\tactualValue === null ||\n\t\t\t\ttypeof actualValue !== \"object\" ||\n\t\t\t\t!matchObjects(\n\t\t\t\t\tactualValue as ITelemetryPropertiesExt,\n\t\t\t\t\texpectedValue as ITelemetryPropertiesExt,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tITelemetryBaseEvent,\n\tITelemetryBaseLogger,\n\tLogLevel,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { ITelemetryLoggerExt, ITelemetryPropertiesExt } from \"./telemetryTypes.js\";\nimport { createChildLogger } from \"./logger.js\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n *\n * @internal\n */\nexport class MockLogger implements ITelemetryBaseLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor(public readonly minLogLevel?: LogLevel) {}\n\n\tclear(): void {\n\t\tthis.events = [];\n\t}\n\n\ttoTelemetryLogger(): ITelemetryLoggerExt {\n\t\treturn createChildLogger({ logger: this });\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/**\n\t * Asserts that matchEvents is true, and prints the actual/expected output if not.\n\t */\n\tassertMatch(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/**\n\t * Asserts that matchAnyEvent is true, and prints the actual/expected output if not.\n\t */\n\tassertMatchAny(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\treturn (\n\t\t\texpectedEvents.length === this.events.length &&\n\t\t\tthis.matchEvents(expectedEvents, inlineDetailsProp)\n\t\t);\n\t}\n\n\t/**\n\t * Asserts that matchEvents is true, and prints the actual/expected output if not\n\t */\n\tassertMatchStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not\n\t */\n\tassertMatchNone(\n\t\tdisallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t): void {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean,\n\t): number {\n\t\tlet iExpectedEvent = 0;\n\t\tfor (const event of this.events) {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t}\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t\tinlineDetailsProp: boolean,\n\t): boolean {\n\t\tconst { details, ...actualForMatching } = actual;\n\t\t// \"details\" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.\n\t\t// Some of the properties in the expected event may be inside \"details\". So, if inlineDetailsProp is true,\n\t\t// extract the properties from \"details\" in the actual event and inline them in the actual event.\n\t\tif (inlineDetailsProp && details !== undefined) {\n\t\t\tassert(\n\t\t\t\ttypeof details === \"string\",\n\t\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t\t0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,\n\t\t\t);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconst detailsExpanded = JSON.parse(details);\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\treturn matchObjects({ ...actualForMatching, ...detailsExpanded }, expected);\n\t\t}\n\t\treturn matchObjects(actual, expected);\n\t}\n}\n\nfunction matchObjects(actual: ITelemetryPropertiesExt, expected: ITelemetryPropertiesExt): boolean {\n\tfor (const [expectedKey, expectedValue] of Object.entries(expected)) {\n\t\tconst actualValue = actual[expectedKey];\n\t\tif (\n\t\t\t!Array.isArray(expectedValue) &&\n\t\t\texpectedValue !== null &&\n\t\t\ttypeof expectedValue === \"object\"\n\t\t) {\n\t\t\tif (\n\t\t\t\tArray.isArray(actualValue) ||\n\t\t\t\tactualValue === null ||\n\t\t\t\ttypeof actualValue !== \"object\" ||\n\t\t\t\t!matchObjects(\n\t\t\t\t\tactualValue as ITelemetryPropertiesExt,\n\t\t\t\t\texpectedValue as ITelemetryPropertiesExt,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n"]}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { ITelemetryLoggerExt } from "./telemetryTypes";
|
|
5
|
+
import type { ITelemetryBaseProperties, IDisposable } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { ITelemetryLoggerExt, type ITelemetryGenericEventExt } from "./telemetryTypes.js";
|
|
7
7
|
/**
|
|
8
8
|
* Helper class that executes a specified code block and writes an
|
|
9
9
|
* {@link @fluidframework/core-interfaces#ITelemetryPerformanceEvent} to a specified logger every time a specified
|
|
@@ -38,10 +38,10 @@ export declare class SampledTelemetryHelper implements IDisposable {
|
|
|
38
38
|
* properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
|
|
39
39
|
* have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
|
|
40
40
|
* reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
|
|
41
|
-
* them is specified as a key in one of the
|
|
41
|
+
* them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
|
|
42
42
|
* ignored.
|
|
43
43
|
*/
|
|
44
|
-
constructor(eventBase:
|
|
44
|
+
constructor(eventBase: ITelemetryGenericEventExt, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryBaseProperties>);
|
|
45
45
|
/**
|
|
46
46
|
* Executes the specified code and keeps track of execution time statistics.
|
|
47
47
|
* If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampledTelemetryHelper.d.ts","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"sampledTelemetryHelper.d.ts","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE7F,OAAO,EACN,mBAAmB,EACnB,KAAK,yBAAyB,EAE9B,MAAM,qBAAqB,CAAC;AAoC7B;;;;;;;;;;GAUG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IAwBxD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IA3BrC,QAAQ,EAAE,OAAO,CAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IAEnE;;;;;;;;;;;;;;;;;OAiBG;gBAEe,SAAS,EAAE,yBAAyB,EACpC,MAAM,EAAE,mBAAmB,EAC3B,eAAe,EAAE,MAAM,EACvB,uBAAuB,GAAE,OAAe,EACxC,mBAAmB,wCAA8C;IAGnF;;;;;;;;;OASG;IACI,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,GAAE,MAAW,GAAG,CAAC;IA0BjE,OAAO,CAAC,WAAW;IAoBZ,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI;CAG/C"}
|
|
@@ -30,7 +30,7 @@ export class SampledTelemetryHelper {
|
|
|
30
30
|
* properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
|
|
31
31
|
* have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
|
|
32
32
|
* reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
|
|
33
|
-
* them is specified as a key in one of the
|
|
33
|
+
* them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
|
|
34
34
|
* ignored.
|
|
35
35
|
*/
|
|
36
36
|
constructor(eventBase, logger, sampleThreshold, includeAggregateMetrics = false, perBucketProperties = new Map()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampledTelemetryHelper.js","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"sampledTelemetryHelper.js","sourceRoot":"","sources":["../src/sampledTelemetryHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAyC3D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,sBAAsB;IAKlC;;;;;;;;;;;;;;;;;OAiBG;IACH,YACkB,SAAoC,EACpC,MAA2B,EAC3B,eAAuB,EACvB,0BAAmC,KAAK,EACxC,sBAAsB,IAAI,GAAG,EAAoC;QAJjE,cAAS,GAAT,SAAS,CAA2B;QACpC,WAAM,GAAN,MAAM,CAAqB;QAC3B,oBAAe,GAAf,eAAe,CAAQ;QACvB,4BAAuB,GAAvB,uBAAuB,CAAiB;QACxC,wBAAmB,GAAnB,mBAAmB,CAA8C;QA3BnF,aAAQ,GAAY,KAAK,CAAC;QAET,oBAAe,GAAG,IAAI,GAAG,EAAwB,CAAC;IA0BhE,CAAC;IAEJ;;;;;;;;;OASG;IACI,OAAO,CAAI,aAAsB,EAAE,SAAiB,EAAE;QAC5D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE3C,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,SAAS,EAAE;YACpB,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;SACpC;QACD,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEtB,IAAI,IAAI,CAAC,uBAAuB,EAAE;YACjC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;YACpD,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC9D,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE;YACpC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;SACzB;QAED,OAAO,WAAW,CAAC;IACpB,CAAC;IAEO,WAAW,CAAC,MAAc;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,YAAY,KAAK,SAAS,EAAE;YAC/B,OAAO;SACP;QAED,IAAI,YAAY,CAAC,KAAK,KAAK,CAAC,EAAE;YAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE9D,MAAM,cAAc,GAAkC;gBACrD,GAAG,IAAI,CAAC,SAAS;gBACjB,GAAG,gBAAgB;gBACnB,GAAG,YAAY;aACf,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;YACjD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SACpC;IACF,CAAC;IAEM,OAAO,CAAC,KAAyB;QACvC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;YAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryBaseProperties, IDisposable } from \"@fluidframework/core-interfaces\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport {\n\tITelemetryLoggerExt,\n\ttype ITelemetryGenericEventExt,\n\ttype ITelemetryPerformanceEventExt,\n} from \"./telemetryTypes.js\";\n\n/**\n * @privateRemarks\n *\n * The names of the properties in this interface are the ones that will get stamped in the\n * telemetry event, changes should be considered carefully. The optional properties should\n * only be populated if 'includeAggregateMetrics' is true.\n */\ninterface Measurements {\n\t/**\n\t * The duration of the latest execution.\n\t */\n\tduration: number;\n\n\t/**\n\t * The number of executions since the last time an event was generated.\n\t */\n\tcount: number;\n\n\t/**\n\t * Total duration across all the executions since the last event was generated.\n\t */\n\ttotalDuration?: number;\n\n\t/**\n\t * Min duration across all the executions since the last event was generated.\n\t */\n\tminDuration?: number;\n\n\t/**\n\t * Max duration across all the executions since the last event was generated.\n\t */\n\tmaxDuration?: number;\n}\n\n/**\n * Helper class that executes a specified code block and writes an\n * {@link @fluidframework/core-interfaces#ITelemetryPerformanceEvent} to a specified logger every time a specified\n * number of executions is reached (or when the class is disposed).\n *\n * The `duration` field in the telemetry event is the duration of the latest execution (sample) of the specified\n * function. See the documentation of the `includeAggregateMetrics` parameter for additional details that can be\n * included.\n *\n * @internal\n */\nexport class SampledTelemetryHelper implements IDisposable {\n\tdisposed: boolean = false;\n\n\tprivate readonly measurementsMap = new Map<string, Measurements>();\n\n\t/**\n\t * @param eventBase -\n\t * Custom properties to include in the telemetry performance event when it is written.\n\t * @param logger -\n\t * The logger to use to write the telemetry performance event.\n\t * @param sampleThreshold -\n\t * Telemetry performance events will be generated every time we hit this many executions of the code block.\n\t * @param includeAggregateMetrics -\n\t * If set to `true`, the telemetry performance event will include aggregated metrics (total duration, min duration,\n\t * max duration) for all the executions in between generated events.\n\t * @param perBucketProperties -\n\t * Map of strings that represent different buckets (which can be specified when calling the 'measure' method), to\n\t * properties which should be added to the telemetry event for that bucket. If a bucket being measured does not\n\t * have an entry in this map, no additional properties will be added to its telemetry events. The following keys are\n\t * reserved for use by this class: \"duration\", \"count\", \"totalDuration\", \"minDuration\", \"maxDuration\". If any of\n\t * them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be\n\t * ignored.\n\t */\n\tpublic constructor(\n\t\tprivate readonly eventBase: ITelemetryGenericEventExt,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly sampleThreshold: number,\n\t\tprivate readonly includeAggregateMetrics: boolean = false,\n\t\tprivate readonly perBucketProperties = new Map<string, ITelemetryBaseProperties>(),\n\t) {}\n\n\t/**\n\t * Executes the specified code and keeps track of execution time statistics.\n\t * If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.\n\t *\n\t * @param codeToMeasure - The code to be executed and measured.\n\t * @param bucket - A key to track executions of the code block separately.\n\t * Each different value of this parameter has a separate set of executions and metrics tracked by the class.\n\t * If no such distinction needs to be made, do not provide a value.\n\t * @returns Whatever the passed-in code block returns.\n\t */\n\tpublic measure<T>(codeToMeasure: () => T, bucket: string = \"\"): T {\n\t\tconst start = performance.now();\n\t\tconst returnValue = codeToMeasure();\n\t\tconst duration = performance.now() - start;\n\n\t\tlet m = this.measurementsMap.get(bucket);\n\t\tif (m === undefined) {\n\t\t\tm = { count: 0, duration: -1 };\n\t\t\tthis.measurementsMap.set(bucket, m);\n\t\t}\n\t\tm.count++;\n\t\tm.duration = duration;\n\n\t\tif (this.includeAggregateMetrics) {\n\t\t\tm.totalDuration = (m.totalDuration ?? 0) + duration;\n\t\t\tm.minDuration = Math.min(m.minDuration ?? duration, duration);\n\t\t\tm.maxDuration = Math.max(m.maxDuration ?? 0, duration);\n\t\t}\n\n\t\tif (m.count >= this.sampleThreshold) {\n\t\t\tthis.flushBucket(bucket);\n\t\t}\n\n\t\treturn returnValue;\n\t}\n\n\tprivate flushBucket(bucket: string): void {\n\t\tconst measurements = this.measurementsMap.get(bucket);\n\t\tif (measurements === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (measurements.count !== 0) {\n\t\t\tconst bucketProperties = this.perBucketProperties.get(bucket);\n\n\t\t\tconst telemetryEvent: ITelemetryPerformanceEventExt = {\n\t\t\t\t...this.eventBase,\n\t\t\t\t...bucketProperties, // If the bucket doesn't exist and this is undefined, things work as expected\n\t\t\t\t...measurements,\n\t\t\t};\n\n\t\t\tthis.logger.sendPerformanceEvent(telemetryEvent);\n\t\t\tthis.measurementsMap.delete(bucket);\n\t\t}\n\t}\n\n\tpublic dispose(error?: Error | undefined): void {\n\t\tfor (const [k] of this.measurementsMap.entries()) this.flushBucket(k);\n\t}\n}\n"]}
|
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { ConfigTypes } from '@fluidframework/core-interfaces';
|
|
2
|
+
import type { EventEmitter } from '@fluid-internal/client-utils';
|
|
4
3
|
import { EventEmitterEventType } from '@fluid-internal/client-utils';
|
|
5
4
|
import { IConfigProviderBase } from '@fluidframework/core-interfaces';
|
|
6
|
-
import { IDisposable } from '@fluidframework/core-interfaces';
|
|
5
|
+
import type { IDisposable } from '@fluidframework/core-interfaces';
|
|
7
6
|
import { IErrorBase } from '@fluidframework/core-interfaces';
|
|
8
7
|
import { IEvent } from '@fluidframework/core-interfaces';
|
|
9
8
|
import { IGenericError } from '@fluidframework/core-interfaces';
|
|
10
|
-
import { ILoggingError } from '@fluidframework/core-interfaces';
|
|
9
|
+
import type { ILoggingError } from '@fluidframework/core-interfaces';
|
|
11
10
|
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
12
11
|
import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
|
|
13
12
|
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
14
13
|
import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
|
|
15
|
-
import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
|
|
16
|
-
import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
|
|
17
|
-
import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
|
|
18
|
-
import { ITelemetryProperties } from '@fluidframework/core-interfaces';
|
|
19
14
|
import { IUsageError } from '@fluidframework/core-interfaces';
|
|
20
15
|
import { Lazy } from '@fluidframework/core-utils';
|
|
21
16
|
import { LogLevel } from '@fluidframework/core-interfaces';
|
|
22
17
|
import { Tagged } from '@fluidframework/core-interfaces';
|
|
23
18
|
import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
|
|
24
|
-
import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
|
|
25
19
|
import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
26
20
|
|
|
27
21
|
/* Excluded from this release type: connectedEventName */
|
|
@@ -63,7 +57,7 @@ export declare function createChildLogger(props?: {
|
|
|
63
57
|
* @privateRemarks
|
|
64
58
|
* This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
|
|
65
59
|
* We should consider moving it to the `core-utils` package.
|
|
66
|
-
* @
|
|
60
|
+
* @alpha
|
|
67
61
|
*/
|
|
68
62
|
export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
|
|
69
63
|
private readonly errorHandler;
|
|
@@ -209,8 +203,6 @@ export declare interface ITelemetryPropertiesExt {
|
|
|
209
203
|
|
|
210
204
|
/* Excluded from this release type: LoggingError */
|
|
211
205
|
|
|
212
|
-
/* Excluded from this release type: logIfFalse */
|
|
213
|
-
|
|
214
206
|
/* Excluded from this release type: mixinMonitoringContext */
|
|
215
207
|
|
|
216
208
|
/* Excluded from this release type: MockLogger */
|
|
@@ -275,14 +267,14 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
|
|
|
275
267
|
*/
|
|
276
268
|
export declare type TelemetryEventPropertyTypes = ITelemetryBaseProperties[string];
|
|
277
269
|
|
|
278
|
-
/* Excluded from this release type: TelemetryNullLogger */
|
|
279
|
-
|
|
280
270
|
/* Excluded from this release type: ThresholdCounter */
|
|
281
271
|
|
|
282
272
|
/* Excluded from this release type: UsageError */
|
|
283
273
|
|
|
284
274
|
/* Excluded from this release type: validatePrecondition */
|
|
285
275
|
|
|
276
|
+
/* Excluded from this release type: wrapConfigProviderWithDefaults */
|
|
277
|
+
|
|
286
278
|
/* Excluded from this release type: wrapError */
|
|
287
279
|
|
|
288
280
|
/* Excluded from this release type: wrapErrorAndLog */
|
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { ConfigTypes } from '@fluidframework/core-interfaces';
|
|
2
|
+
import type { EventEmitter } from '@fluid-internal/client-utils';
|
|
4
3
|
import { EventEmitterEventType } from '@fluid-internal/client-utils';
|
|
5
4
|
import { IConfigProviderBase } from '@fluidframework/core-interfaces';
|
|
6
|
-
import { IDisposable } from '@fluidframework/core-interfaces';
|
|
5
|
+
import type { IDisposable } from '@fluidframework/core-interfaces';
|
|
7
6
|
import { IErrorBase } from '@fluidframework/core-interfaces';
|
|
8
7
|
import { IEvent } from '@fluidframework/core-interfaces';
|
|
9
8
|
import { IGenericError } from '@fluidframework/core-interfaces';
|
|
10
|
-
import { ILoggingError } from '@fluidframework/core-interfaces';
|
|
9
|
+
import type { ILoggingError } from '@fluidframework/core-interfaces';
|
|
11
10
|
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
12
11
|
import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
|
|
13
12
|
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
14
13
|
import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
|
|
15
|
-
import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
|
|
16
|
-
import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
|
|
17
|
-
import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
|
|
18
|
-
import { ITelemetryProperties } from '@fluidframework/core-interfaces';
|
|
19
14
|
import { IUsageError } from '@fluidframework/core-interfaces';
|
|
20
15
|
import { Lazy } from '@fluidframework/core-utils';
|
|
21
16
|
import { LogLevel } from '@fluidframework/core-interfaces';
|
|
22
17
|
import { Tagged } from '@fluidframework/core-interfaces';
|
|
23
18
|
import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
|
|
24
|
-
import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
|
|
25
19
|
import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
26
20
|
|
|
27
21
|
/* Excluded from this release type: connectedEventName */
|
|
@@ -40,22 +34,7 @@ import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
|
40
34
|
|
|
41
35
|
/* Excluded from this release type: disconnectedEventName */
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
* Event Emitter helper class
|
|
45
|
-
*
|
|
46
|
-
* @remarks
|
|
47
|
-
* Any exceptions thrown by listeners will be caught and raised through "error" event.
|
|
48
|
-
* Any exception thrown by "error" listeners will propagate to the caller.
|
|
49
|
-
* @privateRemarks
|
|
50
|
-
* This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
|
|
51
|
-
* We should consider moving it to the `core-utils` package.
|
|
52
|
-
* @public
|
|
53
|
-
*/
|
|
54
|
-
export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
|
|
55
|
-
private readonly errorHandler;
|
|
56
|
-
constructor(errorHandler: (eventName: EventEmitterEventType, error: any) => void);
|
|
57
|
-
emit(event: EventEmitterEventType, ...args: unknown[]): boolean;
|
|
58
|
-
}
|
|
37
|
+
/* Excluded from this release type: EventEmitterWithErrorHandling */
|
|
59
38
|
|
|
60
39
|
/* Excluded from this release type: eventNamespaceSeparator */
|
|
61
40
|
|
|
@@ -184,8 +163,6 @@ export declare interface ITelemetryPropertiesExt {
|
|
|
184
163
|
|
|
185
164
|
/* Excluded from this release type: LoggingError */
|
|
186
165
|
|
|
187
|
-
/* Excluded from this release type: logIfFalse */
|
|
188
|
-
|
|
189
166
|
/* Excluded from this release type: mixinMonitoringContext */
|
|
190
167
|
|
|
191
168
|
/* Excluded from this release type: MockLogger */
|
|
@@ -218,8 +195,6 @@ export declare interface ITelemetryPropertiesExt {
|
|
|
218
195
|
|
|
219
196
|
/* Excluded from this release type: TaggedLoggerAdapter */
|
|
220
197
|
|
|
221
|
-
/* Excluded from this release type: TelemetryBaseEventPropertyType */
|
|
222
|
-
|
|
223
198
|
/* Excluded from this release type: TelemetryDataTag */
|
|
224
199
|
|
|
225
200
|
/**
|
|
@@ -249,14 +224,14 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
|
|
|
249
224
|
|
|
250
225
|
/* Excluded from this release type: TelemetryEventPropertyTypes */
|
|
251
226
|
|
|
252
|
-
/* Excluded from this release type: TelemetryNullLogger */
|
|
253
|
-
|
|
254
227
|
/* Excluded from this release type: ThresholdCounter */
|
|
255
228
|
|
|
256
229
|
/* Excluded from this release type: UsageError */
|
|
257
230
|
|
|
258
231
|
/* Excluded from this release type: validatePrecondition */
|
|
259
232
|
|
|
233
|
+
/* Excluded from this release type: wrapConfigProviderWithDefaults */
|
|
234
|
+
|
|
260
235
|
/* Excluded from this release type: wrapError */
|
|
261
236
|
|
|
262
237
|
/* Excluded from this release type: wrapErrorAndLog */
|
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { ConfigTypes } from '@fluidframework/core-interfaces';
|
|
2
|
+
import type { EventEmitter } from '@fluid-internal/client-utils';
|
|
4
3
|
import { EventEmitterEventType } from '@fluid-internal/client-utils';
|
|
5
4
|
import { IConfigProviderBase } from '@fluidframework/core-interfaces';
|
|
6
|
-
import { IDisposable } from '@fluidframework/core-interfaces';
|
|
5
|
+
import type { IDisposable } from '@fluidframework/core-interfaces';
|
|
7
6
|
import { IErrorBase } from '@fluidframework/core-interfaces';
|
|
8
7
|
import { IEvent } from '@fluidframework/core-interfaces';
|
|
9
8
|
import { IGenericError } from '@fluidframework/core-interfaces';
|
|
10
|
-
import { ILoggingError } from '@fluidframework/core-interfaces';
|
|
9
|
+
import type { ILoggingError } from '@fluidframework/core-interfaces';
|
|
11
10
|
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
12
11
|
import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
|
|
13
12
|
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
14
13
|
import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
|
|
15
|
-
import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
|
|
16
|
-
import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
|
|
17
|
-
import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
|
|
18
|
-
import { ITelemetryProperties } from '@fluidframework/core-interfaces';
|
|
19
14
|
import { IUsageError } from '@fluidframework/core-interfaces';
|
|
20
15
|
import { Lazy } from '@fluidframework/core-utils';
|
|
21
16
|
import { LogLevel } from '@fluidframework/core-interfaces';
|
|
22
17
|
import { Tagged } from '@fluidframework/core-interfaces';
|
|
23
18
|
import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
|
|
24
|
-
import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
|
|
25
19
|
import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
26
20
|
|
|
27
21
|
/* Excluded from this release type: connectedEventName */
|
|
@@ -40,22 +34,7 @@ import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
|
40
34
|
|
|
41
35
|
/* Excluded from this release type: disconnectedEventName */
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
* Event Emitter helper class
|
|
45
|
-
*
|
|
46
|
-
* @remarks
|
|
47
|
-
* Any exceptions thrown by listeners will be caught and raised through "error" event.
|
|
48
|
-
* Any exception thrown by "error" listeners will propagate to the caller.
|
|
49
|
-
* @privateRemarks
|
|
50
|
-
* This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
|
|
51
|
-
* We should consider moving it to the `core-utils` package.
|
|
52
|
-
* @public
|
|
53
|
-
*/
|
|
54
|
-
export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
|
|
55
|
-
private readonly errorHandler;
|
|
56
|
-
constructor(errorHandler: (eventName: EventEmitterEventType, error: any) => void);
|
|
57
|
-
emit(event: EventEmitterEventType, ...args: unknown[]): boolean;
|
|
58
|
-
}
|
|
37
|
+
/* Excluded from this release type: EventEmitterWithErrorHandling */
|
|
59
38
|
|
|
60
39
|
/* Excluded from this release type: eventNamespaceSeparator */
|
|
61
40
|
|
|
@@ -184,8 +163,6 @@ export declare interface ITelemetryPropertiesExt {
|
|
|
184
163
|
|
|
185
164
|
/* Excluded from this release type: LoggingError */
|
|
186
165
|
|
|
187
|
-
/* Excluded from this release type: logIfFalse */
|
|
188
|
-
|
|
189
166
|
/* Excluded from this release type: mixinMonitoringContext */
|
|
190
167
|
|
|
191
168
|
/* Excluded from this release type: MockLogger */
|
|
@@ -218,8 +195,6 @@ export declare interface ITelemetryPropertiesExt {
|
|
|
218
195
|
|
|
219
196
|
/* Excluded from this release type: TaggedLoggerAdapter */
|
|
220
197
|
|
|
221
|
-
/* Excluded from this release type: TelemetryBaseEventPropertyType */
|
|
222
|
-
|
|
223
198
|
/* Excluded from this release type: TelemetryDataTag */
|
|
224
199
|
|
|
225
200
|
/**
|
|
@@ -249,14 +224,14 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
|
|
|
249
224
|
|
|
250
225
|
/* Excluded from this release type: TelemetryEventPropertyTypes */
|
|
251
226
|
|
|
252
|
-
/* Excluded from this release type: TelemetryNullLogger */
|
|
253
|
-
|
|
254
227
|
/* Excluded from this release type: ThresholdCounter */
|
|
255
228
|
|
|
256
229
|
/* Excluded from this release type: UsageError */
|
|
257
230
|
|
|
258
231
|
/* Excluded from this release type: validatePrecondition */
|
|
259
232
|
|
|
233
|
+
/* Excluded from this release type: wrapConfigProviderWithDefaults */
|
|
234
|
+
|
|
260
235
|
/* Excluded from this release type: wrapError */
|
|
261
236
|
|
|
262
237
|
/* Excluded from this release type: wrapErrorAndLog */
|
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { EventEmitter } from 'events';
|
|
1
|
+
import { ConfigTypes } from '@fluidframework/core-interfaces';
|
|
2
|
+
import type { EventEmitter } from '@fluid-internal/client-utils';
|
|
4
3
|
import { EventEmitterEventType } from '@fluid-internal/client-utils';
|
|
5
4
|
import { IConfigProviderBase } from '@fluidframework/core-interfaces';
|
|
6
|
-
import { IDisposable } from '@fluidframework/core-interfaces';
|
|
5
|
+
import type { IDisposable } from '@fluidframework/core-interfaces';
|
|
7
6
|
import { IErrorBase } from '@fluidframework/core-interfaces';
|
|
8
7
|
import { IEvent } from '@fluidframework/core-interfaces';
|
|
9
8
|
import { IGenericError } from '@fluidframework/core-interfaces';
|
|
10
|
-
import { ILoggingError } from '@fluidframework/core-interfaces';
|
|
9
|
+
import type { ILoggingError } from '@fluidframework/core-interfaces';
|
|
11
10
|
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
12
11
|
import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
|
|
13
12
|
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
14
13
|
import { ITelemetryBaseProperties } from '@fluidframework/core-interfaces';
|
|
15
|
-
import { ITelemetryErrorEvent } from '@fluidframework/core-interfaces';
|
|
16
|
-
import { ITelemetryGenericEvent } from '@fluidframework/core-interfaces';
|
|
17
|
-
import { ITelemetryPerformanceEvent } from '@fluidframework/core-interfaces';
|
|
18
|
-
import { ITelemetryProperties } from '@fluidframework/core-interfaces';
|
|
19
14
|
import { IUsageError } from '@fluidframework/core-interfaces';
|
|
20
15
|
import { Lazy } from '@fluidframework/core-utils';
|
|
21
16
|
import { LogLevel } from '@fluidframework/core-interfaces';
|
|
22
17
|
import { Tagged } from '@fluidframework/core-interfaces';
|
|
23
18
|
import { TelemetryBaseEventPropertyType } from '@fluidframework/core-interfaces';
|
|
24
|
-
import { TelemetryEventPropertyType } from '@fluidframework/core-interfaces';
|
|
25
19
|
import { TypedEventEmitter } from '@fluid-internal/client-utils';
|
|
26
20
|
|
|
27
21
|
/**
|
|
@@ -147,7 +141,7 @@ export declare const disconnectedEventName = "disconnected";
|
|
|
147
141
|
* @privateRemarks
|
|
148
142
|
* This probably doesn't belong in this package, as it is not telemetry-specific, and is really only intended for internal fluid-framework use.
|
|
149
143
|
* We should consider moving it to the `core-utils` package.
|
|
150
|
-
* @
|
|
144
|
+
* @alpha
|
|
151
145
|
*/
|
|
152
146
|
export declare class EventEmitterWithErrorHandling<TEvent extends IEvent = IEvent> extends TypedEventEmitter<TEvent> {
|
|
153
147
|
private readonly errorHandler;
|
|
@@ -340,11 +334,11 @@ export declare interface IFluidErrorBase extends Error {
|
|
|
340
334
|
/**
|
|
341
335
|
* Get the telemetry properties stashed on this error for logging.
|
|
342
336
|
*/
|
|
343
|
-
getTelemetryProperties():
|
|
337
|
+
getTelemetryProperties(): ITelemetryBaseProperties;
|
|
344
338
|
/**
|
|
345
339
|
* Add telemetry properties to this error which will be logged with the error
|
|
346
340
|
*/
|
|
347
|
-
addTelemetryProperties: (props:
|
|
341
|
+
addTelemetryProperties: (props: ITelemetryPropertiesExt) => void;
|
|
348
342
|
}
|
|
349
343
|
|
|
350
344
|
/**
|
|
@@ -568,28 +562,13 @@ export declare class LoggingError extends Error implements ILoggingError, Omit<I
|
|
|
568
562
|
/**
|
|
569
563
|
* Add additional properties to be logged
|
|
570
564
|
*/
|
|
571
|
-
addTelemetryProperties(props:
|
|
565
|
+
addTelemetryProperties(props: ITelemetryPropertiesExt): void;
|
|
572
566
|
/**
|
|
573
567
|
* Get all properties fit to be logged to telemetry for this error
|
|
574
568
|
*/
|
|
575
569
|
getTelemetryProperties(): ITelemetryBaseProperties;
|
|
576
570
|
}
|
|
577
571
|
|
|
578
|
-
/**
|
|
579
|
-
* Like assert, but logs only if the condition is false, rather than throwing
|
|
580
|
-
* @param condition - The condition to attest too
|
|
581
|
-
* @param logger - The logger to log with
|
|
582
|
-
* @param event - The string or event to log
|
|
583
|
-
* @returns The outcome of the condition
|
|
584
|
-
*
|
|
585
|
-
* @internal
|
|
586
|
-
*
|
|
587
|
-
* @deprecated
|
|
588
|
-
* This API will be removed in a future release.
|
|
589
|
-
* No replacement API is intended, but reproducing its behavior should be trivial for anyone who needs it.
|
|
590
|
-
*/
|
|
591
|
-
export declare function logIfFalse(condition: unknown, logger: ITelemetryBaseLogger, event: string | ITelemetryGenericEvent): condition is true;
|
|
592
|
-
|
|
593
572
|
/**
|
|
594
573
|
* Creates a {@link MonitoringContext} from the provided logger.
|
|
595
574
|
*
|
|
@@ -864,10 +843,10 @@ export declare class SampledTelemetryHelper implements IDisposable {
|
|
|
864
843
|
* properties which should be added to the telemetry event for that bucket. If a bucket being measured does not
|
|
865
844
|
* have an entry in this map, no additional properties will be added to its telemetry events. The following keys are
|
|
866
845
|
* reserved for use by this class: "duration", "count", "totalDuration", "minDuration", "maxDuration". If any of
|
|
867
|
-
* them is specified as a key in one of the
|
|
846
|
+
* them is specified as a key in one of the ITelemetryBaseProperties objects in this map, that key-value pair will be
|
|
868
847
|
* ignored.
|
|
869
848
|
*/
|
|
870
|
-
constructor(eventBase:
|
|
849
|
+
constructor(eventBase: ITelemetryGenericEventExt, logger: ITelemetryLoggerExt, sampleThreshold: number, includeAggregateMetrics?: boolean, perBucketProperties?: Map<string, ITelemetryBaseProperties>);
|
|
871
850
|
/**
|
|
872
851
|
* Executes the specified code and keeps track of execution time statistics.
|
|
873
852
|
* If it's been called enough times (the sampleThreshold for the class) then it generates a log message with the necessary information.
|
|
@@ -915,7 +894,7 @@ export declare const sessionStorageConfigProvider: Lazy<IConfigProviderBase>;
|
|
|
915
894
|
*
|
|
916
895
|
* @internal
|
|
917
896
|
*/
|
|
918
|
-
export declare const tagCodeArtifacts: <T extends Record<string,
|
|
897
|
+
export declare const tagCodeArtifacts: <T extends Record<string, TelemetryBaseEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(values: T) => { [P in keyof T]: (T[P] extends () => TelemetryBaseEventPropertyType ? () => {
|
|
919
898
|
value: ReturnType<T[P]>;
|
|
920
899
|
tag: TelemetryDataTag.CodeArtifact;
|
|
921
900
|
} : {
|
|
@@ -945,7 +924,7 @@ export declare const tagCodeArtifacts: <T extends Record<string, TelemetryEventP
|
|
|
945
924
|
*
|
|
946
925
|
* @internal
|
|
947
926
|
*/
|
|
948
|
-
export declare const tagData: <T extends TelemetryDataTag, V extends Record<string,
|
|
927
|
+
export declare const tagData: <T extends TelemetryDataTag, V extends Record<string, TelemetryBaseEventPropertyType | (() => TelemetryBaseEventPropertyType)>>(tag: T, values: V) => { [P in keyof V]: (V[P] extends () => TelemetryBaseEventPropertyType ? () => {
|
|
949
928
|
value: ReturnType<V[P]>;
|
|
950
929
|
tag: T;
|
|
951
930
|
} : {
|
|
@@ -1017,23 +996,6 @@ export declare type TelemetryEventPropertyTypeExt = string | number | boolean |
|
|
|
1017
996
|
*/
|
|
1018
997
|
export declare type TelemetryEventPropertyTypes = ITelemetryBaseProperties[string];
|
|
1019
998
|
|
|
1020
|
-
/**
|
|
1021
|
-
* Null logger that no-ops for all telemetry events passed to it.
|
|
1022
|
-
*
|
|
1023
|
-
* @deprecated This will be removed in a future release.
|
|
1024
|
-
* For internal use within the FluidFramework codebase, use {@link createChildLogger} with no arguments instead.
|
|
1025
|
-
* For external consumers we recommend writing a trivial implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger}
|
|
1026
|
-
* where the send() method does nothing and using that.
|
|
1027
|
-
*
|
|
1028
|
-
* @internal
|
|
1029
|
-
*/
|
|
1030
|
-
export declare class TelemetryNullLogger implements ITelemetryLoggerExt {
|
|
1031
|
-
send(event: ITelemetryBaseEvent): void;
|
|
1032
|
-
sendTelemetryEvent(event: ITelemetryGenericEvent, error?: unknown): void;
|
|
1033
|
-
sendErrorEvent(event: ITelemetryErrorEvent, error?: unknown): void;
|
|
1034
|
-
sendPerformanceEvent(event: ITelemetryPerformanceEvent, error?: unknown): void;
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
999
|
/**
|
|
1038
1000
|
* Utility counter which will send event only if the provided value is above a configured threshold.
|
|
1039
1001
|
*
|
|
@@ -1079,6 +1041,19 @@ export declare class UsageError extends LoggingError implements IUsageError, IFl
|
|
|
1079
1041
|
*/
|
|
1080
1042
|
export declare function validatePrecondition(condition: boolean, message: string, props?: ITelemetryBaseProperties): asserts condition;
|
|
1081
1043
|
|
|
1044
|
+
/**
|
|
1045
|
+
* Creates a wrapper on top of an existing config provider which allows for
|
|
1046
|
+
* specifying feature gates if not present in the original provider.
|
|
1047
|
+
*
|
|
1048
|
+
* @param original - the original config provider
|
|
1049
|
+
* @param defaults - default feature gate configs to be used if not specified by the original provider
|
|
1050
|
+
* @returns A config provider that looks for any requested feature gates in the original provider and falls
|
|
1051
|
+
* back to the values specified in the `defaults` feature gates if they're not present in the original.
|
|
1052
|
+
*
|
|
1053
|
+
* @internal
|
|
1054
|
+
*/
|
|
1055
|
+
export declare const wrapConfigProviderWithDefaults: (original: IConfigProviderBase | undefined, defaults: Record<string, ConfigTypes>) => IConfigProviderBase;
|
|
1056
|
+
|
|
1082
1057
|
/**
|
|
1083
1058
|
* Create a new error using newErrorFn, wrapping and caused by the given unknown error.
|
|
1084
1059
|
* Copies the inner error's stack, errorInstanceId and telemetry props over to the new error if present
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { strict as assert } from "node:assert";
|
|
6
|
+
import { EventEmitterWithErrorHandling } from "../eventEmitterWithErrorHandling.js";
|
|
7
|
+
describe("EventEmitterWithErrorHandling", () => {
|
|
8
|
+
let errorHandlerCalled = false;
|
|
9
|
+
function defaultErrorHandler(event, error) {
|
|
10
|
+
errorHandlerCalled = true;
|
|
11
|
+
throw error;
|
|
12
|
+
}
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
errorHandlerCalled = false;
|
|
15
|
+
});
|
|
16
|
+
it("forwards events", () => {
|
|
17
|
+
const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
|
|
18
|
+
let passedArg;
|
|
19
|
+
emitter.on("foo", (arg) => {
|
|
20
|
+
passedArg = arg;
|
|
21
|
+
});
|
|
22
|
+
emitter.emit("foo", 3);
|
|
23
|
+
assert.strictEqual(passedArg, 3);
|
|
24
|
+
assert.strictEqual(errorHandlerCalled, false);
|
|
25
|
+
});
|
|
26
|
+
it("forwards error event", () => {
|
|
27
|
+
const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
|
|
28
|
+
let passedArg;
|
|
29
|
+
emitter.on("error", (arg) => {
|
|
30
|
+
passedArg = arg;
|
|
31
|
+
});
|
|
32
|
+
emitter.emit("error", 3);
|
|
33
|
+
assert.strictEqual(passedArg, 3);
|
|
34
|
+
assert.strictEqual(errorHandlerCalled, false);
|
|
35
|
+
});
|
|
36
|
+
it("error thrown from listener is handled, some other listeners succeed", () => {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
const emitter = new EventEmitterWithErrorHandling((event, error) => {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
40
|
+
passedErrorMsg = error.message;
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
42
|
+
passedEventArg = error.eventArg;
|
|
43
|
+
});
|
|
44
|
+
let passedErrorMsg;
|
|
45
|
+
let passedEventArg;
|
|
46
|
+
let earlyListenerCallCount = 0;
|
|
47
|
+
let lateListenerCallCount = 0;
|
|
48
|
+
// Innocent bystander - early (registered before throwing one)
|
|
49
|
+
emitter.on("foo", (_arg) => {
|
|
50
|
+
++earlyListenerCallCount;
|
|
51
|
+
});
|
|
52
|
+
// The delinquent
|
|
53
|
+
emitter.on("foo", (arg) => {
|
|
54
|
+
const error = new Error("foo listener throws");
|
|
55
|
+
Object.assign(error, { eventArg: arg });
|
|
56
|
+
throw error;
|
|
57
|
+
});
|
|
58
|
+
// Innocent bystander - late (registered after throwing one)
|
|
59
|
+
emitter.on("foo", (_arg) => {
|
|
60
|
+
++lateListenerCallCount;
|
|
61
|
+
});
|
|
62
|
+
emitter.emit("foo", 3); // listener above will throw. Expect error listener to be invoked
|
|
63
|
+
assert.strictEqual(passedErrorMsg, "foo listener throws");
|
|
64
|
+
assert.strictEqual(passedEventArg, 3);
|
|
65
|
+
assert.strictEqual(earlyListenerCallCount, 1);
|
|
66
|
+
assert.strictEqual(lateListenerCallCount, 0);
|
|
67
|
+
});
|
|
68
|
+
it("emitting error event when unhandled will invoke handler", () => {
|
|
69
|
+
const emitter = new EventEmitterWithErrorHandling(defaultErrorHandler);
|
|
70
|
+
try {
|
|
71
|
+
const error = new Error("No one is listening");
|
|
72
|
+
Object.assign(error, { prop: 4 });
|
|
73
|
+
emitter.emit("error", error, 3); // the extra args (e.g. 3 here) are dropped
|
|
74
|
+
assert.fail("previous line should throw");
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
79
|
+
assert.strictEqual(error.message, "No one is listening");
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
81
|
+
assert.strictEqual(error.prop, 4);
|
|
82
|
+
assert.strictEqual(errorHandlerCalled, true);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=EventEmitterWithErrorHandling.spec.js.map
|