@fluidframework/telemetry-utils 2.0.0-rc.1.0.3 → 2.0.0-rc.2.0.0
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/{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 +10 -33
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- 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 -60
- 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 +4 -15
- package/dist/telemetry-utils-beta.d.ts +4 -32
- package/dist/telemetry-utils-public.d.ts +4 -32
- package/dist/telemetry-utils-untrimmed.d.ts +11 -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 +2 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +1 -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} +4 -15
- package/lib/{telemetry-utils-beta.d.mts → telemetry-utils-beta.d.ts} +4 -32
- package/lib/{telemetry-utils-public.d.mts → telemetry-utils-public.d.ts} +4 -32
- package/lib/{telemetry-utils-untrimmed.d.mts → telemetry-utils-untrimmed.d.ts} +11 -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 +2 -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 +12 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiSinkLogger.spec.js","sourceRoot":"","sources":["../../src/test/multiSinkLogger.spec.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 { strict as assert } from \"node:assert\";\nimport { LogLevel } from \"@fluidframework/core-interfaces\";\nimport { MultiSinkLogger, createChildLogger, createMultiSinkLogger } from \"../logger.js\";\nimport { MockLogger } from \"../mockLogger.js\";\n\ndescribe(\"MultiSinkLogger\", () => {\n\tit(\"Pushes logs to all sinks\", () => {\n\t\tconst logger1 = new MockLogger();\n\t\tconst logger2 = new MockLogger();\n\t\tconst multiSink = createMultiSinkLogger({ loggers: [logger1, logger2] });\n\t\tmultiSink.sendTelemetryEvent({ eventName: \"test\" });\n\n\t\tlogger1.assertMatch([{ category: \"generic\", eventName: \"test\" }]);\n\t\tlogger2.assertMatch([{ category: \"generic\", eventName: \"test\" }]);\n\t});\n\n\tit(\"Appends namespace to all logged events\", () => {\n\t\tconst logger1 = new MockLogger();\n\t\tconst logger2 = new MockLogger();\n\t\tconst multiSink = createMultiSinkLogger({ loggers: [logger1, logger2], namespace: \"test\" });\n\t\tmultiSink.sendTelemetryEvent({ eventName: \"test\" });\n\n\t\tlogger1.assertMatch([{ category: \"generic\", eventName: \"test:test\" }]);\n\t\tlogger2.assertMatch([{ category: \"generic\", eventName: \"test:test\" }]);\n\t});\n\n\tit(\"Propagates Properties to sinks when tryInheritProperties true\", () => {\n\t\tconst logger1 = new MockLogger();\n\t\tconst logger2 = new MockLogger();\n\t\tconst multiSink = createMultiSinkLogger({\n\t\t\tloggers: [\n\t\t\t\tcreateChildLogger({ logger: logger1, properties: { all: { test: true } } }),\n\t\t\t\tlogger2,\n\t\t\t],\n\t\t\ttryInheritProperties: true,\n\t\t});\n\t\tmultiSink.sendTelemetryEvent({ eventName: \"test\" });\n\n\t\tlogger1.assertMatch([{ category: \"generic\", eventName: \"test\", test: true }]);\n\t\tlogger2.assertMatch([{ category: \"generic\", eventName: \"test\", test: true }]);\n\t});\n\n\tit(\"Does not Propagates Properties to sinks when tryInheritProperties not set\", () => {\n\t\tconst logger1 = new MockLogger();\n\t\tconst logger2 = new MockLogger();\n\t\tconst multiSink = createMultiSinkLogger({\n\t\t\tloggers: [\n\t\t\t\tcreateChildLogger({ logger: logger1, properties: { all: { test: true } } }),\n\t\t\t\tlogger2,\n\t\t\t],\n\t\t});\n\t\tmultiSink.sendTelemetryEvent({ eventName: \"test\" });\n\n\t\tlogger1.assertMatch([{ category: \"generic\", eventName: \"test\", test: true }]);\n\t\tlogger2.assertMatch([{ category: \"generic\", eventName: \"test\" }]);\n\t});\n\n\tit(\"MultiSink logger set the logLevel to min logLevel of all loggers\", () => {\n\t\tconst logger1 = new MockLogger(LogLevel.error);\n\t\tconst logger2 = new MockLogger(LogLevel.default);\n\t\tconst multiSink = createMultiSinkLogger({\n\t\t\tloggers: [createChildLogger({ logger: logger1 }), logger2],\n\t\t});\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.default,\n\t\t\t\"Min loglevel should be set correctly\",\n\t\t);\n\n\t\t// Add logger with a log level as verbose\n\t\t(multiSink as MultiSinkLogger).addLogger(new MockLogger(LogLevel.verbose));\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.verbose,\n\t\t\t\"Min loglevel should be set correctly to verbose\",\n\t\t);\n\t});\n\n\tit(\"MultiSink logger set the logLevel to default if not supplied with a log level\", () => {\n\t\tconst logger1 = new MockLogger();\n\t\tconst logger2 = new MockLogger();\n\t\tconst multiSink = createMultiSinkLogger({\n\t\t\tloggers: [createChildLogger({ logger: logger1 }), logger2],\n\t\t});\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.default,\n\t\t\t\"Min loglevel should be set correctly to default\",\n\t\t);\n\t});\n\n\tit(\"MultiSink logger set the logLevel correctly when no initial loggers are supplied\", () => {\n\t\tconst multiSink = createMultiSinkLogger({\n\t\t\tloggers: [],\n\t\t});\n\n\t\t(multiSink as MultiSinkLogger).addLogger(new MockLogger());\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.default,\n\t\t\t\"Min loglevel should be set correctly to default\",\n\t\t);\n\n\t\t(multiSink as MultiSinkLogger).addLogger(new MockLogger(LogLevel.default));\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.default,\n\t\t\t\"Min loglevel should be set correctly to default\",\n\t\t);\n\n\t\t(multiSink as MultiSinkLogger).addLogger(new MockLogger(LogLevel.verbose));\n\t\tassert.strictEqual(\n\t\t\tmultiSink.minLogLevel,\n\t\t\tLogLevel.verbose,\n\t\t\t\"Min loglevel should be set correctly to verbose\",\n\t\t);\n\t});\n});\n"]}
|
|
@@ -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 { TelemetryLogger, PerformanceEvent } from "../logger.js";
|
|
7
|
+
class MockLogger extends TelemetryLogger {
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this.errorsLogged = 0;
|
|
11
|
+
this.eventsLogged = 0;
|
|
12
|
+
}
|
|
13
|
+
send(event) {
|
|
14
|
+
if (event.category === "error") {
|
|
15
|
+
++this.errorsLogged;
|
|
16
|
+
}
|
|
17
|
+
++this.eventsLogged;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
describe("PerformanceEvent", () => {
|
|
21
|
+
let logger;
|
|
22
|
+
let callbackCalls = 0;
|
|
23
|
+
const callback = () => {
|
|
24
|
+
callbackCalls++;
|
|
25
|
+
};
|
|
26
|
+
const asyncCallback = async (event) => {
|
|
27
|
+
const outerPromise = new Promise((resolve, reject) => {
|
|
28
|
+
Promise.resolve("A")
|
|
29
|
+
.finally(() => {
|
|
30
|
+
reject(new Error("B"));
|
|
31
|
+
})
|
|
32
|
+
.then((val) => {
|
|
33
|
+
event.end({ val });
|
|
34
|
+
resolve("C");
|
|
35
|
+
})
|
|
36
|
+
.catch(() => { });
|
|
37
|
+
});
|
|
38
|
+
callbackCalls++;
|
|
39
|
+
return outerPromise.catch(() => { });
|
|
40
|
+
};
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
callbackCalls = 0;
|
|
43
|
+
logger = new MockLogger();
|
|
44
|
+
});
|
|
45
|
+
it("Cancel then End", async () => {
|
|
46
|
+
await PerformanceEvent.timedExecAsync(logger, { eventName: "Testing" }, asyncCallback, { start: true, end: true, cancel: "generic" }, true);
|
|
47
|
+
assert.equal(logger.errorsLogged, 0, "Shouldn't have logged any errors");
|
|
48
|
+
});
|
|
49
|
+
describe("Event sampling", () => {
|
|
50
|
+
it("Events are logged at least once", async () => {
|
|
51
|
+
await PerformanceEvent.timedExecAsync(logger, { eventName: "TestingAsyncOnce" }, asyncCallback, { start: true, end: true, cancel: "generic" }, true, 100);
|
|
52
|
+
PerformanceEvent.timedExec(logger, { eventName: "TestingSyncOnce" }, callback, { start: true, end: true, cancel: "generic" }, 100);
|
|
53
|
+
assert.equal(callbackCalls, 2);
|
|
54
|
+
assert.equal(logger.eventsLogged, 4);
|
|
55
|
+
});
|
|
56
|
+
it("No sampling by default", async () => {
|
|
57
|
+
await Promise.all(Array.from({ length: 100 }).map(async (_) => PerformanceEvent.timedExecAsync(logger, { eventName: "TestingAsync" }, asyncCallback, { start: true, end: true, cancel: "generic" }, true)));
|
|
58
|
+
Array.from({ length: 100 }).map((_) => PerformanceEvent.timedExec(logger, { eventName: "TestingSync" }, callback, {
|
|
59
|
+
start: true,
|
|
60
|
+
end: true,
|
|
61
|
+
cancel: "generic",
|
|
62
|
+
}));
|
|
63
|
+
assert.equal(callbackCalls, 200);
|
|
64
|
+
assert.equal(logger.eventsLogged, 200 * 2);
|
|
65
|
+
});
|
|
66
|
+
it("Sampling for async", async () => {
|
|
67
|
+
await Promise.all(Array.from({ length: 100 }).map(async (_) => PerformanceEvent.timedExecAsync(logger, { eventName: "TestingAsync" }, asyncCallback, { start: true, end: true, cancel: "generic" }, true, 20)));
|
|
68
|
+
assert.equal(callbackCalls, 100);
|
|
69
|
+
assert.equal(logger.eventsLogged, 10, "With sampling threshold of 20, expecting 100 calls to produce 10 events (5 start, 5 cancel)");
|
|
70
|
+
// Event with a different category gets logged
|
|
71
|
+
await PerformanceEvent.timedExecAsync(logger, { eventName: "TestingAsync", category: "error" }, asyncCallback, { start: true, end: true, cancel: "generic" }, true, 20);
|
|
72
|
+
assert.equal(callbackCalls, 101);
|
|
73
|
+
assert.equal(logger.eventsLogged, 12, "Expecting two extra events");
|
|
74
|
+
});
|
|
75
|
+
it("Sampling for sync", async () => {
|
|
76
|
+
Array.from({ length: 100 }).map((_) => PerformanceEvent.timedExec(logger, { eventName: "TestingSync" }, callback, { start: true, end: true, cancel: "generic" }, 20));
|
|
77
|
+
assert.equal(callbackCalls, 100);
|
|
78
|
+
assert.equal(logger.eventsLogged, 10, "With sampling threshold of 20, expecting 100 calls to produce 10 events (5 start, 5 cancel)");
|
|
79
|
+
// Event with a different category gets logged
|
|
80
|
+
PerformanceEvent.timedExec(logger, { eventName: "TestingSync", category: "error" }, callback, { start: true, end: true, cancel: "generic" }, 20);
|
|
81
|
+
assert.equal(callbackCalls, 101);
|
|
82
|
+
assert.equal(logger.eventsLogged, 12, "Expecting two extra events");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=performanceEvent.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performanceEvent.spec.js","sourceRoot":"","sources":["../../src/test/performanceEvent.spec.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 { strict as assert } from \"node:assert\";\nimport { ITelemetryBaseEvent } from \"@fluidframework/core-interfaces\";\nimport { TelemetryLogger, PerformanceEvent } from \"../logger.js\";\nimport { ITelemetryLoggerExt } from \"../telemetryTypes.js\";\n\nclass MockLogger extends TelemetryLogger implements ITelemetryLoggerExt {\n\tpublic errorsLogged: number = 0;\n\tpublic eventsLogged: number = 0;\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tif (event.category === \"error\") {\n\t\t\t++this.errorsLogged;\n\t\t}\n\n\t\t++this.eventsLogged;\n\t}\n}\n\ndescribe(\"PerformanceEvent\", () => {\n\tlet logger: MockLogger;\n\tlet callbackCalls = 0;\n\n\tconst callback = (): void => {\n\t\tcallbackCalls++;\n\t};\n\tconst asyncCallback = async (event: PerformanceEvent): Promise<string | void> => {\n\t\tconst outerPromise: Promise<string> = new Promise((resolve, reject) => {\n\t\t\tPromise.resolve(\"A\")\n\t\t\t\t.finally(() => {\n\t\t\t\t\treject(new Error(\"B\"));\n\t\t\t\t})\n\t\t\t\t.then((val) => {\n\t\t\t\t\tevent.end({ val });\n\t\t\t\t\tresolve(\"C\");\n\t\t\t\t})\n\t\t\t\t.catch(() => {});\n\t\t});\n\n\t\tcallbackCalls++;\n\t\treturn outerPromise.catch(() => {});\n\t};\n\n\tbeforeEach(() => {\n\t\tcallbackCalls = 0;\n\t\tlogger = new MockLogger();\n\t});\n\n\tit(\"Cancel then End\", async () => {\n\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{ eventName: \"Testing\" },\n\t\t\tasyncCallback,\n\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\ttrue,\n\t\t);\n\t\tassert.equal(logger.errorsLogged, 0, \"Shouldn't have logged any errors\");\n\t});\n\n\tdescribe(\"Event sampling\", () => {\n\t\tit(\"Events are logged at least once\", async () => {\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{ eventName: \"TestingAsyncOnce\" },\n\t\t\t\tasyncCallback,\n\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\ttrue,\n\t\t\t\t100, // sampleThreshold\n\t\t\t);\n\n\t\t\tPerformanceEvent.timedExec(\n\t\t\t\tlogger,\n\t\t\t\t{ eventName: \"TestingSyncOnce\" },\n\t\t\t\tcallback,\n\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\t100, // sampleThreshold\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 2);\n\t\t\tassert.equal(logger.eventsLogged, 4);\n\t\t});\n\n\t\tit(\"No sampling by default\", async () => {\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from({ length: 100 }).map(async (_) =>\n\t\t\t\t\tPerformanceEvent.timedExecAsync(\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t{ eventName: \"TestingAsync\" },\n\t\t\t\t\t\tasyncCallback,\n\t\t\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tArray.from({ length: 100 }).map((_) =>\n\t\t\t\tPerformanceEvent.timedExec(logger, { eventName: \"TestingSync\" }, callback, {\n\t\t\t\t\tstart: true,\n\t\t\t\t\tend: true,\n\t\t\t\t\tcancel: \"generic\",\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 200);\n\t\t\tassert.equal(logger.eventsLogged, 200 * 2);\n\t\t});\n\n\t\tit(\"Sampling for async\", async () => {\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from({ length: 100 }).map(async (_) =>\n\t\t\t\t\tPerformanceEvent.timedExecAsync(\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t{ eventName: \"TestingAsync\" },\n\t\t\t\t\t\tasyncCallback,\n\t\t\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t20, // sampleThreshold\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 100);\n\t\t\tassert.equal(\n\t\t\t\tlogger.eventsLogged,\n\t\t\t\t10,\n\t\t\t\t\"With sampling threshold of 20, expecting 100 calls to produce 10 events (5 start, 5 cancel)\",\n\t\t\t);\n\n\t\t\t// Event with a different category gets logged\n\t\t\tawait PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{ eventName: \"TestingAsync\", category: \"error\" },\n\t\t\t\tasyncCallback,\n\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\ttrue,\n\t\t\t\t20, // sampleThreshold\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 101);\n\t\t\tassert.equal(logger.eventsLogged, 12, \"Expecting two extra events\");\n\t\t});\n\n\t\tit(\"Sampling for sync\", async () => {\n\t\t\tArray.from({ length: 100 }).map((_) =>\n\t\t\t\tPerformanceEvent.timedExec(\n\t\t\t\t\tlogger,\n\t\t\t\t\t{ eventName: \"TestingSync\" },\n\t\t\t\t\tcallback,\n\t\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\t\t20, // sampleThreshold\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 100);\n\t\t\tassert.equal(\n\t\t\t\tlogger.eventsLogged,\n\t\t\t\t10,\n\t\t\t\t\"With sampling threshold of 20, expecting 100 calls to produce 10 events (5 start, 5 cancel)\",\n\t\t\t);\n\n\t\t\t// Event with a different category gets logged\n\t\t\tPerformanceEvent.timedExec(\n\t\t\t\tlogger,\n\t\t\t\t{ eventName: \"TestingSync\", category: \"error\" },\n\t\t\t\tcallback,\n\t\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t\t\t20, // sampleThreshold\n\t\t\t);\n\n\t\t\tassert.equal(callbackCalls, 101);\n\t\t\tassert.equal(logger.eventsLogged, 12, \"Expecting two extra events\");\n\t\t});\n\t});\n});\n"]}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import assert from "node:assert";
|
|
6
|
+
import { SampledTelemetryHelper } from "../sampledTelemetryHelper.js";
|
|
7
|
+
/**
|
|
8
|
+
* Test logger with only the necessary functionality used by the SampledTelemetryHelper
|
|
9
|
+
* so we can test it.
|
|
10
|
+
*/
|
|
11
|
+
class TestLogger {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.events = [];
|
|
14
|
+
}
|
|
15
|
+
sendPerformanceEvent(event, error) {
|
|
16
|
+
this.events.push(event);
|
|
17
|
+
}
|
|
18
|
+
send(event) {
|
|
19
|
+
throw new Error("Method not implemented.");
|
|
20
|
+
}
|
|
21
|
+
sendTelemetryEvent(event, error) {
|
|
22
|
+
throw new Error("Method not implemented.");
|
|
23
|
+
}
|
|
24
|
+
sendErrorEvent(event, error) {
|
|
25
|
+
throw new Error("Method not implemented.");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const standardEventProperties = ["eventName", "duration", "count"];
|
|
29
|
+
const aggregateProperties = ["totalDuration", "minDuration", "maxDuration"];
|
|
30
|
+
describe("SampledTelemetryHelper", () => {
|
|
31
|
+
let logger;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
logger = new TestLogger();
|
|
34
|
+
});
|
|
35
|
+
it("only writes event after correct number of samples", () => {
|
|
36
|
+
const sampling = 10;
|
|
37
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, sampling);
|
|
38
|
+
for (let i = 0; i < sampling - 1; i++) {
|
|
39
|
+
helper.measure(() => { });
|
|
40
|
+
}
|
|
41
|
+
assert.strictEqual(logger.events.length, 0);
|
|
42
|
+
helper.measure(() => { });
|
|
43
|
+
assert.strictEqual(logger.events.length, 1);
|
|
44
|
+
// Again to make sure the internal counter is reset correctly
|
|
45
|
+
for (let i = 0; i < sampling - 1; i++) {
|
|
46
|
+
helper.measure(() => { });
|
|
47
|
+
}
|
|
48
|
+
assert.strictEqual(logger.events.length, 1);
|
|
49
|
+
helper.measure(() => { });
|
|
50
|
+
assert.strictEqual(logger.events.length, 2);
|
|
51
|
+
});
|
|
52
|
+
it("does not include aggregate properties when it shouldn't", () => {
|
|
53
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 1, false);
|
|
54
|
+
helper.measure(() => { });
|
|
55
|
+
assert.strictEqual(logger.events.length, 1);
|
|
56
|
+
const event = logger.events[0];
|
|
57
|
+
ensurePropertiesExist(event, standardEventProperties, true);
|
|
58
|
+
assert.strictEqual(event.count, 1);
|
|
59
|
+
});
|
|
60
|
+
it("includes aggregate properties when it should", () => {
|
|
61
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 1, true);
|
|
62
|
+
helper.measure(() => { });
|
|
63
|
+
assert.strictEqual(logger.events.length, 1);
|
|
64
|
+
const event = logger.events[0];
|
|
65
|
+
ensurePropertiesExist(event, [...standardEventProperties, ...aggregateProperties], true);
|
|
66
|
+
assert.strictEqual(event.count, 1);
|
|
67
|
+
});
|
|
68
|
+
it("includes properties from base event when no aggregate properties are included", () => {
|
|
69
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent", myProp: "myValue" }, logger, 1, false);
|
|
70
|
+
helper.measure(() => { });
|
|
71
|
+
assert.strictEqual(logger.events.length, 1);
|
|
72
|
+
const event = logger.events[0];
|
|
73
|
+
ensurePropertiesExist(event, [...standardEventProperties, "myProp"], true);
|
|
74
|
+
assert.strictEqual(event.count, 1);
|
|
75
|
+
assert.strictEqual(event.myProp, "myValue");
|
|
76
|
+
});
|
|
77
|
+
it("includes properties from base event when aggregate properties are included", () => {
|
|
78
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent", myProp: "myValue" }, logger, 1, true);
|
|
79
|
+
helper.measure(() => { });
|
|
80
|
+
assert.strictEqual(logger.events.length, 1);
|
|
81
|
+
const event = logger.events[0];
|
|
82
|
+
ensurePropertiesExist(event, [...standardEventProperties, ...aggregateProperties, "myProp"], true);
|
|
83
|
+
assert.strictEqual(event.count, 1);
|
|
84
|
+
assert.strictEqual(event.myProp, "myValue");
|
|
85
|
+
});
|
|
86
|
+
it("tracks buckets separately and includes per-bucket properties", () => {
|
|
87
|
+
const bucket1 = "bucket1";
|
|
88
|
+
const bucket2 = "bucket2";
|
|
89
|
+
const bucketProperties = new Map([
|
|
90
|
+
[bucket1, { prop1: "value1" }],
|
|
91
|
+
[bucket2, { prop2: "value2" }],
|
|
92
|
+
]);
|
|
93
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 3, false, bucketProperties);
|
|
94
|
+
for (let i = 0; i < 9; i++) {
|
|
95
|
+
helper.measure(() => { }, bucket1);
|
|
96
|
+
}
|
|
97
|
+
for (let i = 0; i < 7; i++) {
|
|
98
|
+
helper.measure(() => { }, bucket2);
|
|
99
|
+
}
|
|
100
|
+
assert.strictEqual(logger.events.filter((x) => x.prop1 === "value1").length, 3);
|
|
101
|
+
assert.strictEqual(logger.events.filter((x) => x.prop2 === "value2").length, 2);
|
|
102
|
+
});
|
|
103
|
+
it("bucket properties do not override measurement properties", () => {
|
|
104
|
+
// If the names of the properties specified by the consumers for a bucket overlap with the names
|
|
105
|
+
// of the standard properties we put in the telemetry events, our values should not be overwritten
|
|
106
|
+
// by the custom properties.
|
|
107
|
+
const bucket1 = "bucket1";
|
|
108
|
+
const bucketProperties = new Map([
|
|
109
|
+
// Here just using a duration value that we can be sure will not be the actual value, to make sure the
|
|
110
|
+
// actuals is different from this one (since it's much harder to guarantee an exact duration
|
|
111
|
+
// value to test for equality).
|
|
112
|
+
[bucket1, { duration: 1000, count: 1000 }],
|
|
113
|
+
]);
|
|
114
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 1, false, bucketProperties);
|
|
115
|
+
helper.measure(() => { }, bucket1);
|
|
116
|
+
assert.strictEqual(logger.events.length, 1);
|
|
117
|
+
const event = logger.events[0];
|
|
118
|
+
assert.strictEqual(event.count, 1);
|
|
119
|
+
assert(event.duration !== bucketProperties.get("bucket1").duration);
|
|
120
|
+
});
|
|
121
|
+
it("generates telemetry event from buffered data when disposed", () => {
|
|
122
|
+
// Logging several buckets to make sure they are all flushed. We can only distingush the events based on the
|
|
123
|
+
// custom properties added to the event for each bucket
|
|
124
|
+
const bucket1 = "bucket1";
|
|
125
|
+
const bucket2 = "bucket2";
|
|
126
|
+
const bucketProperties = new Map([
|
|
127
|
+
[bucket1, { prop1: "value1" }],
|
|
128
|
+
[bucket2, { prop2: "value2" }],
|
|
129
|
+
]);
|
|
130
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 5, false, bucketProperties);
|
|
131
|
+
// Only measure 4 times when we need 5 samples before writing the telemetry event
|
|
132
|
+
for (let i = 0; i < 4; i++) {
|
|
133
|
+
helper.measure(() => { }, bucket1);
|
|
134
|
+
helper.measure(() => { }, bucket2);
|
|
135
|
+
}
|
|
136
|
+
// Nothing should have been logged yet
|
|
137
|
+
assert.strictEqual(logger.events.length, 0);
|
|
138
|
+
// After disposing, there should be one event for each bucket
|
|
139
|
+
helper.dispose();
|
|
140
|
+
assert.strictEqual(logger.events.filter((x) => x.prop1 === "value1").length, 1);
|
|
141
|
+
assert.strictEqual(logger.events.filter((x) => x.prop2 === "value2").length, 1);
|
|
142
|
+
});
|
|
143
|
+
it("no event is generated on dispose if there's no pending 'buffered' data", () => {
|
|
144
|
+
const helper = new SampledTelemetryHelper({ eventName: "testEvent" }, logger, 2);
|
|
145
|
+
// Nothing should have been logged after the first call
|
|
146
|
+
helper.measure(() => { });
|
|
147
|
+
assert.strictEqual(logger.events.length, 0);
|
|
148
|
+
// On the second call, we should have 1 event
|
|
149
|
+
helper.measure(() => { });
|
|
150
|
+
assert.strictEqual(logger.events.length, 1);
|
|
151
|
+
// After disposing, there should still be just one event
|
|
152
|
+
helper.dispose();
|
|
153
|
+
assert.strictEqual(logger.events.length, 1);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
function ensurePropertiesExist(object, propNames, noExtraProperties = false) {
|
|
157
|
+
for (const name of propNames) {
|
|
158
|
+
assert.strictEqual(object[name] !== undefined, true);
|
|
159
|
+
}
|
|
160
|
+
if (noExtraProperties) {
|
|
161
|
+
const actualNumberOfProps = Object.keys(object).length;
|
|
162
|
+
const expectedNumberOfProps = propNames.length;
|
|
163
|
+
if (actualNumberOfProps !== expectedNumberOfProps) {
|
|
164
|
+
assert.fail(`Object contains unexpected properties ` +
|
|
165
|
+
`(${actualNumberOfProps} found, ${expectedNumberOfProps}) expected)`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=sampledTelemetryHelper.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampledTelemetryHelper.spec.js","sourceRoot":"","sources":["../../src/test/sampledTelemetryHelper.spec.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 assert from \"node:assert\";\nimport type {\n\tITelemetryBaseEvent,\n\tITelemetryBaseProperties,\n} from \"@fluidframework/core-interfaces\";\n\nimport { SampledTelemetryHelper } from \"../sampledTelemetryHelper.js\";\nimport {\n\tITelemetryLoggerExt,\n\ttype ITelemetryErrorEventExt,\n\ttype ITelemetryPerformanceEventExt,\n\ttype ITelemetryGenericEventExt,\n} from \"../telemetryTypes.js\";\n\n/**\n * Test logger with only the necessary functionality used by the SampledTelemetryHelper\n * so we can test it.\n */\nclass TestLogger implements ITelemetryLoggerExt {\n\tpublic events: ITelemetryPerformanceEventExt[] = [];\n\n\tsendPerformanceEvent(event: ITelemetryPerformanceEventExt, error?: unknown): void {\n\t\tthis.events.push(event);\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tsendTelemetryEvent(event: ITelemetryGenericEventExt, error?: unknown): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tsendErrorEvent(event: ITelemetryErrorEventExt, error?: unknown): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tsupportsTags?: true | undefined;\n}\n\nconst standardEventProperties = [\"eventName\", \"duration\", \"count\"];\nconst aggregateProperties = [\"totalDuration\", \"minDuration\", \"maxDuration\"];\n\ndescribe(\"SampledTelemetryHelper\", () => {\n\tlet logger: TestLogger;\n\n\tbeforeEach(() => {\n\t\tlogger = new TestLogger();\n\t});\n\n\tit(\"only writes event after correct number of samples\", () => {\n\t\tconst sampling = 10;\n\t\tconst helper = new SampledTelemetryHelper({ eventName: \"testEvent\" }, logger, sampling);\n\t\tfor (let i = 0; i < sampling - 1; i++) {\n\t\t\thelper.measure(() => {});\n\t\t}\n\t\tassert.strictEqual(logger.events.length, 0);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\n\t\t// Again to make sure the internal counter is reset correctly\n\t\tfor (let i = 0; i < sampling - 1; i++) {\n\t\t\thelper.measure(() => {});\n\t\t}\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 2);\n\t});\n\n\tit(\"does not include aggregate properties when it shouldn't\", () => {\n\t\tconst helper = new SampledTelemetryHelper({ eventName: \"testEvent\" }, logger, 1, false);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\tconst event = logger.events[0];\n\t\tensurePropertiesExist(event, standardEventProperties, true);\n\t\tassert.strictEqual(event.count, 1);\n\t});\n\n\tit(\"includes aggregate properties when it should\", () => {\n\t\tconst helper = new SampledTelemetryHelper({ eventName: \"testEvent\" }, logger, 1, true);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\tconst event = logger.events[0];\n\t\tensurePropertiesExist(event, [...standardEventProperties, ...aggregateProperties], true);\n\t\tassert.strictEqual(event.count, 1);\n\t});\n\n\tit(\"includes properties from base event when no aggregate properties are included\", () => {\n\t\tconst helper = new SampledTelemetryHelper(\n\t\t\t{ eventName: \"testEvent\", myProp: \"myValue\" },\n\t\t\tlogger,\n\t\t\t1,\n\t\t\tfalse,\n\t\t);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\tconst event = logger.events[0];\n\t\tensurePropertiesExist(event, [...standardEventProperties, \"myProp\"], true);\n\t\tassert.strictEqual(event.count, 1);\n\t\tassert.strictEqual(event.myProp, \"myValue\");\n\t});\n\n\tit(\"includes properties from base event when aggregate properties are included\", () => {\n\t\tconst helper = new SampledTelemetryHelper(\n\t\t\t{ eventName: \"testEvent\", myProp: \"myValue\" },\n\t\t\tlogger,\n\t\t\t1,\n\t\t\ttrue,\n\t\t);\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\tconst event = logger.events[0];\n\t\tensurePropertiesExist(\n\t\t\tevent,\n\t\t\t[...standardEventProperties, ...aggregateProperties, \"myProp\"],\n\t\t\ttrue,\n\t\t);\n\t\tassert.strictEqual(event.count, 1);\n\t\tassert.strictEqual(event.myProp, \"myValue\");\n\t});\n\n\tit(\"tracks buckets separately and includes per-bucket properties\", () => {\n\t\tconst bucket1 = \"bucket1\";\n\t\tconst bucket2 = \"bucket2\";\n\t\tconst bucketProperties: Map<string, ITelemetryBaseProperties> = new Map<\n\t\t\tstring,\n\t\t\tITelemetryBaseProperties\n\t\t>([\n\t\t\t[bucket1, { prop1: \"value1\" }],\n\t\t\t[bucket2, { prop2: \"value2\" }],\n\t\t]);\n\n\t\tconst helper = new SampledTelemetryHelper(\n\t\t\t{ eventName: \"testEvent\" },\n\t\t\tlogger,\n\t\t\t3,\n\t\t\tfalse,\n\t\t\tbucketProperties,\n\t\t);\n\n\t\tfor (let i = 0; i < 9; i++) {\n\t\t\thelper.measure(() => {}, bucket1);\n\t\t}\n\t\tfor (let i = 0; i < 7; i++) {\n\t\t\thelper.measure(() => {}, bucket2);\n\t\t}\n\n\t\tassert.strictEqual(logger.events.filter((x) => x.prop1 === \"value1\").length, 3);\n\t\tassert.strictEqual(logger.events.filter((x) => x.prop2 === \"value2\").length, 2);\n\t});\n\n\tit(\"bucket properties do not override measurement properties\", () => {\n\t\t// If the names of the properties specified by the consumers for a bucket overlap with the names\n\t\t// of the standard properties we put in the telemetry events, our values should not be overwritten\n\t\t// by the custom properties.\n\n\t\tconst bucket1 = \"bucket1\";\n\t\tconst bucketProperties: Map<string, ITelemetryBaseProperties> = new Map<\n\t\t\tstring,\n\t\t\tITelemetryBaseProperties\n\t\t>([\n\t\t\t// Here just using a duration value that we can be sure will not be the actual value, to make sure the\n\t\t\t// actuals is different from this one (since it's much harder to guarantee an exact duration\n\t\t\t// value to test for equality).\n\t\t\t[bucket1, { duration: 1000, count: 1000 }],\n\t\t]);\n\n\t\tconst helper = new SampledTelemetryHelper(\n\t\t\t{ eventName: \"testEvent\" },\n\t\t\tlogger,\n\t\t\t1,\n\t\t\tfalse,\n\t\t\tbucketProperties,\n\t\t);\n\t\thelper.measure(() => {}, bucket1);\n\t\tassert.strictEqual(logger.events.length, 1);\n\t\tconst event = logger.events[0];\n\t\tassert.strictEqual(event.count, 1);\n\t\tassert(event.duration !== bucketProperties.get(\"bucket1\")!.duration);\n\t});\n\n\tit(\"generates telemetry event from buffered data when disposed\", () => {\n\t\t// Logging several buckets to make sure they are all flushed. We can only distingush the events based on the\n\t\t// custom properties added to the event for each bucket\n\t\tconst bucket1 = \"bucket1\";\n\t\tconst bucket2 = \"bucket2\";\n\t\tconst bucketProperties: Map<string, ITelemetryBaseProperties> = new Map<\n\t\t\tstring,\n\t\t\tITelemetryBaseProperties\n\t\t>([\n\t\t\t[bucket1, { prop1: \"value1\" }],\n\t\t\t[bucket2, { prop2: \"value2\" }],\n\t\t]);\n\n\t\tconst helper = new SampledTelemetryHelper(\n\t\t\t{ eventName: \"testEvent\" },\n\t\t\tlogger,\n\t\t\t5,\n\t\t\tfalse,\n\t\t\tbucketProperties,\n\t\t);\n\n\t\t// Only measure 4 times when we need 5 samples before writing the telemetry event\n\t\tfor (let i = 0; i < 4; i++) {\n\t\t\thelper.measure(() => {}, bucket1);\n\t\t\thelper.measure(() => {}, bucket2);\n\t\t}\n\n\t\t// Nothing should have been logged yet\n\t\tassert.strictEqual(logger.events.length, 0);\n\n\t\t// After disposing, there should be one event for each bucket\n\t\thelper.dispose();\n\t\tassert.strictEqual(logger.events.filter((x) => x.prop1 === \"value1\").length, 1);\n\t\tassert.strictEqual(logger.events.filter((x) => x.prop2 === \"value2\").length, 1);\n\t});\n\n\tit(\"no event is generated on dispose if there's no pending 'buffered' data\", () => {\n\t\tconst helper = new SampledTelemetryHelper({ eventName: \"testEvent\" }, logger, 2);\n\n\t\t// Nothing should have been logged after the first call\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 0);\n\n\t\t// On the second call, we should have 1 event\n\t\thelper.measure(() => {});\n\t\tassert.strictEqual(logger.events.length, 1);\n\n\t\t// After disposing, there should still be just one event\n\t\thelper.dispose();\n\t\tassert.strictEqual(logger.events.length, 1);\n\t});\n});\n\nfunction ensurePropertiesExist(\n\tobject: ITelemetryPerformanceEventExt,\n\tpropNames: string[],\n\tnoExtraProperties: boolean = false,\n): void {\n\tfor (const name of propNames) {\n\t\tassert.strictEqual(object[name] !== undefined, true);\n\t}\n\n\tif (noExtraProperties) {\n\t\tconst actualNumberOfProps = Object.keys(object).length;\n\t\tconst expectedNumberOfProps = propNames.length;\n\t\tif (actualNumberOfProps !== expectedNumberOfProps) {\n\t\t\tassert.fail(\n\t\t\t\t`Object contains unexpected properties ` +\n\t\t\t\t\t`(${actualNumberOfProps} found, ${expectedNumberOfProps}) expected)`,\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
|