typescriptazure-functionsazure-functions-runtime

Enable Application Insights With Open Telemetry in Azure Functions


I am trying to create an Azure Function with typescript. I am fairly new to both. I followed the docs and create one Azure function using the steps mentioned in the Azure Docs.

Docs: AppInsight-Typescript HOST.json Azure function With Typecript

When I created the function using Httptrigger template it worked just fine. I was able to access httptrigger and got the Hello World! in response. I am using programming model v4, host.json v2, Runtime worker: node, worker runtime version is ~4 and node version 20.

My current directory structure is as follows:

az-createquote-functionapp/
├── .vscode/
├── dist/
├── node_modules/
├── src/
│   ├── functions/
│   │   └── createQuoteHttp.ts
│   ├── index.ts
│   └── telemetry.ts
├── .gitignore
├── .funcignore
├── eslint.config.js
├── host.json
├── local-settings.json
├── package-lock.json
├── package.json
└── tsconfig.json
My tsconfig.json:
{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ESNext",
    "moduleResolution": "Node",
    "outDir": "dist",
    "rootDir": ".",
    "sourceMap": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "forceConsistentCasingInFileNames": true,
  },
  "include": [
    "./**/*.ts",
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}
My package.json
{
  "name": "az-createquote-functionapp",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "clean": "rimraf dist",
    "prestart": "npm run clean && npm run build",
    "start": "func start  --verbose",
    "lint": "eslint '**/*.{js,mjs,cjs,ts}'",
    "lint:fix": "eslint '**/*.{js,mjs,cjs,ts}' --fix",
    "test": "echo \"No tests yet...\""
  },
  "dependencies": {
    "@azure/functions": "^4.5.0",
    "@azure/functions-opentelemetry-instrumentation": "^0.1.0",
    "@azure/monitor-opentelemetry-exporter": "^1.0.0-beta.24",
    "@azure/openapi": "^3.0.104",
    "@opentelemetry/api": "^1.9.0",
    "@opentelemetry/auto-instrumentations-node": "^0.49.1",
    "@opentelemetry/exporter-trace-otlp-http": "^0.52.1",
    "@opentelemetry/sdk-node": "^0.52.1"
  },
  "devDependencies": {
    "@eslint/js": "^9.8.0",
    "@types/node": "^20.x",
    "eslint": "^9.8.0",
    "globals": "^15.9.0",
    "rimraf": "^5.0.0",
    "typescript": "^4.0.0",
    "typescript-eslint": "^8.0.0"
  },
  "overrides": {
    "eslint": "^9.8.0"
  },
  "type": "module",
  "main": "dist/src/{index.js,functions/*.js}"
}
//index.ts
import "./telemetry";
import { app } from '@azure/functions';

app.setup({
    enableHttpStream: true,
});
//telemetry.ts
import { AzureFunctionsInstrumentation } from '@azure/functions-opentelemetry-instrumentation';
import { AzureMonitorLogExporter, AzureMonitorTraceExporter } from '@azure/monitor-opentelemetry-exporter';
import { getNodeAutoInstrumentations, getResourceDetectors } from '@opentelemetry/auto-instrumentations-node';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { detectResourcesSync } from '@opentelemetry/resources';
import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';

const resource = detectResourcesSync({ detectors: getResourceDetectors() });

const tracerProvider = new NodeTracerProvider({ resource });
tracerProvider.addSpanProcessor(new SimpleSpanProcessor(new AzureMonitorTraceExporter()));
tracerProvider.register();

const loggerProvider = new LoggerProvider({ resource });
loggerProvider.addLogRecordProcessor(new SimpleLogRecordProcessor(new AzureMonitorLogExporter()));

registerInstrumentations({
    tracerProvider,
    loggerProvider,
    instrumentations: [getNodeAutoInstrumentations(), new AzureFunctionsInstrumentation()],
});
// my http trigger
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";

export async function createQuoteHttp(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    context.log(`Http function processed request for url "${request.url}"`);

    const name = request.query.get('name') || await request.text() || 'world';

    return { body: `Hello, ${name}!` };
};

app.http('createQuoteHttp', {
    route: 'V1/createQuote',
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: createQuoteHttp
});

As soon as I added telemetry, I started getting error

Error [ERR_MODULE_NOT_FOUND]: Worker was unable to load entry point "dist/src/index.js": Cannot find module '/x/y/projects/az-createquote-functionapp/dist/src/telemetry'. 

However, files are present in the correct location in the dist folder. Trigger with default template works but as soon as I try to create any directory or other files and import it either in the index.ts or in my trigger.ts. I start getting this error. I need to build lot of files and directories to seggregate logics but I am not why it is failing.

Here is the exact error:
enter image description here

I am trying to build an API using Azure function with typescript. I tried changing Node versions. I tried changing model to "CommonJS". I tried adding telemetry code in index.ts itself but not sure if I even know the right cause. I am fairly new to both Azure and Typescript so I am trying to implement this using official documentation.


Solution

  • Worker was unable to load entry point "dist/src/index.js": Cannot find module '/x/y/projects/az-createquote-functionapp/dist/src/telemetry'.

    To resolve this error, add import {} from './telemetry'; instead of import './telemetry'; in index.js:

    index.js:

    import { app } from '@azure/functions';
    import { } from './telemetry';
    
    app.setup({
        enableHttpStream: true,
    });
    

    Able to run the function as expected:

    Local response:

    C:\Users\uname\tsfn>npm start
    
    > az-createquote-functionapp@1.0.0 prestart
    > npm run clean && npm run build
    
    > az-createquote-functionapp@1.0.0 clean
    > rimraf dist
    
    > az-createquote-functionapp@1.0.0 build
    > tsc
    
    > az-createquote-functionapp@1.0.0 start
    > func start  --verbose
    
    [2024-08-08T05:05:53.843Z] Building host: version spec: , startup suppressed: 'False', configuration suppressed: 'False', startup operation id: '65f12becXXXb31011'
    [2024-08-08T05:05:53.856Z] Reading host configuration file 'C:\Users\uname\tsfn\host.json'
    [2024-08-08T05:05:53.859Z] Host configuration file read:
    [2024-08-08T05:05:53.861Z] {
    //Removed few logs
    [2024-08-08T05:05:53.887Z] }
    //Removed few logs
    [2024-08-08T05:05:54.908Z] Loading entry point file "dist/src/index.js"
    [2024-08-08T05:05:56.263Z] Loaded entry point file "dist/src/index.js"[2024-08-08T05:05:56.263Z] HTTP streaming enabled.
    [2024-08-08T05:05:56.265Z] Loading entry point file "dist/src/functions/createQuoteHttp.js"
    [2024-08-08T05:05:56.288Z] Setting Node.js programming model to "@azure/functions" version "4.5.0"
    [2024-08-08T05:05:56.288Z] Loaded entry point file "dist/src/functions/createQuoteHttp.js"
    [2024-08-08T05:05:56.478Z] Worker 19de9c81-598d-4d11-a687-fa8d4d139ddc received FunctionsMetadataRequest
    [2024-08-08T05:05:56.541Z] 1 functions found (Worker)
    [2024-08-08T05:05:56.553Z] 1 functions loaded
    [2024-08-08T05:05:56.558Z] Looking for extension bundle Microsoft.Azure.Functions.ExtensionBundle at C:\Users\uname\.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle
    [2024-08-08T05:05:56.562Z] Found a matching extension bundle at C:\Users\uname\.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle\4.17.0
    [2024-08-08T05:05:56.564Z] Fetching information on versions of extension bundle Microsoft.Azure.Functions.ExtensionBundle available on https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index.json
    [2024-08-08T05:05:56.844Z] Skipping bundle download since it already exists at path C:\Users\uname\.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle\4.17.0
    [2024-08-08T05:05:56.849Z] Loading extension bundle from C:\Users\uname\.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle\4.17.0\bin
    [2024-08-08T05:05:56.851Z] Script Startup resetting load context with base path: 'C:\Users\uname\.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle\4.17.0\bin'.     
    [2024-08-08T05:05:58.327Z] Starting JobHost
    [2024-08-08T05:05:58.337Z] Starting Host (HostId=mtpf1lw01d-683002283, InstanceId=9eab1dfa-0569-4d69-b2a4-e385b03fa0d2, Version=4.834.3.22875, ProcessId=24148, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
    [2024-08-08T05:05:58.367Z] Loading functions metadata
    [2024-08-08T05:05:58.369Z] Worker indexing is enabled
    [2024-08-08T05:05:58.371Z] Fetching metadata for workerRuntime: node
    [2024-08-08T05:05:58.373Z] Reading functions metadata (Worker)
    [2024-08-08T05:05:58.400Z] Reading functions metadata (Custom)
    [2024-08-08T05:05:58.426Z] 1 functions found (Custom)
    [2024-08-08T05:05:58.446Z] 1 functions loaded
    [2024-08-08T05:05:58.613Z] Generating 1 job function(s)
    [2024-08-08T05:05:58.617Z] Worker process started and initialized.
    [2024-08-08T05:05:58.623Z] Worker 19de9c81-598d-4d11-a687-fa8d4d139ddc received FunctionLoadRequest
    [2024-08-08T05:05:58.814Z] Found the following functions:
    [2024-08-08T05:05:58.816Z] Host.Functions.createQuoteHttp
    [2024-08-08T05:05:58.817Z]
    //Removed few logs
    [2024-08-08T05:05:58.915Z] Host initialized (558ms)
    [2024-08-08T05:05:58.925Z] Host started (582ms)
    [2024-08-08T05:05:58.927Z] Job host started
    
    Functions:
    
            createQuoteHttp: [GET,POST] http://localhost:7071/api/V1/createQuote
    
    [2024-08-08T05:06:03.201Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
    [2024-08-08T05:07:17.061Z] Executing HTTP request: {
    [2024-08-08T05:07:17.063Z]   "requestId": "0853d91f-0ce1-44c2-8133-70313a8d3a4b",
    [2024-08-08T05:07:17.066Z]   "method": "GET",
    [2024-08-08T05:07:17.069Z]   "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0",
    [2024-08-08T05:07:17.071Z]   "uri": "/api/V1/createQuote"
    [2024-08-08T05:07:17.073Z] }
    [2024-08-08T05:07:17.878Z] Executing 'Functions.createQuoteHttp' (Reason='This function was programmatically called via the host APIs.', Id=e22a8e42-05c7-4a2f-a1a1-304b7a1973bb)
    [2024-08-08T05:07:18.243Z] Worker 19de9c81-598d-4d11-a687-fa8d4d139ddc received FunctionInvocationRequest with invocationId e22a8e42-05c7-4a2f-a1a1-304b7a1973bb
    [2024-08-08T05:07:18.269Z] Http function processed request for url "http://localhost:7071/api/V1/createQuote"[2024-08-08T05:07:18.387Z] Executed 'Functions.createQuoteHttp' (Succeeded, Id=e22a8e42-05c7-4a2f-a1a1-304b7a1973bb, Duration=611ms)
    [2024-08-08T05:07:18.447Z] Executed HTTP request: {
    [2024-08-08T05:07:18.449Z]   "requestId": "0853d91f-0ce1-44c2-8133-70313a8d3a4b",
    [2024-08-08T05:07:18.451Z]   "identities": "",
    [2024-08-08T05:07:18.453Z]   "status": "200",
    [2024-08-08T05:07:18.455Z]   "duration": "1383"
    [2024-08-08T05:07:18.458Z] }
    

    enter image description here

    Portal:

    enter image description here