@fluidframework/app-insights-logger 2.0.0-dev.7.3.0.210328
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/.eslintrc.js +11 -0
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +57 -0
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/api-extractor.json +20 -0
- package/api-report/app-insights-logger.api.md +42 -0
- package/dist/fluidAppInsightsLogger.d.ts +164 -0
- package/dist/fluidAppInsightsLogger.d.ts.map +1 -0
- package/dist/fluidAppInsightsLogger.js +172 -0
- package/dist/fluidAppInsightsLogger.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/fluidAppInsightsLogger.d.ts +164 -0
- package/lib/fluidAppInsightsLogger.d.ts.map +1 -0
- package/lib/fluidAppInsightsLogger.js +168 -0
- package/lib/fluidAppInsightsLogger.js.map +1 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -0
- package/lib/test/fluidAppInsightsLogger.spec.d.ts +2 -0
- package/lib/test/fluidAppInsightsLogger.spec.d.ts.map +1 -0
- package/lib/test/fluidAppInsightsLogger.spec.js +625 -0
- package/lib/test/fluidAppInsightsLogger.spec.js.map +1 -0
- package/package.json +79 -0
- package/prettier.config.cjs +8 -0
- package/src/fluidAppInsightsLogger.ts +310 -0
- package/src/index.ts +21 -0
- package/tsconfig.esnext.json +7 -0
- package/tsconfig.json +10 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
extends: [require.resolve("@fluidframework/eslint-config-fluid/strict"), "prettier"],
|
|
8
|
+
parserOptions: {
|
|
9
|
+
project: ["./tsconfig.json"],
|
|
10
|
+
},
|
|
11
|
+
};
|
package/.mocharc.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common");
|
|
9
|
+
|
|
10
|
+
const packageDir = __dirname;
|
|
11
|
+
const config = getFluidTestMochaConfig(packageDir);
|
|
12
|
+
module.exports = config;
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @fluid-internal/app-insights-logger
|
|
2
|
+
|
|
3
|
+
## 2.0.0-internal.7.2.0
|
|
4
|
+
|
|
5
|
+
Dependency updates only.
|
|
6
|
+
|
|
7
|
+
## 2.0.0-internal.7.1.0
|
|
8
|
+
|
|
9
|
+
Dependency updates only.
|
|
10
|
+
|
|
11
|
+
## 2.0.0-internal.7.0.0
|
|
12
|
+
|
|
13
|
+
Dependency updates only.
|
|
14
|
+
|
|
15
|
+
## 2.0.0-internal.6.4.0
|
|
16
|
+
|
|
17
|
+
Dependency updates only.
|
|
18
|
+
|
|
19
|
+
## 2.0.0-internal.6.3.0
|
|
20
|
+
|
|
21
|
+
Dependency updates only.
|
|
22
|
+
|
|
23
|
+
## 2.0.0-internal.6.2.0
|
|
24
|
+
|
|
25
|
+
Dependency updates only.
|
|
26
|
+
|
|
27
|
+
## 2.0.0-internal.6.1.0
|
|
28
|
+
|
|
29
|
+
Dependency updates only.
|
|
30
|
+
|
|
31
|
+
## 2.0.0-internal.6.0.0
|
|
32
|
+
|
|
33
|
+
Dependency updates only.
|
|
34
|
+
|
|
35
|
+
## 2.0.0-internal.5.4.0
|
|
36
|
+
|
|
37
|
+
Dependency updates only.
|
|
38
|
+
|
|
39
|
+
## 2.0.0-internal.5.3.0
|
|
40
|
+
|
|
41
|
+
Dependency updates only.
|
|
42
|
+
|
|
43
|
+
## 2.0.0-internal.5.2.0
|
|
44
|
+
|
|
45
|
+
Dependency updates only.
|
|
46
|
+
|
|
47
|
+
## 2.0.0-internal.5.1.0
|
|
48
|
+
|
|
49
|
+
Dependency updates only.
|
|
50
|
+
|
|
51
|
+
## 2.0.0-internal.5.0.0
|
|
52
|
+
|
|
53
|
+
Dependency updates only.
|
|
54
|
+
|
|
55
|
+
## 2.0.0-internal.4.4.0
|
|
56
|
+
|
|
57
|
+
Dependency updates only.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @fluidframework/app-insights-logger
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This `app-insights-logger` package provides a Fluid telemetry logger that will route Fluid telemetry to Azure App Insights using the `ApplicationInsights.trackEvent` API provided by the [@microsoft/applicationinsights-web](https://www.npmjs.com/package/@microsoft/applicationinsights-web) package. The logger is intended for use by browser based web applications, not NodeJS applications [as stated by the App Insights Web SDK.](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview?tabs=net)
|
|
6
|
+
|
|
7
|
+
## What is Application Insights?
|
|
8
|
+
|
|
9
|
+
At a high level, App Insights is an Azure cloud service for aggregating, visualizing, analyzing, and alerting on metrics related to a given “service” or “application”.
|
|
10
|
+
You create an App Insights Instance and then configure your applications to send data to your instance using either Azure provided SDK’s or REST APIs.
|
|
11
|
+
This could be general machine related health being automatically reported to the instance when you install a logging program on your service’s machines or custom metrics that you manually configure your applications to send. Keep in mind this logger is intended for use with browser based web applications, not pure nodeJS.
|
|
12
|
+
In our case, we are sending custom metrics. [Learn more about Azure App Insights with their docs](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview?tabs=net)
|
|
13
|
+
|
|
14
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_INSTALLATION_SECTION:includeHeading=TRUE&devDependency=FALSE) -->
|
|
15
|
+
|
|
16
|
+
<!-- prettier-ignore-start -->
|
|
17
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
To get started, install the package by running the following command:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm i @fluidframework/app-insights-logger
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<!-- prettier-ignore-end -->
|
|
28
|
+
|
|
29
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
30
|
+
|
|
31
|
+
## Use case
|
|
32
|
+
|
|
33
|
+
The primary use case of sending telemetry to Azure App Insights allows users to analyze and store telemetry logs without having to manually setup complex infrastructure.
|
|
34
|
+
Once in App Insights users can leverage Azure's log exploring tools to analyze logs.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
In order to use this logger, users will first have to initialize an `ApplicationInsights` client from the `@microsoft/applicationinsights-web` package. In most cases, initializing the `ApplicationInsights` client will be just providing your App Insight instances connection string AND calling `.loadAppInsights()` on your client. [Learn more about the App Insights SDK](https://github.com/microsoft/ApplicationInsights-JS#before-getting-started)
|
|
39
|
+
|
|
40
|
+
Here is an example usage:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const appInsightsClient = new ApplicationInsights({
|
|
44
|
+
config: {
|
|
45
|
+
connectionString:
|
|
46
|
+
"InstrumentationKey=abcdefgh-ijkl-mnop-qrst-uvwxyz6ffd9c;IngestionEndpoint=https://westus2-2.in.applicationinsights.azure.com/;LiveEndpoint=https://westus2.livediagnostics.monitor.azure.com/",
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Initializes the App Insights client. Without this, logs will not be sent to Azure.
|
|
51
|
+
appInsightsClient.loadAppInsights();
|
|
52
|
+
|
|
53
|
+
const logger = new FluidAppInsightsLogger(appInsightsClient);
|
|
54
|
+
|
|
55
|
+
// Example of sending an event to app insights using the FluidAppInsightsLogger directly
|
|
56
|
+
logger.send({ category: "mockEvent", eventName: "mockEventName" });
|
|
57
|
+
|
|
58
|
+
// More commonly, we would provide the logger to the instance of the Fluid Loader used by your application. This enables Fluid telemetry to be automatically sent to App Insights as your Fluid App is running.
|
|
59
|
+
const tinyliciousClient = new TinyliciousClient({
|
|
60
|
+
logger,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const createContainerResult = await tinyliciousClient.createContainer(containerSchema);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Viewing Logs in App Insights
|
|
67
|
+
|
|
68
|
+
From the Azure web portal, navigate to your app insights instance. Now, go to the "Logs" for your instance, this should be an option within the left side panel. Finally, from this page, you can query for telemetry events, which will be stored in the customEvents table. As an example, you can issue this simple query to get recent telemetry events sent to the customEvents table:
|
|
69
|
+
|
|
70
|
+
- Get a count of each distinct log event name and category of log event
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
customEvents
|
|
74
|
+
| summarize count() by name, tostring(customDimensions.category)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- Get all performance related logs
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
customEvents
|
|
81
|
+
| where customDimensions.name == "performance"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_API_DOCS_SECTION:includeHeading=TRUE) -->
|
|
85
|
+
|
|
86
|
+
<!-- prettier-ignore-start -->
|
|
87
|
+
|
|
88
|
+
<!-- This section is automatically generated. To update it, make the appropriate changes to docs/md-magic.config.js or the embedded content, then run 'npm run build:md-magic' in the docs folder. -->
|
|
89
|
+
|
|
90
|
+
<!-- prettier-ignore-end -->
|
|
91
|
+
|
|
92
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
93
|
+
|
|
94
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_HELP_SECTION:includeHeading=TRUE) -->
|
|
95
|
+
|
|
96
|
+
<!-- prettier-ignore-start -->
|
|
97
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
98
|
+
|
|
99
|
+
## Help
|
|
100
|
+
|
|
101
|
+
Not finding what you're looking for in this README? Check out our [GitHub
|
|
102
|
+
Wiki](https://github.com/microsoft/FluidFramework/wiki) or [fluidframework.com](https://fluidframework.com/docs/).
|
|
103
|
+
|
|
104
|
+
Still not finding what you're looking for? Please [file an
|
|
105
|
+
issue](https://github.com/microsoft/FluidFramework/wiki/Submitting-Bugs-and-Feature-Requests).
|
|
106
|
+
|
|
107
|
+
Thank you!
|
|
108
|
+
|
|
109
|
+
<!-- prettier-ignore-end -->
|
|
110
|
+
|
|
111
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
112
|
+
|
|
113
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_CONTRIBUTION_GUIDELINES_SECTION:includeHeading=TRUE) -->
|
|
114
|
+
|
|
115
|
+
<!-- prettier-ignore-start -->
|
|
116
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
117
|
+
|
|
118
|
+
## Contribution Guidelines
|
|
119
|
+
|
|
120
|
+
There are many ways to [contribute](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md) to Fluid.
|
|
121
|
+
|
|
122
|
+
- Participate in Q&A in our [GitHub Discussions](https://github.com/microsoft/FluidFramework/discussions).
|
|
123
|
+
- [Submit bugs](https://github.com/microsoft/FluidFramework/issues) and help us verify fixes as they are checked in.
|
|
124
|
+
- Review the [source code changes](https://github.com/microsoft/FluidFramework/pulls).
|
|
125
|
+
- [Contribute bug fixes](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md).
|
|
126
|
+
|
|
127
|
+
Detailed instructions for working in the repo can be found in the [Wiki](https://github.com/microsoft/FluidFramework/wiki).
|
|
128
|
+
|
|
129
|
+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
|
130
|
+
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
131
|
+
|
|
132
|
+
This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
|
|
133
|
+
Use of these trademarks or logos must follow Microsoft’s [Trademark & Brand Guidelines](https://www.microsoft.com/trademarks).
|
|
134
|
+
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
|
|
135
|
+
|
|
136
|
+
<!-- prettier-ignore-end -->
|
|
137
|
+
|
|
138
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
139
|
+
|
|
140
|
+
<!-- AUTO-GENERATED-CONTENT:START (README_TRADEMARK_SECTION:includeHeading=TRUE) -->
|
|
141
|
+
|
|
142
|
+
<!-- prettier-ignore-start -->
|
|
143
|
+
<!-- NOTE: This section is automatically generated using @fluid-tools/markdown-magic. Do not update these generated contents directly. -->
|
|
144
|
+
|
|
145
|
+
## Trademark
|
|
146
|
+
|
|
147
|
+
This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
|
|
148
|
+
|
|
149
|
+
Use of these trademarks or logos must follow Microsoft's [Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
|
|
150
|
+
|
|
151
|
+
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
|
|
152
|
+
|
|
153
|
+
<!-- prettier-ignore-end -->
|
|
154
|
+
|
|
155
|
+
<!-- AUTO-GENERATED-CONTENT:END -->
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "@fluidframework/build-common/api-extractor-base.json",
|
|
4
|
+
|
|
5
|
+
"messages": {
|
|
6
|
+
// The following overrides are workarounds for API-Extractor incorrectly running analysis on our application
|
|
7
|
+
// insights dependency.
|
|
8
|
+
"tsdocMessageReporting": {
|
|
9
|
+
"tsdoc-escape-right-brace": {
|
|
10
|
+
"logLevel": "none"
|
|
11
|
+
},
|
|
12
|
+
"tsdoc-malformed-inline-tag": {
|
|
13
|
+
"logLevel": "none"
|
|
14
|
+
},
|
|
15
|
+
"tsdoc-undefined-tag": {
|
|
16
|
+
"logLevel": "none"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
## API Report File for "@fluidframework/app-insights-logger"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import { ApplicationInsights } from '@microsoft/applicationinsights-web';
|
|
8
|
+
import { ITelemetryBaseEvent } from '@fluidframework/core-interfaces';
|
|
9
|
+
import { ITelemetryBaseLogger } from '@fluidframework/core-interfaces';
|
|
10
|
+
import { TelemetryEventCategory } from '@fluidframework/telemetry-utils';
|
|
11
|
+
|
|
12
|
+
// @public
|
|
13
|
+
export interface CategoryFilter {
|
|
14
|
+
categories: TelemetryEventCategory[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// @public @sealed
|
|
18
|
+
export class FluidAppInsightsLogger implements ITelemetryBaseLogger {
|
|
19
|
+
constructor(client: ApplicationInsights, config?: FluidAppInsightsLoggerConfig);
|
|
20
|
+
send(event: ITelemetryBaseEvent): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// @public
|
|
24
|
+
export interface FluidAppInsightsLoggerConfig {
|
|
25
|
+
filtering: {
|
|
26
|
+
mode: "inclusive" | "exclusive";
|
|
27
|
+
filters?: TelemetryFilter[];
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// @public
|
|
32
|
+
export interface NamespaceFilter {
|
|
33
|
+
namespacePattern: string;
|
|
34
|
+
namespacePatternExceptions?: Set<string>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { TelemetryEventCategory }
|
|
38
|
+
|
|
39
|
+
// @public
|
|
40
|
+
export type TelemetryFilter = CategoryFilter | NamespaceFilter | (CategoryFilter & NamespaceFilter);
|
|
41
|
+
|
|
42
|
+
```
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { type ApplicationInsights } from "@microsoft/applicationinsights-web";
|
|
6
|
+
import { type ITelemetryBaseEvent, type ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
7
|
+
import { type TelemetryEventCategory } from "@fluidframework/telemetry-utils";
|
|
8
|
+
/**
|
|
9
|
+
* The configuration object for the {@link FluidAppInsightsLogger}
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export interface FluidAppInsightsLoggerConfig {
|
|
14
|
+
/**
|
|
15
|
+
* This Configuration defines how filtering will be applied to Fluid telemetry events flowing through the logger.
|
|
16
|
+
* This determines which events will be sent to Azure App Insights.
|
|
17
|
+
*/
|
|
18
|
+
filtering: {
|
|
19
|
+
/**
|
|
20
|
+
* Determines whether all telemetry events are sent or not sent by default and whether filters will exclude matching telemetry events or include them.
|
|
21
|
+
*
|
|
22
|
+
* "inclusive" mode means all logs are NOT SENT by default and only the events that match at least one or more specified filters WILL be sent (included).
|
|
23
|
+
*
|
|
24
|
+
* "exclusive" mode means all logs ARE SENT by default and only the events that match at least one or more specified filters WILL NOT be sent (excluded).
|
|
25
|
+
*/
|
|
26
|
+
mode: "inclusive" | "exclusive";
|
|
27
|
+
/**
|
|
28
|
+
* Controls the filtering of log events.
|
|
29
|
+
*
|
|
30
|
+
* @remarks Leaving this undefined will be treated as an empty array.
|
|
31
|
+
*
|
|
32
|
+
* In order for the filters to be valid they must meet the following conditions:
|
|
33
|
+
*
|
|
34
|
+
* 1. There must not be any two filters with the same `namespacePattern`.
|
|
35
|
+
*
|
|
36
|
+
* 2. All {@link NamespaceFilter} must not have any defined `namespacePatternException` that is not a child of the parent `namespacePattern`
|
|
37
|
+
*/
|
|
38
|
+
filters?: TelemetryFilter[];
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A filter used to match against the category of a telemetry event
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export interface CategoryFilter {
|
|
47
|
+
/**
|
|
48
|
+
* The categories of telemetry events that this filter applies to
|
|
49
|
+
*/
|
|
50
|
+
categories: TelemetryEventCategory[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A filter used to match against the namespaces of a telemetry event
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
export interface NamespaceFilter {
|
|
58
|
+
/**
|
|
59
|
+
* The namespace pattern to filter telemetry events.
|
|
60
|
+
*
|
|
61
|
+
* @remarks This will match namespaces that start with the given string. It is not a Regex pattern.
|
|
62
|
+
* @example
|
|
63
|
+
* "perf:latency" will match any namespace starting with "perf:latency"
|
|
64
|
+
*/
|
|
65
|
+
namespacePattern: string;
|
|
66
|
+
/**
|
|
67
|
+
* A list of namespace patterns to explicitly exclude from the filter.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* If you have a namespacePattern of "perf:latency" but want to exclude
|
|
71
|
+
* events from "perf:latency:ops", you would add "perf:latency:ops" to this list.
|
|
72
|
+
*/
|
|
73
|
+
namespacePatternExceptions?: Set<string>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Object used with an {@link FluidAppInsightsLoggerConfig}
|
|
77
|
+
* to define a filter with logic for matching it to telemetry events.
|
|
78
|
+
* Filters can include either a category, namespace or both types of filters; a valid filter must have at least one defined.
|
|
79
|
+
* Not definining the `categories` filter array is the same as providing an array with all possible categories.
|
|
80
|
+
*
|
|
81
|
+
* Events must satisify the following rules for a telemetry filter:
|
|
82
|
+
*
|
|
83
|
+
* 1. The event must match the requirements of the most specific relevant filter to it. This takes precedence over a more generic filter.
|
|
84
|
+
* The less categories and longer the namespace within a filter, the more specific it is. Definining no categories is equivalant to defining all categories.
|
|
85
|
+
*
|
|
86
|
+
* 2. If a {@link TelemetryFilter} specifies both `categories` and a `namespace`, the event must match both.
|
|
87
|
+
*
|
|
88
|
+
* 3. If only `categories` or a `namespace` is provided, the event should just match the with whatever was defined.
|
|
89
|
+
*
|
|
90
|
+
* 4. If a `namespace` pattern exception is specified in the {@link TelemetryFilter}, the event should not match the exception pattern.
|
|
91
|
+
*
|
|
92
|
+
* @public
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* With the following configuration, an event `{ namespace: "A.B.C", categories: ["generic"] }` will not be sent despite matching the first, less specific filter because it did not match the second filter which was the most relevant and specific
|
|
96
|
+
* ```
|
|
97
|
+
* const logger = new FluidAppInsightsLogger(appInsightsClient, {
|
|
98
|
+
* filtering: {
|
|
99
|
+
* mode: "inclusive",
|
|
100
|
+
* filters: [
|
|
101
|
+
* {
|
|
102
|
+
* namespacePattern: "A:B",
|
|
103
|
+
* categories: ["generic", "error"],
|
|
104
|
+
* },
|
|
105
|
+
* {
|
|
106
|
+
* namespacePattern: "A:B:C",
|
|
107
|
+
* categories: ["error"],
|
|
108
|
+
* },
|
|
109
|
+
* ],
|
|
110
|
+
* },
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export type TelemetryFilter = CategoryFilter | NamespaceFilter | (CategoryFilter & NamespaceFilter);
|
|
115
|
+
/**
|
|
116
|
+
* An implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger | ITelemetryBaseLogger}
|
|
117
|
+
* that routes Fluid telemetry events to Azure App Insights using the App Insights trackEvent API.
|
|
118
|
+
* The provided ApplicationInsights instance MUST be initialized with client.loadAppInsights()
|
|
119
|
+
* or else logging will not occur.
|
|
120
|
+
*
|
|
121
|
+
* @sealed
|
|
122
|
+
* @public
|
|
123
|
+
*/
|
|
124
|
+
export declare class FluidAppInsightsLogger implements ITelemetryBaseLogger {
|
|
125
|
+
/**
|
|
126
|
+
* The Azure ApplicationInsights client utilized by this logger.
|
|
127
|
+
* The ApplicationInsights instance MUST be initialized with client.loadAppInsights()
|
|
128
|
+
* or else logging will not occur.
|
|
129
|
+
*/
|
|
130
|
+
private readonly baseLoggingClient;
|
|
131
|
+
private readonly config;
|
|
132
|
+
constructor(client: ApplicationInsights, config?: FluidAppInsightsLoggerConfig);
|
|
133
|
+
/**
|
|
134
|
+
* Routes Fluid telemetry events to the trackEvent App Insights API.
|
|
135
|
+
* This method also uses the provided {@link FluidAppInsightsLoggerConfig} to
|
|
136
|
+
* determine whether an event should be sent or not.
|
|
137
|
+
*/
|
|
138
|
+
send(event: ITelemetryBaseEvent): void;
|
|
139
|
+
private shouldSendEvent;
|
|
140
|
+
/**
|
|
141
|
+
* Checks if a given telemetry event conforms to any of the provided {@link TelemetryFilter} rules.
|
|
142
|
+
*
|
|
143
|
+
* 1. The event must match the requirements of the most specific relevant filter to it. This takes precedence over a more generic filter.
|
|
144
|
+
* The less categories and longer the namespace within a filter, the more specific it is. Definining no categories is equivalant to defining all categories.
|
|
145
|
+
*
|
|
146
|
+
* 2. If a {@link TelemetryFilter} specifies both `categories` and a `namespace`, the event must match both.
|
|
147
|
+
*
|
|
148
|
+
* 3. If only `categories` or a `namespace` is provided, the event should match either one of them.
|
|
149
|
+
*
|
|
150
|
+
* 4. If a `namespace` pattern exception is specified in the {@link TelemetryFilter}, the event should not match the exception pattern.
|
|
151
|
+
*
|
|
152
|
+
* @param event - The telemetry event to check against the filters.
|
|
153
|
+
*
|
|
154
|
+
* @returns `true` if the event matches any filter, otherwise `false`.
|
|
155
|
+
*/
|
|
156
|
+
private doesEventMatchFilter;
|
|
157
|
+
/**
|
|
158
|
+
* Checks an array of telemetry filters for any issues, merges redundant filters, and returns a fully validated array.
|
|
159
|
+
*
|
|
160
|
+
* @throws An Error if there are two filters with duplicate namespace patterns or a filter with a pattern exception that is not a child of the parent pattern.
|
|
161
|
+
*/
|
|
162
|
+
private validateFilters;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=fluidAppInsightsLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fluidAppInsightsLogger.d.ts","sourceRoot":"","sources":["../src/fluidAppInsightsLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;;OAGG;IACH,SAAS,EAAE;QACV;;;;;;WAMG;QACH,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;QAChC;;;;;;;;;;WAUG;QACH,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;KAC5B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,UAAU,EAAE,sBAAsB,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,CAAC,cAAc,GAAG,eAAe,CAAC,CAAC;AAEpG;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,YAAW,oBAAoB;IAClE;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAsB;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBACnC,MAAM,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,4BAA4B;IA6BrF;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAS7C,OAAO,CAAC,eAAe;IAYvB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,oBAAoB;IA+D5B;;;;OAIG;IACH,OAAO,CAAC,eAAe;CA8BvB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.FluidAppInsightsLogger = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* An implementation of {@link @fluidframework/core-interfaces#ITelemetryBaseLogger | ITelemetryBaseLogger}
|
|
10
|
+
* that routes Fluid telemetry events to Azure App Insights using the App Insights trackEvent API.
|
|
11
|
+
* The provided ApplicationInsights instance MUST be initialized with client.loadAppInsights()
|
|
12
|
+
* or else logging will not occur.
|
|
13
|
+
*
|
|
14
|
+
* @sealed
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
class FluidAppInsightsLogger {
|
|
18
|
+
constructor(client, config) {
|
|
19
|
+
this.baseLoggingClient = client;
|
|
20
|
+
// Deep copy config to prevent issues if user mutates the object they passed in
|
|
21
|
+
this.config = config
|
|
22
|
+
? structuredClone(config)
|
|
23
|
+
: {
|
|
24
|
+
filtering: {
|
|
25
|
+
mode: "exclusive",
|
|
26
|
+
filters: [],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
if (this.config.filtering.filters) {
|
|
30
|
+
this.validateFilters(this.config.filtering.filters);
|
|
31
|
+
// Sort filters by longest namespace first.
|
|
32
|
+
this.config.filtering.filters.sort((a, b) => {
|
|
33
|
+
const namespaceALength = "namespacePattern" in a && a.namespacePattern !== undefined
|
|
34
|
+
? a.namespacePattern.length
|
|
35
|
+
: 0;
|
|
36
|
+
const namespaceBLength = "namespacePattern" in b && b.namespacePattern !== undefined
|
|
37
|
+
? b.namespacePattern.length
|
|
38
|
+
: 0;
|
|
39
|
+
return namespaceBLength - namespaceALength;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Routes Fluid telemetry events to the trackEvent App Insights API.
|
|
45
|
+
* This method also uses the provided {@link FluidAppInsightsLoggerConfig} to
|
|
46
|
+
* determine whether an event should be sent or not.
|
|
47
|
+
*/
|
|
48
|
+
send(event) {
|
|
49
|
+
if (this.shouldSendEvent(event)) {
|
|
50
|
+
this.baseLoggingClient.trackEvent({
|
|
51
|
+
name: event.eventName,
|
|
52
|
+
properties: event,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
shouldSendEvent(event) {
|
|
57
|
+
// No events should be sent by default in "inclusive" mode, and all events should be
|
|
58
|
+
// sent by default in "exclusive" mode.
|
|
59
|
+
let shouldSendEvent = this.config.filtering.mode === "inclusive" ? false : true;
|
|
60
|
+
if (this.doesEventMatchFilter(event)) {
|
|
61
|
+
// If the event does match a filter, in "inclusive" filter mode that means it should
|
|
62
|
+
// be sent (included). In "exclusive" mode the opposite is true.
|
|
63
|
+
shouldSendEvent = this.config.filtering.mode === "inclusive" ? true : false;
|
|
64
|
+
}
|
|
65
|
+
return shouldSendEvent;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a given telemetry event conforms to any of the provided {@link TelemetryFilter} rules.
|
|
69
|
+
*
|
|
70
|
+
* 1. The event must match the requirements of the most specific relevant filter to it. This takes precedence over a more generic filter.
|
|
71
|
+
* The less categories and longer the namespace within a filter, the more specific it is. Definining no categories is equivalant to defining all categories.
|
|
72
|
+
*
|
|
73
|
+
* 2. If a {@link TelemetryFilter} specifies both `categories` and a `namespace`, the event must match both.
|
|
74
|
+
*
|
|
75
|
+
* 3. If only `categories` or a `namespace` is provided, the event should match either one of them.
|
|
76
|
+
*
|
|
77
|
+
* 4. If a `namespace` pattern exception is specified in the {@link TelemetryFilter}, the event should not match the exception pattern.
|
|
78
|
+
*
|
|
79
|
+
* @param event - The telemetry event to check against the filters.
|
|
80
|
+
*
|
|
81
|
+
* @returns `true` if the event matches any filter, otherwise `false`.
|
|
82
|
+
*/
|
|
83
|
+
doesEventMatchFilter(event) {
|
|
84
|
+
for (const filter of this.config.filtering.filters ?? []) {
|
|
85
|
+
if ("namespacePattern" in filter && filter.namespacePattern !== undefined) {
|
|
86
|
+
if (event.eventName.startsWith(filter.namespacePattern)) {
|
|
87
|
+
// Found matching namespace pattern, since filters are ordered in most specific first,
|
|
88
|
+
// this is the most specific, relevant matching filter for the event.
|
|
89
|
+
// By default, if no categories are defined then any category is a valid match.
|
|
90
|
+
let doesFilterCategoriesMatch = true;
|
|
91
|
+
if ("categories" in filter &&
|
|
92
|
+
filter.categories !== undefined &&
|
|
93
|
+
filter.categories.length > 0) {
|
|
94
|
+
doesFilterCategoriesMatch = false;
|
|
95
|
+
const matchingCategory = filter.categories.find((category) => category === event.category);
|
|
96
|
+
doesFilterCategoriesMatch = matchingCategory ? true : false;
|
|
97
|
+
}
|
|
98
|
+
if (doesFilterCategoriesMatch) {
|
|
99
|
+
// The most specific, relevant filter matches so no need to attempt to evaluate against other filters
|
|
100
|
+
// as long as the events namespace does not match any defined namespace exception.
|
|
101
|
+
if (filter.namespacePatternExceptions !== undefined) {
|
|
102
|
+
for (const patternException of filter.namespacePatternExceptions) {
|
|
103
|
+
if (event.eventName.startsWith(patternException)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Filter only has categories defined
|
|
116
|
+
else if ("categories" in filter &&
|
|
117
|
+
filter.categories !== undefined &&
|
|
118
|
+
filter.categories.length > 0) {
|
|
119
|
+
const doesFilterCategoriesMatch = filter.categories.find((category) => category === event.category);
|
|
120
|
+
// This filter specified no namespaces but it has a category match.
|
|
121
|
+
// Since filters are ordered by most specific first, we know that no previous
|
|
122
|
+
// filters with namespaces matched so we can return true.
|
|
123
|
+
if (doesFilterCategoriesMatch) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Checks an array of telemetry filters for any issues, merges redundant filters, and returns a fully validated array.
|
|
138
|
+
*
|
|
139
|
+
* @throws An Error if there are two filters with duplicate namespace patterns or a filter with a pattern exception that is not a child of the parent pattern.
|
|
140
|
+
*/
|
|
141
|
+
validateFilters(filters) {
|
|
142
|
+
const uniqueFilterNamespaces = new Set();
|
|
143
|
+
for (const filter of filters) {
|
|
144
|
+
if ("namespacePattern" in filter && filter.namespacePattern !== undefined) {
|
|
145
|
+
if (uniqueFilterNamespaces.has(filter.namespacePattern)) {
|
|
146
|
+
throw new Error("Cannot have duplicate namespace pattern filters");
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
uniqueFilterNamespaces.add(filter.namespacePattern);
|
|
150
|
+
}
|
|
151
|
+
for (const patternException of filter.namespacePatternExceptions ?? []) {
|
|
152
|
+
if (!patternException.startsWith(filter.namespacePattern)) {
|
|
153
|
+
throw new Error("Cannot have a namespace pattern exception that is not a child of the parent namespace");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if ("categories" in filter && filter.categories !== undefined) {
|
|
158
|
+
// These are filters that only contain "categories". For the purpose of this validation logic, we are treating filters
|
|
159
|
+
// that does not contain a defined namespace as the the same as a blank "" namespace pattern (which will match any event).
|
|
160
|
+
if (uniqueFilterNamespaces.has("")) {
|
|
161
|
+
throw new Error("Cannot have multiple filters that only define categories");
|
|
162
|
+
}
|
|
163
|
+
uniqueFilterNamespaces.add("");
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
throw new Error("Invalid filter does not have either a namespace or a category.");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.FluidAppInsightsLogger = FluidAppInsightsLogger;
|
|
172
|
+
//# sourceMappingURL=fluidAppInsightsLogger.js.map
|