UNPKG

@azure/monitor-opentelemetry

Version:
141 lines 5.46 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import url from "url"; import { redirectPolicyName } from "@azure/core-rest-pipeline"; import { diag } from "@opentelemetry/api"; import { QuickpulseClient } from "../../../generated/index.js"; import { isSameRegisteredDomain } from "../redirectUtils.js"; const applicationInsightsResource = "https://monitor.azure.com/.default"; /** * Quickpulse sender class * @internal */ export class QuickpulseSender { quickpulseClient; instrumentationKey; endpointUrl; credential; credentialScopes; constructor(options) { // Build endpoint using provided configuration or default values this.endpointUrl = options.endpointUrl; const clientOptions = { endpoint: this.endpointUrl, }; this.instrumentationKey = options.instrumentationKey; this.credential = options.credential; // Configure credential scopes if (options.credentialScopes) { this.credentialScopes = Array.isArray(options.credentialScopes) ? options.credentialScopes : [options.credentialScopes]; } else { this.credentialScopes = [applicationInsightsResource]; } if (options.credential) { clientOptions.credentials = { scopes: this.credentialScopes }; } this.quickpulseClient = this.createQuickpulseClient(clientOptions); } createQuickpulseClient(clientOptions) { const client = new QuickpulseClient(this.credential, clientOptions); // Handle redirects in HTTP Sender client.pipeline.removePolicy({ name: redirectPolicyName }); return client; } /** * isSubscribed Quickpulse service * @internal */ async isSubscribed(optionalParams) { try { let responseHeaders = {}; const body = await this.quickpulseClient.isSubscribed(this.instrumentationKey, { ...optionalParams, onResponse: (rawResponse) => { responseHeaders = rawResponse.headers.toJSON(); }, }); return { ...body, xMsQpsSubscribed: responseHeaders["x-ms-qps-subscribed"], xMsQpsConfigurationEtag: responseHeaders["x-ms-qps-configuration-etag"], xMsQpsServicePollingIntervalHint: responseHeaders["x-ms-qps-service-polling-interval-hint"], xMsQpsServiceEndpointRedirectV2: responseHeaders["x-ms-qps-service-endpoint-redirect-v2"], }; } catch (error) { const restError = error; diag.info("Failed to ping Quickpulse service", restError.message); } return; } /** * publish Quickpulse service * @internal */ async publish(optionalParams) { try { let responseHeaders = {}; const body = await this.quickpulseClient.publish(this.instrumentationKey, { ...optionalParams, onResponse: (rawResponse) => { responseHeaders = rawResponse.headers.toJSON(); }, }); return { ...body, xMsQpsSubscribed: responseHeaders["x-ms-qps-subscribed"], xMsQpsConfigurationEtag: responseHeaders["x-ms-qps-configuration-etag"], }; } catch (error) { const restError = error; diag.warn("Failed to post Quickpulse service", restError.message); } return; } /** * Apply a server-issued Live Metrics redirect (`x-ms-qps-service-endpoint-redirect-v2`) by * re-pointing the underlying client at the new host. * * Cross-origin redirects are refused (no state mutated) when the target is neither the configured * Live Metrics host nor under a known Azure Monitor ingestion domain suffix. Refusing them is * required to prevent an attacker-controlled redirect from causing the bearer auth policy to * attach a freshly-signed AAD token (scope `https://monitor.azure.com/.default`) — and the * telemetry body — to a foreign host on the next ping/publish call. */ handlePermanentRedirect(location) { if (location) { let locUrl; try { locUrl = new url.URL(location); } catch { return; } if (!locUrl.host) { return; } let currentHost = ""; try { currentHost = new url.URL(this.endpointUrl).host; } catch { currentHost = ""; } if (!isSameRegisteredDomain(currentHost, locUrl.host)) { diag.error(`Refusing cross-origin Live Metrics redirect to https://${locUrl.host}: target is neither the configured endpoint host nor under a known Azure Monitor ingestion domain.`); return; } this.endpointUrl = "https://" + locUrl.host; // Recreate the client so subsequent requests use the new endpoint this.quickpulseClient = this.createQuickpulseClient({ endpoint: this.endpointUrl, credentials: { scopes: this.credentialScopes }, }); } } } //# sourceMappingURL=sender.js.map