UNPKG

3.67 kBPlain TextView Raw
1/**
2 * -------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4 * See License in the project root for license information.
5 * -------------------------------------------------------------------------------------------
6 */
7
8/**
9 * @module TelemetryHandler
10 */
11import { isCustomHost, isGraphURL } from "../GraphRequestUtil";
12import { Context } from "../IContext";
13import { PACKAGE_VERSION } from "../Version";
14import { Middleware } from "./IMiddleware";
15import { MiddlewareControl } from "./MiddlewareControl";
16import { appendRequestHeader, generateUUID, getRequestHeader, setRequestHeader } from "./MiddlewareUtil";
17import { TelemetryHandlerOptions } from "./options/TelemetryHandlerOptions";
18
19/**
20 * @class
21 * @implements Middleware
22 * Class for TelemetryHandler
23 */
24export class TelemetryHandler implements Middleware {
25 /**
26 * @private
27 * @static
28 * A member holding the name of the client request id header
29 */
30 private static CLIENT_REQUEST_ID_HEADER = "client-request-id";
31
32 /**
33 * @private
34 * @static
35 * A member holding the name of the sdk version header
36 */
37 private static SDK_VERSION_HEADER = "SdkVersion";
38
39 /**
40 * @private
41 * @static
42 * A member holding the language prefix for the sdk version header value
43 */
44 private static PRODUCT_NAME = "graph-js";
45
46 /**
47 * @private
48 * @static
49 * A member holding the key for the feature usage metrics
50 */
51 private static FEATURE_USAGE_STRING = "featureUsage";
52
53 /**
54 * @private
55 * A member to hold next middleware in the middleware chain
56 */
57 private nextMiddleware: Middleware;
58
59 /**
60 * @public
61 * @async
62 * To execute the current middleware
63 * @param {Context} context - The context object of the request
64 * @returns A Promise that resolves to nothing
65 */
66 public async execute(context: Context): Promise<void> {
67 const url = typeof context.request === "string" ? context.request : context.request.url;
68 if (isGraphURL(url) || (context.customHosts && isCustomHost(url, context.customHosts))) {
69 // Add telemetry only if the request url is a Graph URL.
70 // Errors are reported as in issue #265 if headers are present when redirecting to a non Graph URL
71 let clientRequestId: string = getRequestHeader(context.request, context.options, TelemetryHandler.CLIENT_REQUEST_ID_HEADER);
72 if (!clientRequestId) {
73 clientRequestId = generateUUID();
74 setRequestHeader(context.request, context.options, TelemetryHandler.CLIENT_REQUEST_ID_HEADER, clientRequestId);
75 }
76 let sdkVersionValue = `${TelemetryHandler.PRODUCT_NAME}/${PACKAGE_VERSION}`;
77 let options: TelemetryHandlerOptions;
78 if (context.middlewareControl instanceof MiddlewareControl) {
79 options = context.middlewareControl.getMiddlewareOptions(TelemetryHandlerOptions) as TelemetryHandlerOptions;
80 }
81 if (options) {
82 const featureUsage: string = options.getFeatureUsage();
83 sdkVersionValue += ` (${TelemetryHandler.FEATURE_USAGE_STRING}=${featureUsage})`;
84 }
85 appendRequestHeader(context.request, context.options, TelemetryHandler.SDK_VERSION_HEADER, sdkVersionValue);
86 } else {
87 // Remove telemetry headers if present during redirection.
88 delete context.options.headers[TelemetryHandler.CLIENT_REQUEST_ID_HEADER];
89 delete context.options.headers[TelemetryHandler.SDK_VERSION_HEADER];
90 }
91 return await this.nextMiddleware.execute(context);
92 }
93
94 /**
95 * @public
96 * To set the next middleware in the chain
97 * @param {Middleware} next - The middleware instance
98 * @returns Nothing
99 */
100 public setNext(next: Middleware): void {
101 this.nextMiddleware = next;
102 }
103}