-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updating how cross-application correlations are tracked (#231)
* Updating how cross-application correlations are tracked Instead of using a hash of the instrumentation key we now use the appId, matching the .NET sdk. We also use different headers to match the .NET sdk. * Updating to only issue appId requests once per ikey * Exposing profileQueryEndpoint property Allows for the appId query target to be configured separately to the telemetry endpoint. It may be specified either by the APPINSIGHTS_PROFILE_QUERY_ENDPOINT environment variable, or explicitly via client.config.profileQueryEndpoint. Note that it must be set synchronously with the creation of the Config otherwise the value will not be used. * Allowing appId lookups to be cancelled if a new endpoint is specified * Adding operationId to outbound HTTP headers
- Loading branch information
1 parent
8c31b39
commit 6f8d4a2
Showing
10 changed files
with
225 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import https = require('https'); | ||
import http = require('http'); | ||
import url = require('url'); | ||
|
||
class CorrelationIdManager { | ||
public static correlationIdPrefix: "cid-v1:"; | ||
|
||
// To avoid extraneous HTTP requests, we maintain a queue of callbacks waiting on a particular appId lookup, | ||
// as well as a cache of completed lookups so future requests can be resolved immediately. | ||
private static pendingLookups: {[key: string]: Function[]} = {}; | ||
private static completedLookups: {[key: string]: string} = {}; | ||
|
||
public static queryCorrelationId(endpointBase: string, instrumentationKey: string, correlationIdRetryInterval: number, callback: (correlationId: string) => void) { | ||
// GET request to `${this.endpointBase}/api/profiles/${this.instrumentationKey}/appId` | ||
// If it 404s, the iKey is bad and we should give up | ||
// If it fails otherwise, try again later | ||
const appIdUrlString = `${endpointBase}/api/profiles/${instrumentationKey}/appId`; | ||
const appIdUrl = url.parse(appIdUrlString); | ||
|
||
if (CorrelationIdManager.completedLookups.hasOwnProperty(appIdUrlString)) { | ||
callback(CorrelationIdManager.completedLookups[appIdUrlString]); | ||
return; | ||
} else if (CorrelationIdManager.pendingLookups[appIdUrlString]) { | ||
CorrelationIdManager.pendingLookups[appIdUrlString].push(callback); | ||
return; | ||
} | ||
|
||
CorrelationIdManager.pendingLookups[appIdUrlString] = [callback]; | ||
|
||
const requestOptions = { | ||
protocol: appIdUrl.protocol, | ||
hostname: appIdUrl.host, | ||
path: appIdUrl.pathname, | ||
method: 'GET', | ||
// Ensure this request is not captured by auto-collection. | ||
// Note: we don't refer to the property in ClientRequestParser because that would cause a cyclical dependency | ||
disableAppInsightsAutoCollection: true | ||
}; | ||
|
||
let httpRequest = appIdUrl.protocol === 'https:' ? https.request : http.request; | ||
|
||
const fetchAppId = () => { | ||
if (!CorrelationIdManager.pendingLookups[appIdUrlString]) { | ||
// This query has been cancelled. | ||
return; | ||
} | ||
const req = httpRequest(requestOptions, (res) => { | ||
if (res.statusCode === 200) { | ||
// Success; extract the appId from the body | ||
let appId = ""; | ||
res.setEncoding("utf-8"); | ||
res.on('data', function (data) { | ||
appId += data; | ||
}); | ||
res.on('end', () => { | ||
const result = CorrelationIdManager.correlationIdPrefix + appId; | ||
CorrelationIdManager.completedLookups[appIdUrlString] = result; | ||
if (CorrelationIdManager.pendingLookups[appIdUrlString]) { | ||
CorrelationIdManager.pendingLookups[appIdUrlString].forEach((cb) => cb(result)); | ||
} | ||
delete CorrelationIdManager.pendingLookups[appIdUrlString]; | ||
}); | ||
} else if (res.statusCode >= 400 && res.statusCode < 500) { | ||
// Not found, probably a bad key. Do not try again. | ||
CorrelationIdManager.completedLookups[appIdUrlString] = undefined; | ||
delete CorrelationIdManager.pendingLookups[appIdUrlString]; | ||
} else { | ||
// Retry after timeout. | ||
setTimeout(fetchAppId, correlationIdRetryInterval); | ||
} | ||
}); | ||
if (req) { | ||
req.on('error', () => { | ||
// Unable to contact endpoint. | ||
// Do nothing for now. | ||
}); | ||
req.end(); | ||
} | ||
}; | ||
setTimeout(fetchAppId, 0); | ||
} | ||
|
||
public static cancelCorrelationIdQuery(endpointBase: string, instrumentationKey: string, callback: (correlationId: string) => void) { | ||
const appIdUrlString = `${endpointBase}/api/profiles/${instrumentationKey}/appId`; | ||
const pendingLookups = CorrelationIdManager.pendingLookups[appIdUrlString]; | ||
if (pendingLookups) { | ||
CorrelationIdManager.pendingLookups[appIdUrlString] = pendingLookups.filter((cb) => cb != callback); | ||
if (CorrelationIdManager.pendingLookups[appIdUrlString].length == 0) { | ||
delete CorrelationIdManager.pendingLookups[appIdUrlString]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
export = CorrelationIdManager; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.