forked from microsoft/ApplicationInsights-node.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatically handle request/dependency correlation in Azure Functions (
microsoft#1044) * Automatically handle request/dependency correlation in Azure Functions * Update * Adding tests
- Loading branch information
1 parent
39213a3
commit 9909cbd
Showing
15 changed files
with
312 additions
and
145 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { Context, HttpRequest } from "../Library/Functions"; | ||
import Logging = require("../Library/Logging"); | ||
import TelemetryClient = require("../Library/TelemetryClient"); | ||
import { CorrelationContextManager } from "./CorrelationContextManager"; | ||
|
||
|
||
/** Node.js Azure Functions handle incoming HTTP requests before Application Insights SDK is available, | ||
* this code generate incoming request telemetry and generate correlation context to be used | ||
* by outgoing requests and other telemetry, we rely on hooks provided by Azure Functions | ||
*/ | ||
export class AutoCollectAzureFunctions { | ||
private _client: TelemetryClient; | ||
private _functionsCoreModule: any; | ||
private _preInvocationHook: any; | ||
|
||
constructor(client: TelemetryClient) { | ||
this._client = client; | ||
try { | ||
this._functionsCoreModule = require('@azure/functions-core'); | ||
} | ||
catch (error) { | ||
Logging.info("AutoCollectAzureFunctions failed to load, not running in Azure Functions"); | ||
} | ||
} | ||
|
||
public enable(isEnabled: boolean) { | ||
if (this._functionsCoreModule) { | ||
if (isEnabled) { | ||
this._addPreInvocationHook(); | ||
} else { | ||
this._removePreInvocationHook(); | ||
} | ||
} | ||
} | ||
|
||
public dispose() { | ||
this.enable(false); | ||
this._functionsCoreModule = undefined; | ||
} | ||
|
||
private _addPreInvocationHook() { | ||
// Only add hook once | ||
if (!this._preInvocationHook) { | ||
this._preInvocationHook = this._functionsCoreModule.registerHook('preInvocation', (context: any) => { | ||
const originalCallback = context.functionCallback; | ||
context.functionCallback = async (context: Context, req: HttpRequest) => { | ||
const startTime = Date.now(); // Start trackRequest timer | ||
// Start an AI Correlation Context using the provided Function context | ||
const correlationContext = CorrelationContextManager.startOperation(context, req); | ||
if (correlationContext) { | ||
CorrelationContextManager.wrapCallback(async () => { | ||
originalCallback(context, req); | ||
this._client.trackRequest({ | ||
name: context?.req?.method + " " + context.req?.url, | ||
resultCode: context?.res?.status, | ||
success: true, | ||
url: (req as HttpRequest)?.url, | ||
time: new Date(startTime), | ||
duration: Date.now() - startTime, | ||
id: correlationContext.operation?.parentId, | ||
}); | ||
this._client.flush(); | ||
}, correlationContext)(); | ||
} | ||
}; | ||
}); | ||
} | ||
} | ||
|
||
private _removePreInvocationHook() { | ||
if (this._preInvocationHook) { | ||
this._preInvocationHook.dispose(); | ||
this._preInvocationHook = undefined; | ||
} | ||
} | ||
} |
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
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,51 @@ | ||
import assert = require("assert"); | ||
import sinon = require("sinon"); | ||
import { TelemetryClient } from "../../applicationinsights"; | ||
|
||
import { AutoCollectAzureFunctions } from "../../AutoCollection/AzureFunctionsHook"; | ||
|
||
const testModule = { | ||
registerHook(type: string, hook: any) { | ||
|
||
} | ||
}; | ||
|
||
describe("AutoCollection/AutoCollectAzureFunctions", () => { | ||
|
||
it("constructor", () => { | ||
let client = new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); | ||
let auto = new AutoCollectAzureFunctions(client); | ||
assert.equal(auto["_functionsCoreModule"], undefined, "Module is not available so it should be undefined unless running in AzFn env"); | ||
}); | ||
|
||
it("enable", () => { | ||
let client = new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); | ||
let auto = new AutoCollectAzureFunctions(client); | ||
auto["_functionsCoreModule"] = testModule; | ||
const addStub = sinon.stub(auto, "_addPreInvocationHook"); | ||
const removeStub = sinon.stub(auto, "_removePreInvocationHook"); | ||
auto.enable(true); | ||
assert.ok(removeStub.notCalled); | ||
assert.ok(addStub.calledOnce); | ||
}); | ||
|
||
it("disable", () => { | ||
let client = new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); | ||
let auto = new AutoCollectAzureFunctions(client); | ||
auto["_functionsCoreModule"] = testModule; | ||
const addStub = sinon.stub(auto, "_addPreInvocationHook"); | ||
const removeStub = sinon.stub(auto, "_removePreInvocationHook"); | ||
auto.enable(false); | ||
assert.ok(removeStub.calledOnce); | ||
assert.ok(addStub.notCalled); | ||
}); | ||
|
||
it("_addPreInvocationHook", () => { | ||
let client = new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); | ||
let auto = new AutoCollectAzureFunctions(client); | ||
const registerHook = sinon.stub(testModule, "registerHook"); | ||
auto["_functionsCoreModule"] = testModule; | ||
auto["_addPreInvocationHook"](); | ||
assert.ok(registerHook.calledOnce); | ||
}); | ||
}); |
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
Oops, something went wrong.