@herrromich/az-functions 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +830 -0
- package/coverage/cobertura-coverage.xml +3482 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/context/forked-invocation-context.ts.html +127 -0
- package/coverage/lcov-report/context/index.html +191 -0
- package/coverage/lcov-report/context/index.ts.html +97 -0
- package/coverage/lcov-report/context/platform-context.manager.ts.html +193 -0
- package/coverage/lcov-report/context/platform-context.model.ts.html +262 -0
- package/coverage/lcov-report/context/platform-context.provider.ts.html +196 -0
- package/coverage/lcov-report/context/platform.execution.context.ts.html +217 -0
- package/coverage/lcov-report/context/wrapped-invocation-context.ts.html +163 -0
- package/coverage/lcov-report/event-hub-handler/azure-event-hub-trigger.model.ts.html +187 -0
- package/coverage/lcov-report/event-hub-handler/azure-event-hub-trigger.service.ts.html +760 -0
- package/coverage/lcov-report/event-hub-handler/decorators/decorators.model.ts.html +292 -0
- package/coverage/lcov-report/event-hub-handler/decorators/decorators.ts.html +778 -0
- package/coverage/lcov-report/event-hub-handler/decorators/index.html +146 -0
- package/coverage/lcov-report/event-hub-handler/decorators/index.ts.html +91 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handle-method-args-metadata.service.ts.html +130 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handler-metadata.reader.ts.html +199 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handler-registration.service.ts.html +220 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handler.factory.ts.html +283 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handler.model.ts.html +421 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-handler.provider.ts.html +187 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-trigger-support.factory.ts.html +787 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-trigger-support.service.ts.html +829 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-trigger.model.ts.html +193 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-trigger.service.ts.html +859 -0
- package/coverage/lcov-report/event-hub-handler/event-hub-triggers-registration.service.ts.html +307 -0
- package/coverage/lcov-report/event-hub-handler/index.html +221 -0
- package/coverage/lcov-report/event-hub-handler/index.ts.html +142 -0
- package/coverage/lcov-report/eventhub-handler/decorators/decorators.model.ts.html +277 -0
- package/coverage/lcov-report/eventhub-handler/decorators/decorators.ts.html +679 -0
- package/coverage/lcov-report/eventhub-handler/decorators/index.html +131 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-handler-metadata.reader.ts.html +196 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-handler-registration.service.ts.html +220 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-handler.factory.ts.html +193 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-handler.model.ts.html +406 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-trigger.model.ts.html +187 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-trigger.service.ts.html +760 -0
- package/coverage/lcov-report/eventhub-handler/eventhub-triggers-registration.service.ts.html +304 -0
- package/coverage/lcov-report/eventhub-handler/index.html +206 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/forked-invocation-context.ts.html +127 -0
- package/coverage/lcov-report/function-handler-metadata.reader.ts.html +172 -0
- package/coverage/lcov-report/http-controller/authentication.provider.ts.html +481 -0
- package/coverage/lcov-report/http-controller/authenticator.provider.ts.html +460 -0
- package/coverage/lcov-report/http-controller/azure-http-trigger.service.ts.html +1045 -0
- package/coverage/lcov-report/http-controller/decorators/decorators.model.ts.html +388 -0
- package/coverage/lcov-report/http-controller/decorators/decorators.ts.html +1627 -0
- package/coverage/lcov-report/http-controller/decorators/index.html +146 -0
- package/coverage/lcov-report/http-controller/decorators/index.ts.html +94 -0
- package/coverage/lcov-report/http-controller/http-controller-metadata.reader.ts.html +271 -0
- package/coverage/lcov-report/http-controller/http-controller-metadata.service.ts.html +130 -0
- package/coverage/lcov-report/http-controller/http-controller-platform.model.ts.html +187 -0
- package/coverage/lcov-report/http-controller/http-controller-registration.service.ts.html +241 -0
- package/coverage/lcov-report/http-controller/http-controller.model.ts.html +745 -0
- package/coverage/lcov-report/http-controller/http-handler-support.factory.ts.html +499 -0
- package/coverage/lcov-report/http-controller/http-handler.factory.ts.html +415 -0
- package/coverage/lcov-report/http-controller/http-operation-registration.service.ts.html +328 -0
- package/coverage/lcov-report/http-controller/http-operations-registration.service.ts.html +328 -0
- package/coverage/lcov-report/http-controller/http-request-arg-provider.factory.ts.html +580 -0
- package/coverage/lcov-report/http-controller/http-request-handler.provider.ts.html +388 -0
- package/coverage/lcov-report/http-controller/http-response-processor.factory.ts.html +316 -0
- package/coverage/lcov-report/http-controller/index.html +311 -0
- package/coverage/lcov-report/http-controller/index.ts.html +226 -0
- package/coverage/lcov-report/http-controller/open-api-definition.service.ts.html +568 -0
- package/coverage/lcov-report/http-controller/open-api-metadata.service.ts.html +373 -0
- package/coverage/lcov-report/http-controller/open-api-print.service.ts.html +232 -0
- package/coverage/lcov-report/http-controller/open-api-registration.service.ts.html +220 -0
- package/coverage/lcov-report/http-controller/rest-open-api.regstry.ts.html +262 -0
- package/coverage/lcov-report/http-controller/security/authentication-service.factory.ts.html +280 -0
- package/coverage/lcov-report/http-controller/security/authentication-service.ts.html +115 -0
- package/coverage/lcov-report/http-controller/security/authenticator.provider.ts.html +799 -0
- package/coverage/lcov-report/http-controller/security/bearer-security-authentication.service.ts.html +133 -0
- package/coverage/lcov-report/http-controller/security/index.html +206 -0
- package/coverage/lcov-report/http-controller/security/index.ts.html +94 -0
- package/coverage/lcov-report/http-controller/security/model.ts.html +133 -0
- package/coverage/lcov-report/http-controller/security/operation-authentication.resolver.ts.html +418 -0
- package/coverage/lcov-report/http-controller/security/principal-merge.service.ts.html +163 -0
- package/coverage/lcov-report/http-controller/security/strict-principal-merge.servce.ts.html +154 -0
- package/coverage/lcov-report/http-controller/swagger-handling.service.ts.html +463 -0
- package/coverage/lcov-report/index.html +281 -0
- package/coverage/lcov-report/init.ts.html +97 -0
- package/coverage/lcov-report/ioc-container.utils.ts.html +100 -0
- package/coverage/lcov-report/logger/azure-log-transport.service.ts.html +433 -0
- package/coverage/lcov-report/logger/bindings.ts.html +253 -0
- package/coverage/lcov-report/logger/index.html +221 -0
- package/coverage/lcov-report/logger/index.ts.html +163 -0
- package/coverage/lcov-report/logger/log-level.service.ts.html +127 -0
- package/coverage/lcov-report/logger/log-transport.service.ts.html +571 -0
- package/coverage/lcov-report/logger/logger-factory.provider.ts.html +142 -0
- package/coverage/lcov-report/logger/logger.factory.ts.html +172 -0
- package/coverage/lcov-report/logger/logger.model.ts.html +868 -0
- package/coverage/lcov-report/logger/logger.utils.ts.html +877 -0
- package/coverage/lcov-report/logger/model.ts.html +172 -0
- package/coverage/lcov-report/logger/otel.logger.ts.html +358 -0
- package/coverage/lcov-report/logger/platform.logger.ts.html +229 -0
- package/coverage/lcov-report/logger/trie-search.service.ts.html +616 -0
- package/coverage/lcov-report/platform/azure-platform.ts.html +256 -0
- package/coverage/lcov-report/platform/index.html +176 -0
- package/coverage/lcov-report/platform/index.ts.html +139 -0
- package/coverage/lcov-report/platform/platform-component-metadata.service.ts.html +115 -0
- package/coverage/lcov-report/platform/register-function.factory.ts.html +145 -0
- package/coverage/lcov-report/platform/register-trigger-handler.factory.ts.html +214 -0
- package/coverage/lcov-report/platform/security-context.ts.html +127 -0
- package/coverage/lcov-report/platform/startup.service.ts.html +106 -0
- package/coverage/lcov-report/platform/system-logger-name.provider.ts.html +145 -0
- package/coverage/lcov-report/platform/system.container.ts.html +169 -0
- package/coverage/lcov-report/platform-context.model.ts.html +124 -0
- package/coverage/lcov-report/platform.logger.ts.html +316 -0
- package/coverage/lcov-report/platform.model.ts.html +292 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/security/index.html +146 -0
- package/coverage/lcov-report/security/index.ts.html +91 -0
- package/coverage/lcov-report/security/security-context.ts.html +130 -0
- package/coverage/lcov-report/security/security.model.ts.html +169 -0
- package/coverage/lcov-report/shared/all-settled.util.ts.html +118 -0
- package/coverage/lcov-report/shared/decorators/decorators.model.ts.html +136 -0
- package/coverage/lcov-report/shared/decorators/decorators.ts.html +346 -0
- package/coverage/lcov-report/shared/decorators/index.html +146 -0
- package/coverage/lcov-report/shared/decorators/index.ts.html +91 -0
- package/coverage/lcov-report/shared/function-handler-metadata.reader.ts.html +172 -0
- package/coverage/lcov-report/shared/index.html +176 -0
- package/coverage/lcov-report/shared/index.ts.html +133 -0
- package/coverage/lcov-report/shared/ioc-container.utils.ts.html +115 -0
- package/coverage/lcov-report/shared/platform-context-local-storage.ts.html +133 -0
- package/coverage/lcov-report/shared/platform-context.manager.ts.html +253 -0
- package/coverage/lcov-report/shared/platform.context.provider.ts.html +136 -0
- package/coverage/lcov-report/shared/platform.model.ts.html +298 -0
- package/coverage/lcov-report/shared/security.model.ts.html +142 -0
- package/coverage/lcov-report/shared/trie-search.service.ts.html +337 -0
- package/coverage/lcov-report/shared/trigger-handler-metadata.reader.ts.html +166 -0
- package/coverage/lcov-report/shared/zod-parser-wrapper.service.ts.html +217 -0
- package/coverage/lcov-report/shared/zod-parser-wrapper.ts.html +232 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/src/context/index.html +191 -0
- package/coverage/lcov-report/src/context/index.ts.html +97 -0
- package/coverage/lcov-report/src/context/platform-context.manager.ts.html +193 -0
- package/coverage/lcov-report/src/context/platform-context.model.ts.html +262 -0
- package/coverage/lcov-report/src/context/platform-context.provider.ts.html +196 -0
- package/coverage/lcov-report/src/context/platform.execution.context.ts.html +217 -0
- package/coverage/lcov-report/src/context/wrapped-invocation-context.ts.html +163 -0
- package/coverage/lcov-report/src/event-hub-handler/azure-event-hub-trigger.model.ts.html +187 -0
- package/coverage/lcov-report/src/event-hub-handler/azure-event-hub-trigger.service.ts.html +769 -0
- package/coverage/lcov-report/src/event-hub-handler/decorators/decorators.model.ts.html +313 -0
- package/coverage/lcov-report/src/event-hub-handler/decorators/decorators.ts.html +778 -0
- package/coverage/lcov-report/src/event-hub-handler/decorators/index.html +146 -0
- package/coverage/lcov-report/src/event-hub-handler/decorators/index.ts.html +91 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handle-method-args-metadata.service.ts.html +130 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handler-metadata.reader.ts.html +199 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handler-registration.service.ts.html +220 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handler.factory.ts.html +283 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handler.model.ts.html +421 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-handler.provider.ts.html +187 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-trigger-support.factory.ts.html +787 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-trigger-support.service.ts.html +832 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-trigger.model.ts.html +193 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-trigger.service.ts.html +859 -0
- package/coverage/lcov-report/src/event-hub-handler/event-hub-triggers-registration.service.ts.html +307 -0
- package/coverage/lcov-report/src/event-hub-handler/index.html +221 -0
- package/coverage/lcov-report/src/event-hub-handler/index.ts.html +142 -0
- package/coverage/lcov-report/src/framework.container.ts.html +157 -0
- package/coverage/lcov-report/src/http-controller/authentication.provider.ts.html +481 -0
- package/coverage/lcov-report/src/http-controller/authenticator.provider.ts.html +460 -0
- package/coverage/lcov-report/src/http-controller/azure-http-trigger.service.ts.html +865 -0
- package/coverage/lcov-report/src/http-controller/decorators/decorators.model.ts.html +553 -0
- package/coverage/lcov-report/src/http-controller/decorators/decorators.ts.html +1633 -0
- package/coverage/lcov-report/src/http-controller/decorators/index.html +146 -0
- package/coverage/lcov-report/src/http-controller/decorators/index.ts.html +94 -0
- package/coverage/lcov-report/src/http-controller/http-controller-metadata.reader.ts.html +271 -0
- package/coverage/lcov-report/src/http-controller/http-controller-metadata.service.ts.html +121 -0
- package/coverage/lcov-report/src/http-controller/http-controller-platform.model.ts.html +187 -0
- package/coverage/lcov-report/src/http-controller/http-controller-registration.service.ts.html +241 -0
- package/coverage/lcov-report/src/http-controller/http-controller.model.ts.html +784 -0
- package/coverage/lcov-report/src/http-controller/http-handler-support.factory.ts.html +481 -0
- package/coverage/lcov-report/src/http-controller/http-handler.factory.ts.html +406 -0
- package/coverage/lcov-report/src/http-controller/http-operation-registration.service.ts.html +328 -0
- package/coverage/lcov-report/src/http-controller/http-operations-registration.service.ts.html +328 -0
- package/coverage/lcov-report/src/http-controller/http-request-arg-provider.factory.ts.html +580 -0
- package/coverage/lcov-report/src/http-controller/http-request-handler.provider.ts.html +388 -0
- package/coverage/lcov-report/src/http-controller/http-response-processor.factory.ts.html +316 -0
- package/coverage/lcov-report/src/http-controller/index.html +311 -0
- package/coverage/lcov-report/src/http-controller/index.ts.html +226 -0
- package/coverage/lcov-report/src/http-controller/open-api-definition.service.ts.html +550 -0
- package/coverage/lcov-report/src/http-controller/open-api-metadata.service.ts.html +373 -0
- package/coverage/lcov-report/src/http-controller/open-api-print.service.ts.html +232 -0
- package/coverage/lcov-report/src/http-controller/open-api-registration.service.ts.html +220 -0
- package/coverage/lcov-report/src/http-controller/rest-open-api.regstry.ts.html +262 -0
- package/coverage/lcov-report/src/http-controller/security/authentication-service.factory.ts.html +280 -0
- package/coverage/lcov-report/src/http-controller/security/authentication-service.ts.html +139 -0
- package/coverage/lcov-report/src/http-controller/security/authenticator.provider.ts.html +799 -0
- package/coverage/lcov-report/src/http-controller/security/bearer-security-authentication.service.ts.html +133 -0
- package/coverage/lcov-report/src/http-controller/security/index.html +206 -0
- package/coverage/lcov-report/src/http-controller/security/index.ts.html +94 -0
- package/coverage/lcov-report/src/http-controller/security/model.ts.html +133 -0
- package/coverage/lcov-report/src/http-controller/security/operation-authentication.resolver.ts.html +418 -0
- package/coverage/lcov-report/src/http-controller/security/principal-merge.service.ts.html +163 -0
- package/coverage/lcov-report/src/http-controller/security/strict-principal-merge.servce.ts.html +154 -0
- package/coverage/lcov-report/src/http-controller/swagger-handling.service.ts.html +463 -0
- package/coverage/lcov-report/src/index.html +161 -0
- package/coverage/lcov-report/src/init.ts.html +97 -0
- package/coverage/lcov-report/src/logger/azure-log-transport.service.ts.html +433 -0
- package/coverage/lcov-report/src/logger/bindings.ts.html +253 -0
- package/coverage/lcov-report/src/logger/index.html +221 -0
- package/coverage/lcov-report/src/logger/index.ts.html +163 -0
- package/coverage/lcov-report/src/logger/log-level.service.ts.html +127 -0
- package/coverage/lcov-report/src/logger/log-transport.service.ts.html +571 -0
- package/coverage/lcov-report/src/logger/logger-factory.provider.ts.html +142 -0
- package/coverage/lcov-report/src/logger/logger.factory.ts.html +172 -0
- package/coverage/lcov-report/src/logger/logger.model.ts.html +868 -0
- package/coverage/lcov-report/src/logger/logger.utils.ts.html +877 -0
- package/coverage/lcov-report/src/logger/otel.logger.ts.html +358 -0
- package/coverage/lcov-report/src/logger/platform.logger.ts.html +229 -0
- package/coverage/lcov-report/src/logger/trie-search.service.ts.html +616 -0
- package/coverage/lcov-report/src/middleware.ts.html +232 -0
- package/coverage/lcov-report/src/platform/azure-platform.ts.html +256 -0
- package/coverage/lcov-report/src/platform/index.html +176 -0
- package/coverage/lcov-report/src/platform/index.ts.html +139 -0
- package/coverage/lcov-report/src/platform/platform-component-metadata.service.ts.html +115 -0
- package/coverage/lcov-report/src/platform/register-function.factory.ts.html +145 -0
- package/coverage/lcov-report/src/platform/register-trigger-handler.factory.ts.html +214 -0
- package/coverage/lcov-report/src/platform/security-context.ts.html +127 -0
- package/coverage/lcov-report/src/platform/startup.service.ts.html +202 -0
- package/coverage/lcov-report/src/platform/system-logger-name.provider.ts.html +145 -0
- package/coverage/lcov-report/src/platform/system.container.ts.html +172 -0
- package/coverage/lcov-report/src/platform.container.ts.html +148 -0
- package/coverage/lcov-report/src/security/index.html +146 -0
- package/coverage/lcov-report/src/security/index.ts.html +91 -0
- package/coverage/lcov-report/src/security/security-context.ts.html +175 -0
- package/coverage/lcov-report/src/security/security.model.ts.html +223 -0
- package/coverage/lcov-report/src/shared/decorators/decorators.model.ts.html +136 -0
- package/coverage/lcov-report/src/shared/decorators/decorators.ts.html +346 -0
- package/coverage/lcov-report/src/shared/decorators/index.html +146 -0
- package/coverage/lcov-report/src/shared/decorators/index.ts.html +91 -0
- package/coverage/lcov-report/src/shared/index.html +176 -0
- package/coverage/lcov-report/src/shared/index.ts.html +133 -0
- package/coverage/lcov-report/src/shared/ioc-container.utils.ts.html +115 -0
- package/coverage/lcov-report/src/shared/platform-context-local-storage.ts.html +133 -0
- package/coverage/lcov-report/src/shared/platform.model.ts.html +298 -0
- package/coverage/lcov-report/src/shared/security.model.ts.html +139 -0
- package/coverage/lcov-report/src/shared/trie-search.service.ts.html +337 -0
- package/coverage/lcov-report/src/shared/trigger-handler-metadata.reader.ts.html +166 -0
- package/coverage/lcov-report/src/shared/zod-parser-wrapper.ts.html +232 -0
- package/coverage/lcov-report/test/index.html +116 -0
- package/coverage/lcov-report/test/utils.ts.html +100 -0
- package/coverage/lcov-report/test-utils/index.html +116 -0
- package/coverage/lcov-report/test-utils/utils.ts.html +100 -0
- package/coverage/lcov-report/trie-search.service.ts.html +469 -0
- package/coverage/lcov-report/trigger-handler-metadata.reader.ts.html +187 -0
- package/coverage/lcov-report/wrapped-invocation-context.ts.html +163 -0
- package/coverage/lcov-report/zod-parser-wrapper.ts.html +232 -0
- package/coverage/lcov.info +3220 -0
- package/dist/assets/swagger-ui/LICENSE +202 -0
- package/dist/assets/swagger-ui/NOTICE +2 -0
- package/dist/assets/swagger-ui/README.md +40 -0
- package/dist/assets/swagger-ui/absolute-path.js +1 -0
- package/dist/assets/swagger-ui/favicon-16x16.png +0 -0
- package/dist/assets/swagger-ui/favicon-32x32.png +0 -0
- package/dist/assets/swagger-ui/index.css +16 -0
- package/dist/assets/swagger-ui/index.html +19 -0
- package/dist/assets/swagger-ui/index.js +1 -0
- package/dist/assets/swagger-ui/log.bundle-sizes.swagger-ui.txt +114 -0
- package/dist/assets/swagger-ui/log.es-bundle-core-sizes.swagger-ui.txt +14 -0
- package/dist/assets/swagger-ui/log.es-bundle-sizes.swagger-ui.txt +114 -0
- package/dist/assets/swagger-ui/oauth2-redirect.html +6 -0
- package/dist/assets/swagger-ui/oauth2-redirect.js +1 -0
- package/dist/assets/swagger-ui/package.json +20 -0
- package/dist/assets/swagger-ui/swagger-initializer.js +1 -0
- package/dist/assets/swagger-ui/swagger-ui-bundle.js +2 -0
- package/dist/assets/swagger-ui/swagger-ui-bundle.js.LICENSE.txt +106 -0
- package/dist/assets/swagger-ui/swagger-ui-bundle.js.map +1 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle-core.js +2 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle-core.js.LICENSE.txt +35 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle-core.js.map +1 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle.js +2 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle.js.LICENSE.txt +106 -0
- package/dist/assets/swagger-ui/swagger-ui-es-bundle.js.map +1 -0
- package/dist/assets/swagger-ui/swagger-ui-standalone-preset.js +2 -0
- package/dist/assets/swagger-ui/swagger-ui-standalone-preset.js.LICENSE.txt +22 -0
- package/dist/assets/swagger-ui/swagger-ui-standalone-preset.js.map +1 -0
- package/dist/assets/swagger-ui/swagger-ui.css +3 -0
- package/dist/assets/swagger-ui/swagger-ui.css.map +1 -0
- package/dist/assets/swagger-ui/swagger-ui.js +1 -0
- package/dist/assets/swagger-ui/swagger-ui.js.map +1 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.LICENSE.txt +24 -0
- package/dist/src/context/index.d.ts +4 -0
- package/dist/src/context/platform-context.manager.d.ts +23 -0
- package/dist/src/context/platform-context.model.d.ts +56 -0
- package/dist/src/context/platform-context.provider.d.ts +23 -0
- package/dist/src/context/platform.execution.context.d.ts +13 -0
- package/dist/src/context/wrapped-invocation-context.d.ts +5 -0
- package/dist/src/event-hub-handler/decorators/decorators.d.ts +161 -0
- package/dist/src/event-hub-handler/decorators/decorators.model.d.ts +62 -0
- package/dist/src/event-hub-handler/decorators/index.d.ts +2 -0
- package/dist/src/event-hub-handler/event-hub-handler-metadata.reader.d.ts +8 -0
- package/dist/src/event-hub-handler/event-hub-handler-registration.service.d.ts +12 -0
- package/dist/src/event-hub-handler/event-hub-handler.factory.d.ts +13 -0
- package/dist/src/event-hub-handler/event-hub-handler.model.d.ts +101 -0
- package/dist/src/event-hub-handler/event-hub-trigger-support.factory.d.ts +10 -0
- package/dist/src/event-hub-handler/event-hub-trigger.model.d.ts +39 -0
- package/dist/src/event-hub-handler/event-hub-triggers-registration.service.d.ts +18 -0
- package/dist/src/event-hub-handler/index.d.ts +4 -0
- package/dist/src/framework.container.d.ts +6 -0
- package/dist/src/http-controller/decorators/decorators.d.ts +410 -0
- package/dist/src/http-controller/decorators/decorators.model.d.ts +123 -0
- package/dist/src/http-controller/decorators/index.d.ts +3 -0
- package/dist/src/http-controller/http-controller-metadata.reader.d.ts +8 -0
- package/dist/src/http-controller/http-controller-registration.service.d.ts +12 -0
- package/dist/src/http-controller/http-controller.model.d.ts +131 -0
- package/dist/src/http-controller/http-handler-support.factory.d.ts +26 -0
- package/dist/src/http-controller/http-handler.factory.d.ts +16 -0
- package/dist/src/http-controller/http-operations-registration.service.d.ts +22 -0
- package/dist/src/http-controller/http-request-arg-provider.factory.d.ts +12 -0
- package/dist/src/http-controller/http-response-processor.factory.d.ts +10 -0
- package/dist/src/http-controller/index.d.ts +11 -0
- package/dist/src/http-controller/open-api-definition.service.d.ts +29 -0
- package/dist/src/http-controller/open-api-metadata.service.d.ts +11 -0
- package/dist/src/http-controller/open-api-print.service.d.ts +8 -0
- package/dist/src/http-controller/open-api-registration.service.d.ts +17 -0
- package/dist/src/http-controller/security/authentication-service.d.ts +15 -0
- package/dist/src/http-controller/security/authenticator.provider.d.ts +31 -0
- package/dist/src/http-controller/security/bearer-security-authentication.service.d.ts +9 -0
- package/dist/src/http-controller/security/bearer-token.service.d.ts +5 -0
- package/dist/src/http-controller/security/index.d.ts +3 -0
- package/dist/src/http-controller/security/operation-authentication.resolver.d.ts +18 -0
- package/dist/src/http-controller/security/principal-merge.service.d.ts +11 -0
- package/dist/src/http-controller/security/strict-principal-merge.servce.d.ts +5 -0
- package/dist/src/http-controller/swagger-handling.service.d.ts +11 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/init.d.ts +1 -0
- package/dist/src/logger/bindings.d.ts +7 -0
- package/dist/src/logger/index.d.ts +6 -0
- package/dist/src/logger/log-level.service.d.ts +7 -0
- package/dist/src/logger/log-transport.service.d.ts +19 -0
- package/dist/src/logger/logger.model.d.ts +241 -0
- package/dist/src/logger/logger.utils.d.ts +17 -0
- package/dist/src/logger/otel.logger.d.ts +9 -0
- package/dist/src/logger/trie-search.service.d.ts +65 -0
- package/dist/src/middleware.d.ts +10 -0
- package/dist/src/platform/azure-platform.d.ts +15 -0
- package/dist/src/platform/index.d.ts +5 -0
- package/dist/src/platform/model.d.ts +18 -0
- package/dist/src/platform/register-trigger-handler.factory.d.ts +5 -0
- package/dist/src/platform/startup.service.d.ts +36 -0
- package/dist/src/platform/system-logger-name.provider.d.ts +1 -0
- package/dist/src/platform.container.d.ts +3 -0
- package/dist/src/security/index.d.ts +2 -0
- package/dist/src/security/security-context.d.ts +22 -0
- package/dist/src/security/security.model.d.ts +37 -0
- package/dist/src/shared/decorators/decorators.d.ts +37 -0
- package/dist/src/shared/decorators/decorators.model.d.ts +13 -0
- package/dist/src/shared/decorators/index.d.ts +2 -0
- package/dist/src/shared/index.d.ts +8 -0
- package/dist/src/shared/ioc-container.utils.d.ts +7 -0
- package/dist/src/shared/platform.model.d.ts +44 -0
- package/dist/src/shared/trigger-handler-metadata.reader.d.ts +6 -0
- package/dist/src/shared/zod-parser-wrapper.d.ts +5 -0
- package/docs/logging.md +805 -0
- package/package.json +87 -0
- package/src/context/index.ts +4 -0
- package/src/context/platform-context.manager.ts +36 -0
- package/src/context/platform-context.model.ts +59 -0
- package/src/context/platform-context.provider.ts +37 -0
- package/src/context/platform.execution.context.ts +44 -0
- package/src/context/wrapped-invocation-context.ts +26 -0
- package/src/event-hub-handler/decorators/decorators.model.ts +76 -0
- package/src/event-hub-handler/decorators/decorators.ts +231 -0
- package/src/event-hub-handler/decorators/index.ts +2 -0
- package/src/event-hub-handler/event-hub-handler-metadata.reader.ts +38 -0
- package/src/event-hub-handler/event-hub-handler-registration.service.ts +45 -0
- package/src/event-hub-handler/event-hub-handler.factory.ts +66 -0
- package/src/event-hub-handler/event-hub-handler.model.ts +112 -0
- package/src/event-hub-handler/event-hub-trigger-support.factory.ts +234 -0
- package/src/event-hub-handler/event-hub-trigger.model.ts +36 -0
- package/src/event-hub-handler/event-hub-triggers-registration.service.ts +74 -0
- package/src/event-hub-handler/index.ts +19 -0
- package/src/framework.container.ts +24 -0
- package/src/http-controller/decorators/decorators.model.ts +156 -0
- package/src/http-controller/decorators/decorators.ts +516 -0
- package/src/http-controller/decorators/index.ts +3 -0
- package/src/http-controller/http-controller-metadata.reader.ts +62 -0
- package/src/http-controller/http-controller-registration.service.ts +52 -0
- package/src/http-controller/http-controller.model.ts +233 -0
- package/src/http-controller/http-handler-support.factory.ts +132 -0
- package/src/http-controller/http-handler.factory.ts +107 -0
- package/src/http-controller/http-operations-registration.service.ts +81 -0
- package/src/http-controller/http-request-arg-provider.factory.ts +165 -0
- package/src/http-controller/http-response-processor.factory.ts +77 -0
- package/src/http-controller/index.ts +47 -0
- package/src/http-controller/open-api-definition.service.ts +155 -0
- package/src/http-controller/open-api-metadata.service.ts +96 -0
- package/src/http-controller/open-api-print.service.ts +49 -0
- package/src/http-controller/open-api-registration.service.ts +45 -0
- package/src/http-controller/security/authentication-service.ts +18 -0
- package/src/http-controller/security/authenticator.provider.ts +238 -0
- package/src/http-controller/security/bearer-security-authentication.service.ts +16 -0
- package/src/http-controller/security/bearer-token.service.ts +6 -0
- package/src/http-controller/security/index.ts +3 -0
- package/src/http-controller/security/operation-authentication.resolver.ts +111 -0
- package/src/http-controller/security/principal-merge.service.ts +26 -0
- package/src/http-controller/security/strict-principal-merge.servce.ts +23 -0
- package/src/http-controller/swagger-handling.service.ts +126 -0
- package/src/index.ts +80 -0
- package/src/init.ts +4 -0
- package/src/logger/bindings.ts +56 -0
- package/src/logger/index.ts +26 -0
- package/src/logger/log-level.service.ts +14 -0
- package/src/logger/log-transport.service.ts +162 -0
- package/src/logger/logger.model.ts +261 -0
- package/src/logger/logger.utils.ts +264 -0
- package/src/logger/otel.logger.ts +91 -0
- package/src/logger/trie-search.service.ts +177 -0
- package/src/middleware.ts +49 -0
- package/src/platform/azure-platform.ts +57 -0
- package/src/platform/index.ts +18 -0
- package/src/platform/model.ts +19 -0
- package/src/platform/register-trigger-handler.factory.ts +43 -0
- package/src/platform/startup.service.ts +39 -0
- package/src/platform/system-logger-name.provider.ts +20 -0
- package/src/platform.container.ts +21 -0
- package/src/security/index.ts +2 -0
- package/src/security/security-context.ts +30 -0
- package/src/security/security.model.ts +46 -0
- package/src/shared/decorators/decorators.model.ts +17 -0
- package/src/shared/decorators/decorators.ts +87 -0
- package/src/shared/decorators/index.ts +2 -0
- package/src/shared/index.ts +16 -0
- package/src/shared/ioc-container.utils.ts +10 -0
- package/src/shared/platform.model.ts +71 -0
- package/src/shared/trigger-handler-metadata.reader.ts +27 -0
- package/src/shared/zod-parser-wrapper.ts +49 -0
- package/src/test-utilities/index.ts +1 -0
- package/src/test-utilities/utils.ts +5 -0
- package/tsconfig.test.json +8 -0
package/docs/logging.md
ADDED
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
# Logging
|
|
2
|
+
|
|
3
|
+
## Principals
|
|
4
|
+
To have successful logging in an Azure Functions application, the following principals must be in place:
|
|
5
|
+
|
|
6
|
+
### Flexibility of logging levels
|
|
7
|
+
The logging system should allow different thresholds for different loggers, enabling developers to control the verbosity of logs based on their needs.
|
|
8
|
+
|
|
9
|
+
#### Granular control
|
|
10
|
+
Developers should have the ability to get / inject a logger with a specific logger name, that represents the scope of the functionality or component that uses this dedicated logger.
|
|
11
|
+
|
|
12
|
+
#### Dynamic log level configuration
|
|
13
|
+
The logging system should support dynamic configuration of log levels, allowing developers to change the logging level at runtime without restarting the application.
|
|
14
|
+
This is particularly useful for troubleshooting and debugging in production environments.
|
|
15
|
+
|
|
16
|
+
#### Predictable fallback
|
|
17
|
+
If a logger name has no explicitly configured log level, the logging system uses the global default log level as a fallback.
|
|
18
|
+
|
|
19
|
+
#### Hierarchical naming support
|
|
20
|
+
Names like `#backend.interfaces.rest.console.trucks.TrucksController`can inherit from `#backend.interfaces.rest.console` or `#backend.interfaces.rest` or `#backend.interfaces` or `#backend.interfaces.rest` unless overridden by a more specific configuration.
|
|
21
|
+
|
|
22
|
+
### Structured logging
|
|
23
|
+
The logging system should support structured logging.
|
|
24
|
+
Using modern telemetry systems, structured logging allows logs to be more easily searchable and analyzable.
|
|
25
|
+
|
|
26
|
+
#### String interpolation
|
|
27
|
+
String interpolation functionality can be mimicked by using string templates.
|
|
28
|
+
However, it should be supported for backward compatibility with Azure Functions invocation invocationContext logger.
|
|
29
|
+
|
|
30
|
+
#### Using JSON rawMetadata
|
|
31
|
+
The logging system should allow developers to include structured rawMetadata in their log entries in JSON format, enabling better integration with log analysis tools and improving the ability to filter and search logs based on specific attributes.
|
|
32
|
+
|
|
33
|
+
#### Better error logging
|
|
34
|
+
The logging system should provide enhanced support for logging exceptions and errors, allowing developers to capture and store detailed information about the error, such as stack traces, error codes, and contextual information, in a structured format.
|
|
35
|
+
|
|
36
|
+
### Integration / overloading of existing logging frameworks
|
|
37
|
+
|
|
38
|
+
#### Smooth transition
|
|
39
|
+
The logging system should allow developers to easily transition from existing logging framework (InvocationContext.Logger) to the new logging system without requiring significant code changes, ensuring a smooth migration process.
|
|
40
|
+
|
|
41
|
+
#### Integration with Application Insights
|
|
42
|
+
The logging system should seamlessly integrate with Azure Application Insights, making switch to the new logging system transparent and not disruptive to existing monitoring and telemetry setups.
|
|
43
|
+
|
|
44
|
+
## Guidelines
|
|
45
|
+
|
|
46
|
+
We should rely on the flexibility of logging levels and log as much data as possible.
|
|
47
|
+
This means that we can log simultaneously with different log levels in the same code:
|
|
48
|
+
```typescript
|
|
49
|
+
logger.info('fetching items');
|
|
50
|
+
logger.verbose(`fetching items for customer customerId=${customerId}`, { customerId });
|
|
51
|
+
|
|
52
|
+
const responseData: Item[] = await getItems(customerId);
|
|
53
|
+
|
|
54
|
+
logger.info('fetched items successfully');
|
|
55
|
+
logger.verbose(`fetched items for customer customerId=${customerId} itemCount=${responseData.length}`, { customerId, itemsCount: responseData.length });
|
|
56
|
+
logger.debug(`fetched items for customer customerId=${customerId}`, { customerId, responseData });
|
|
57
|
+
```
|
|
58
|
+
### Logger name
|
|
59
|
+
Logger name in combination with log level configuration allows to control the verbosity of logs based on the needs, without changing the code.
|
|
60
|
+
For example, we can have a logger with name `#backend.interfaces.rest.console.trucks.TrucksController` with log level `debug`, and another logger with name `#backend.interfaces.rest.console.cars.CarsController` with log level `error`, and they will log with different verbosity without affecting each other.
|
|
61
|
+
|
|
62
|
+
### Logging levels
|
|
63
|
+
There are many different, standardized logging levels in Node.js ecosystem.
|
|
64
|
+
Following levels mostly cover the needs of Azure Functions applications, and are supported by winston logging framework:
|
|
65
|
+
|
|
66
|
+
- **silly** - the most verbose log level, used for detailed debugging information that may be useful during development or troubleshooting.
|
|
67
|
+
This logging level can be activated temporarily only for narrowly scoped functionality during the analysis of specific issues.
|
|
68
|
+
- **debug** - used for general debugging information, less detailed than `silly`.
|
|
69
|
+
This logging level can be used for general debugging purposes, and can be enabled in development and staging environments.
|
|
70
|
+
- **verbose** - used for verbose logging, providing more invocationContext than `info`.
|
|
71
|
+
- Can be permanently enabled for specific loggers in production environments to provide more insights into the application behavior without overwhelming the logs with too much data.
|
|
72
|
+
- **http** - used for HTTP request/result logging.
|
|
73
|
+
Useful for tracking incoming requests and outgoing responses, and can be enabled in production environments to monitor the application's interactions with clients and other services.
|
|
74
|
+
- **info** - used for informational messages that highlight the progress of the application.
|
|
75
|
+
It's up to the developers to decide in which cases to use `info` but should be used with caution not to overwhelm the logs with too much data.
|
|
76
|
+
As a rule of thumb, this is a recommended default log level for production environments, as it provides a good balance between verbosity and usefulness of logs for monitoring and troubleshooting.
|
|
77
|
+
- **warn** - used for potentially harmful situations.
|
|
78
|
+
Typical use cases include catching functional, not technical, errors, such as validation errors, or failed external service calls.
|
|
79
|
+
- **error** - used for error events that might still allow the application to continue running.
|
|
80
|
+
Typical use cases include catching technical errors.
|
|
81
|
+
|
|
82
|
+
### Message format
|
|
83
|
+
The message is not the main payload — it is the human‑readable summary of the event.
|
|
84
|
+
|
|
85
|
+
A good message follows this pattern:
|
|
86
|
+
|
|
87
|
+
> \<verb\> \<domain object\> \<status\> [key=value key=value ...]
|
|
88
|
+
|
|
89
|
+
Examples:
|
|
90
|
+
|
|
91
|
+
* "created user successfully id=123 email=john@example.com"
|
|
92
|
+
* "executed SQL query duration=42ms rows=12"
|
|
93
|
+
* "validated request body errors=3"
|
|
94
|
+
* "failed to send email reason=timeout"
|
|
95
|
+
|
|
96
|
+
The message should be:
|
|
97
|
+
* human‑readable sentence fragment
|
|
98
|
+
* lower-cased to be visually uniform
|
|
99
|
+
|
|
100
|
+
Key-value pairs are optional, and should follow the rules:
|
|
101
|
+
* follow the message
|
|
102
|
+
* space-separated
|
|
103
|
+
* keys should be camelCased
|
|
104
|
+
* values should be simple data types (string, number, boolean), no JSON.
|
|
105
|
+
* if value contains spaces, it should be enclosed in quotes, e.g. `reason="validation failed"`
|
|
106
|
+
|
|
107
|
+
### Metadata
|
|
108
|
+
Depending on the log level and the invocationContext, it is often useful to include additional rawMetadata in log entries.
|
|
109
|
+
It can be done by passing an object as a parameter to logging methods, following the message parameter.
|
|
110
|
+
```typescript
|
|
111
|
+
logger.debug(`fetched items for customer customerId=${customerId}`, { customerId, responseData });
|
|
112
|
+
```
|
|
113
|
+
> Note: The rawMetadata can be passed in multiple parameters. The all should be merged into a single object, and the last parameter should take precedence in case of key conflicts.
|
|
114
|
+
|
|
115
|
+
### Errors
|
|
116
|
+
It should be possible to use error as the parameter of logging methods.
|
|
117
|
+
For better logging of errors, it is recommended to introduce a custom base error class that extends the native Error class, and includes additional properties.
|
|
118
|
+
```typescript
|
|
119
|
+
export interface AzFunctionsErrorOptions extends ErrorOptions {
|
|
120
|
+
details?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export class AzFunctionsError extends Error {
|
|
124
|
+
readonly details?: Record<string, unknown>;
|
|
125
|
+
|
|
126
|
+
constructor(message?: string, options?: AzFunctionsErrorOptions) {
|
|
127
|
+
super(message, options);
|
|
128
|
+
this.name = this.constructor.name;
|
|
129
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
130
|
+
this.details = options?.details;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
> **Note**: Logging of the error should happen only if it is handled and not re-thrown, otherwise it can lead to duplicate logging of the same error in case of multiple catch blocks.
|
|
135
|
+
|
|
136
|
+
## Choice of logging framework ([winston](https://github.com/winstonjs/winston))
|
|
137
|
+
During the analysis of logging frameworks, we have considered several options, including [winston](https://github.com/winstonjs/winston).
|
|
138
|
+
Following main reasoning were considered for choosing winston as the logging framework for Azure Functions:
|
|
139
|
+
- **Customizable transports**: Winston allows for the creation of custom transports, enabling log level based routing and filtering and also integration with Azure Application Insights.
|
|
140
|
+
- **Structured logging support**: Winston natively supports structured logging, allowing developers to include rawMetadata in their log entries.
|
|
141
|
+
- **Top community support**: Winston is a widely used logging library in the Node.js ecosystem, with a large community and active development, ensuring ongoing support and improvements.
|
|
142
|
+
|
|
143
|
+
## Integration of [winston](https://github.com/winstonjs/winston)
|
|
144
|
+
The primary assumption for the integration of winston is the usage of IoC container [inversifyJS](https://github.com/inversify/InversifyJS).
|
|
145
|
+
|
|
146
|
+
It is necessary to have an invocation invocationContext of the Azure Function trigger in the invocationContext of logger calls, to be able to correlate logs with the specific function invocation.
|
|
147
|
+
|
|
148
|
+
### Available log levels
|
|
149
|
+
The logging system supports the following log levels, in order of increasing severity:
|
|
150
|
+
- **silly** - the most verbose log level, used for detailed debugging information that may be useful during development or troubleshooting.
|
|
151
|
+
- **debug** - used for general debugging information, less detailed than `silly`.
|
|
152
|
+
- **verbose** - used for verbose logging, providing more invocationContext than `info`.
|
|
153
|
+
- **http** - used for HTTP request/result logging.
|
|
154
|
+
- **info** - used for informational messages that highlight the progress of the application.
|
|
155
|
+
- **warn** - used for potentially harmful situations.
|
|
156
|
+
- **error** - used for error events that might still allow the application to continue running.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
export const LOG_LEVELS = {
|
|
160
|
+
error: 0,
|
|
161
|
+
warn: 1,
|
|
162
|
+
info: 2,
|
|
163
|
+
http: 3,
|
|
164
|
+
verbose: 4,
|
|
165
|
+
debug: 5,
|
|
166
|
+
silly: 6,
|
|
167
|
+
} as const;
|
|
168
|
+
|
|
169
|
+
export type LogLevel = keyof typeof LOG_LEVELS;
|
|
170
|
+
export const DEFAULT_ROOT_LOG_LEVEL: LogLevel = 'info';
|
|
171
|
+
export const DEFAULT_LOG_LEVEL = serviceIdentifier<LogLevel>('LOG_LEVEL');
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Logger
|
|
175
|
+
A logger is a fork of the winston logger, which provides the same logging methods (`error`, `warn`, `info`, `http`, `verbose`, `debug`, `silly`) and supports structured logging with JSON rawMetadata.
|
|
176
|
+
Log entries are enriched with a timestamp and rawMetadata about the function invocation (like invocation id, function name, etc.) to provide better invocationContext for log analysis and troubleshooting.
|
|
177
|
+
String interpolation can be omitted in favout of string templates.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
export type Logger = Pick<winston.Logger, LogLevel>;
|
|
181
|
+
```
|
|
182
|
+
```typescript
|
|
183
|
+
container.bind(winston.Logger).toDynamicValue(invocationContext => {
|
|
184
|
+
const transport = invocationContext.get(AzFunctionsTransport);
|
|
185
|
+
return winston.createLogger({
|
|
186
|
+
level: 'verbose',
|
|
187
|
+
levels: LOG_LEVELS,
|
|
188
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.splat(), winston.format.rawMetadata()),
|
|
189
|
+
transports: [transport],
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
* Each log entry wil be formatted:
|
|
194
|
+
* To include timestamp
|
|
195
|
+
* to translate message by the string interpolation. (It is needed for backward compatibility)
|
|
196
|
+
* To include structured rawMetadata in JSON format.
|
|
197
|
+
* Custom transport will implement logic to filter log entries based on their log level and threshold resolved by the logger name, and route them to Azure Application Insights.
|
|
198
|
+
|
|
199
|
+
### Logger factory
|
|
200
|
+
A logger factory provides an instance of a logger with the preconfigured logger name.
|
|
201
|
+
It has a single parameter - logger name, which is a string that represents the scope of the functionality or component that uses this dedicated logger.
|
|
202
|
+
If logger name is omitted, the logger factory will request the name from the `LOGGER_NAME_PROVIDER` (which is a function that returns the logger name).
|
|
203
|
+
If it is not provided, it will use the global default logger name `ROOT_LOGGER_NAME` as a fallback.
|
|
204
|
+
```typescript
|
|
205
|
+
export const LOGGER_FACTORY = serviceIdentifier<LoggerFactory>('Logger factory.');
|
|
206
|
+
export type LoggerFactory = (loggerName?: string) => Logger;
|
|
207
|
+
|
|
208
|
+
export const ROOT_LOGGER_NAME = 'root';
|
|
209
|
+
|
|
210
|
+
export type LoggerNameProvider = (stackEntry?: string) => string | undefined;
|
|
211
|
+
export const LOGGER_NAME_PROVIDER = serviceIdentifier<LoggerNameProvider>('LOGGER_NAME_PROVIDER');
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
> **Note**: The logger name can be set / overridden in each call to logger by setting rawMetadata property `loggerName` in the log entry.
|
|
215
|
+
|
|
216
|
+
### Platform invocationContext manager
|
|
217
|
+
The original invocation invocationContext of the Azure Function trigger should be preserved in the call invocationContext of the implementation.
|
|
218
|
+
This is necessary to be able to correlate log entries with the specific function invocation, and also to provide the fallback logger that uses the original invocation invocationContext logger if the OpenTelemetry was not properly configured.
|
|
219
|
+
|
|
220
|
+
This is done by introducing a platform invocationContext manager that allows to run the trigger handler in a customized invocationContext.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
export class PlatformContextError extends AzFunctionsRuntimeError {}
|
|
224
|
+
|
|
225
|
+
export const PLATFORM_CONTEXT_MANAGER = serviceIdentifier<PlatformContextManager>('Platform InvocationCtx manager');
|
|
226
|
+
|
|
227
|
+
export interface PlatformContextManager {
|
|
228
|
+
active(): PlatformContext | undefined;
|
|
229
|
+
runWith<T>(platformContext: PlatformContext, callback: () => T): T;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@injectable()
|
|
233
|
+
export class BasePlatformContextManager implements PlatformContextManager {
|
|
234
|
+
private readonly storage = new AsyncLocalStorage<PlatformContext>();
|
|
235
|
+
|
|
236
|
+
runWith<T>(platformContext: PlatformContext, callback: () => T): T {
|
|
237
|
+
if (this.active() !== undefined) {
|
|
238
|
+
throw new PlatformContextError(
|
|
239
|
+
'A platform InvocationCtx is already active. Nested platform contexts are not supported.',
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return this.storage.run(platformContext, callback);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
active(): PlatformContext | undefined {
|
|
246
|
+
return this.storage.getStore();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Platform invocationContext provider
|
|
252
|
+
```typescript
|
|
253
|
+
export const PLATFORM_CONTEXT_PROVIDER = serviceIdentifier<PlatformContextProvider>('Platform InvocationCtx provider');
|
|
254
|
+
export interface PlatformContextProvider {
|
|
255
|
+
providePlatformContext(invocationContext: InvocationContext): PlatformContext;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export const ORIGINAL_INVOCATION_CONTEXT_VALUE_KEY =
|
|
259
|
+
createPlatformContextValueKey<InvocationContext>('Original invocation InvocationCtx');
|
|
260
|
+
|
|
261
|
+
export class PlatformExecutionContext implements PlatformContext {
|
|
262
|
+
private readonly data: Map<PlatformContextValueKey, unknown>;
|
|
263
|
+
readonly invocationContext: InvocationContext;
|
|
264
|
+
|
|
265
|
+
constructor(invocationContext: InvocationContext, logger: winston.Logger) {
|
|
266
|
+
this.invocationContext = new WrappedInvocationContext(invocationContext, logger.child({}));
|
|
267
|
+
this.data = new Map<PlatformContextValueKey, unknown>();
|
|
268
|
+
this.data.set(ORIGINAL_INVOCATION_CONTEXT_VALUE_KEY, invocationContext);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
getValue<T>(key: PlatformContextValueKey<T>): T | undefined {
|
|
272
|
+
return this.data.get(key) as T | undefined;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
setValue<T>(key: PlatformContextValueKey<T>, value: T): PlatformContext {
|
|
276
|
+
this.data.set(key, value);
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
deleteValue(key: PlatformContextValueKey): PlatformContext {
|
|
281
|
+
this.data.delete(key);
|
|
282
|
+
return this;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@injectable()
|
|
287
|
+
export class PlatformExecutionContextProvider implements PlatformContextProvider {
|
|
288
|
+
constructor(private readonly logger: winston.Logger) {}
|
|
289
|
+
|
|
290
|
+
providePlatformContext(invocationContext: InvocationContext): PlatformContext {
|
|
291
|
+
return new PlatformExecutionContext(invocationContext, this.logger);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Invocation invocationContext wrapper
|
|
297
|
+
The original invocation invocationContext of the Azure Function trigger should be wrapped in a customized invocationContext that allows proxying the logging calls to the underlying winston logger, while preserving the original invocationContext information.
|
|
298
|
+
This invocationContext should be used in the execution
|
|
299
|
+
|
|
300
|
+
#### Programming model v3
|
|
301
|
+
```typescript
|
|
302
|
+
class WrappedInvocationContext implements InvocationCtx {
|
|
303
|
+
log: Logger;
|
|
304
|
+
|
|
305
|
+
constructor(
|
|
306
|
+
private invocationContext: InvocationCtx,
|
|
307
|
+
logger: winston.Logger,
|
|
308
|
+
) {
|
|
309
|
+
this.log = Object.assign((message: any, ...args: any[]) => logger.info(message, ...args), {
|
|
310
|
+
error: (message: any, ...args: any[]) => logger.error(message, ...args),
|
|
311
|
+
warn: (message: any, ...args: any[]) => logger.warn(message, ...args),
|
|
312
|
+
info: (message: any, ...args: any[]) => logger.info(message, ...args),
|
|
313
|
+
verbose: (message: any, ...args: any[]) => logger.verbose(message, ...args),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
get bindingData(): ContextBindingData {
|
|
318
|
+
return this.invocationContext.bindingData;
|
|
319
|
+
}
|
|
320
|
+
set bindingData(value: ContextBindingData) {
|
|
321
|
+
this.invocationContext.bindingData = value;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
get bindingDefinitions(): BindingDefinition[] {
|
|
325
|
+
return this.invocationContext.bindingDefinitions;
|
|
326
|
+
}
|
|
327
|
+
set bindingDefinitions(value: BindingDefinition[]) {
|
|
328
|
+
this.invocationContext.bindingDefinitions = value;
|
|
329
|
+
}
|
|
330
|
+
get bindings(): ContextBindings {
|
|
331
|
+
return this.invocationContext.bindings;
|
|
332
|
+
}
|
|
333
|
+
set bindings(value: ContextBindings) {
|
|
334
|
+
this.invocationContext.bindings = value;
|
|
335
|
+
}
|
|
336
|
+
get executionContext(): ExecutionContext {
|
|
337
|
+
return this.invocationContext.executionContext;
|
|
338
|
+
}
|
|
339
|
+
set executionContext(value: ExecutionContext) {
|
|
340
|
+
this.invocationContext.executionContext = value;
|
|
341
|
+
}
|
|
342
|
+
get invocationId(): string {
|
|
343
|
+
return this.invocationContext.invocationId;
|
|
344
|
+
}
|
|
345
|
+
set invocationId(value: string) {
|
|
346
|
+
this.invocationContext.invocationId = value;
|
|
347
|
+
}
|
|
348
|
+
get req(): HttpRequest | undefined {
|
|
349
|
+
return this.invocationContext.req;
|
|
350
|
+
}
|
|
351
|
+
set req(value: HttpRequest) {
|
|
352
|
+
this.invocationContext.req = value;
|
|
353
|
+
}
|
|
354
|
+
get res(): { [p: string]: any } | undefined {
|
|
355
|
+
return this.invocationContext.res;
|
|
356
|
+
}
|
|
357
|
+
set res(value: { [p: string]: any }) {
|
|
358
|
+
this.invocationContext.res = value;
|
|
359
|
+
}
|
|
360
|
+
get suppressAsyncDoneError(): boolean | undefined {
|
|
361
|
+
return this.invocationContext.suppressAsyncDoneError;
|
|
362
|
+
}
|
|
363
|
+
set suppressAsyncDoneError(value: boolean) {
|
|
364
|
+
this.invocationContext.suppressAsyncDoneError = value;
|
|
365
|
+
}
|
|
366
|
+
get traceContext(): TraceContext {
|
|
367
|
+
return this.invocationContext.traceContext;
|
|
368
|
+
}
|
|
369
|
+
set traceContext(value: TraceContext) {
|
|
370
|
+
this.invocationContext.traceContext = value;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
done(err?: Error | string | null, result?: any): void {
|
|
374
|
+
this.done(err, result);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
##### Programming model v4
|
|
381
|
+
```typescript
|
|
382
|
+
const LOG_LEVEL_MAP: Record<FunctionsLoglevel, LogLevel> = {
|
|
383
|
+
critical: 'error',
|
|
384
|
+
error: 'error',
|
|
385
|
+
warning: 'warn',
|
|
386
|
+
information: 'info',
|
|
387
|
+
debug: 'debug',
|
|
388
|
+
trace: 'verbose',
|
|
389
|
+
none: 'info',
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
export class WrappedInvocationContext extends InvocationContext {
|
|
393
|
+
constructor(parentInvocationContext: InvocationContext, logger: winston.Logger) {
|
|
394
|
+
super({
|
|
395
|
+
...parentInvocationContext,
|
|
396
|
+
logHandler: (level, ...args) => {
|
|
397
|
+
const translatedLogLevel = LOG_LEVEL_MAP[level];
|
|
398
|
+
const [message, ...meta] = args;
|
|
399
|
+
logger.log(translatedLogLevel, message as string, ...meta);
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Logger Transport
|
|
407
|
+
|
|
408
|
+
The custom transport will implement following logic:
|
|
409
|
+
* Filters log entries based on their log level and threshold resolved by the logger name.
|
|
410
|
+
* Combines the rawMetadata.
|
|
411
|
+
* Adjusts rawMetadata with error chain structure if error is present in the log entry.
|
|
412
|
+
* Routes log entries to Azure Application Insights using the underlying invocation invocationContext of the Azure Function trigger.
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
function isLogLevel(level: string): level is LogLevel {
|
|
416
|
+
return level in LOG_LEVELS;
|
|
417
|
+
}
|
|
418
|
+
function logLevelOrDefault(level: string): LogLevel {
|
|
419
|
+
return isLogLevel(level) ? level : DEFAULT_ROOT_LOG_LEVEL;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export type InvocationContextLogger = Pick<InvocationContext, 'log' | 'trace' | 'debug' | 'info' | 'warn' | 'error'>;
|
|
423
|
+
|
|
424
|
+
export const LOG_METHOD_MAP: Record<LogLevel, keyof InvocationContextLogger | undefined> = {
|
|
425
|
+
error: 'error',
|
|
426
|
+
warn: 'warn',
|
|
427
|
+
info: 'info',
|
|
428
|
+
http: 'info',
|
|
429
|
+
verbose: 'info',
|
|
430
|
+
debug: 'debug',
|
|
431
|
+
silly: 'trace',
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
interface LogMetadata {
|
|
435
|
+
loggerName?: string;
|
|
436
|
+
stack?: string;
|
|
437
|
+
cause?: unknown;
|
|
438
|
+
details?: unknown;
|
|
439
|
+
name?: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
interface LogInfo {
|
|
443
|
+
level: LogLevel;
|
|
444
|
+
message: string;
|
|
445
|
+
timestamp: string;
|
|
446
|
+
rawMetadata: LogMetadata;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
@injectable()
|
|
450
|
+
export class AzFunctionsTransport extends Transport {
|
|
451
|
+
constructor(
|
|
452
|
+
@inject(PLATFORM_CONTEXT_MANAGER)
|
|
453
|
+
private readonly platformContextManager: PlatformContextManager,
|
|
454
|
+
@inject(OtelLogger)
|
|
455
|
+
@optional()
|
|
456
|
+
private readonly logger: OtelLogger | undefined,
|
|
457
|
+
private readonly logLevelsService: LogLevelService,
|
|
458
|
+
) {
|
|
459
|
+
super();
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
463
|
+
log(info: LogInfo, next: () => void): any {
|
|
464
|
+
setImmediate(() => {
|
|
465
|
+
this.emit('logged', info);
|
|
466
|
+
});
|
|
467
|
+
const {
|
|
468
|
+
level,
|
|
469
|
+
rawMetadata: { loggerName },
|
|
470
|
+
} = info;
|
|
471
|
+
const currentLogLevel = logLevelOrDefault(level);
|
|
472
|
+
const availableLogLevel = this.logLevelsService.getLogLevel(loggerName);
|
|
473
|
+
|
|
474
|
+
if (LOG_LEVELS[currentLogLevel] <= LOG_LEVELS[availableLogLevel]) {
|
|
475
|
+
this.logInternal(info);
|
|
476
|
+
}
|
|
477
|
+
if (next) {
|
|
478
|
+
next();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
private logInternal(info: LogInfo): void {
|
|
483
|
+
const platformContext = this.platformContextManager.active();
|
|
484
|
+
const invocationContext = platformContext?.invocationContext;
|
|
485
|
+
const platformLogInfo = this.getPlatformLogInfo(info, invocationContext);
|
|
486
|
+
if (this.logger !== undefined) {
|
|
487
|
+
this.logger.log(platformLogInfo);
|
|
488
|
+
} else {
|
|
489
|
+
const originalInvocationContext = platformContext?.getValue<InvocationContext>(
|
|
490
|
+
ORIGINAL_INVOCATION_CONTEXT_VALUE_KEY,
|
|
491
|
+
);
|
|
492
|
+
const logMethod = LOG_METHOD_MAP[info.level] ?? 'log';
|
|
493
|
+
originalInvocationContext?.[logMethod](platformLogInfo.message, platformLogInfo.rawMetadata);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
private getPlatformLogInfo(logInfo: LogInfo, invocationContext?: InvocationContext): PlatformLogInfo {
|
|
498
|
+
const {
|
|
499
|
+
timestamp,
|
|
500
|
+
message,
|
|
501
|
+
rawMetadata: { loggerName, stack, cause, details, ...rest },
|
|
502
|
+
} = logInfo;
|
|
503
|
+
const rawMetadata: Metadata = {
|
|
504
|
+
loggerName: loggerName ?? ROOT_LOGGER_NAME,
|
|
505
|
+
};
|
|
506
|
+
if (stack !== undefined) {
|
|
507
|
+
const errorChain: ErrorChain = {
|
|
508
|
+
name: rest.name ?? 'Error',
|
|
509
|
+
message,
|
|
510
|
+
stack,
|
|
511
|
+
};
|
|
512
|
+
if (details !== undefined) {
|
|
513
|
+
Object.assign(errorChain, { details });
|
|
514
|
+
}
|
|
515
|
+
this.provideErrorChain(errorChain, cause);
|
|
516
|
+
rawMetadata.errorChain = errorChain;
|
|
517
|
+
}
|
|
518
|
+
if (loggerName) {
|
|
519
|
+
rawMetadata.loggerName = loggerName;
|
|
520
|
+
}
|
|
521
|
+
Object.assign(rawMetadata, rest);
|
|
522
|
+
return {
|
|
523
|
+
level: logInfo.level,
|
|
524
|
+
timestamp: new Date(timestamp),
|
|
525
|
+
message,
|
|
526
|
+
invocationId: invocationContext?.invocationId,
|
|
527
|
+
traceContext: invocationContext?.traceContext,
|
|
528
|
+
operationName: invocationContext?.functionName,
|
|
529
|
+
rawMetadata,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
private provideErrorChain(errorChain: ErrorChain, error: unknown) {
|
|
534
|
+
if (error === undefined) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const innerError: ErrorChain = {
|
|
538
|
+
name: 'UnknownError',
|
|
539
|
+
message: String(error),
|
|
540
|
+
};
|
|
541
|
+
errorChain.innerError = innerError;
|
|
542
|
+
if (error instanceof Error) {
|
|
543
|
+
innerError.name = error.name;
|
|
544
|
+
innerError.message = error.message;
|
|
545
|
+
if (error.stack) {
|
|
546
|
+
innerError.stack = error.stack;
|
|
547
|
+
}
|
|
548
|
+
this.provideErrorChain(innerError, error.cause);
|
|
549
|
+
}
|
|
550
|
+
if (error instanceof AzFunctionsError && error.details) {
|
|
551
|
+
Object.assign(innerError, { details: error.details });
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Integration of Open Telemetry
|
|
558
|
+
### Open Telemetry logger (OtelLogger)
|
|
559
|
+
Otel logger is an optional dependency that can be used to log telemetry data to Azure Application Insights using OpenTelemetry.
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
const LOG_LEVEL_SEVERITY_MAP: Record<LogLevel, { severityNumber: SeverityNumber; severityText: string }> = {
|
|
563
|
+
error: {
|
|
564
|
+
severityNumber: SeverityNumber.ERROR,
|
|
565
|
+
severityText: 'error',
|
|
566
|
+
},
|
|
567
|
+
warn: {
|
|
568
|
+
severityNumber: SeverityNumber.WARN,
|
|
569
|
+
severityText: 'warn',
|
|
570
|
+
},
|
|
571
|
+
info: {
|
|
572
|
+
severityNumber: SeverityNumber.INFO,
|
|
573
|
+
severityText: 'info',
|
|
574
|
+
},
|
|
575
|
+
http: {
|
|
576
|
+
severityNumber: SeverityNumber.INFO2,
|
|
577
|
+
severityText: 'http',
|
|
578
|
+
},
|
|
579
|
+
verbose: {
|
|
580
|
+
severityNumber: SeverityNumber.INFO3,
|
|
581
|
+
severityText: 'verbose',
|
|
582
|
+
},
|
|
583
|
+
debug: {
|
|
584
|
+
severityNumber: SeverityNumber.DEBUG,
|
|
585
|
+
severityText: 'debug',
|
|
586
|
+
},
|
|
587
|
+
silly: {
|
|
588
|
+
severityNumber: SeverityNumber.TRACE,
|
|
589
|
+
severityText: 'silly',
|
|
590
|
+
},
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
const TraceParentRegex = /^\d{2}-([0-9a-z]+)-([0-9a-z]+)-\d{2}$/;
|
|
594
|
+
|
|
595
|
+
@injectable()
|
|
596
|
+
export class OtelLogger implements PlatformLogger {
|
|
597
|
+
constructor(@inject(LOGGER_PROVIDER) private readonly loggerProvider: LoggerProvider) {}
|
|
598
|
+
|
|
599
|
+
log(logInfo: PlatformLogInfo): void {
|
|
600
|
+
const traceContextValues = this.decodeTraceContext(logInfo);
|
|
601
|
+
let invocationContext;
|
|
602
|
+
if (traceContextValues !== undefined) {
|
|
603
|
+
invocationContext = trace.setSpanContext(ROOT_CONTEXT, {
|
|
604
|
+
traceId: traceContextValues.triggerId,
|
|
605
|
+
spanId: traceContextValues.operationParentId,
|
|
606
|
+
traceFlags: 1,
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
const logger = this.loggerProvider.getLogger('default');
|
|
610
|
+
logger.emit({
|
|
611
|
+
timestamp: logInfo.timestamp,
|
|
612
|
+
...LOG_LEVEL_SEVERITY_MAP[logInfo.level],
|
|
613
|
+
body: logInfo.message,
|
|
614
|
+
invocationContext,
|
|
615
|
+
attributes: this.getCustomDimensions(logInfo),
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
private decodeTraceContext(logInfo: PlatformLogInfo): { triggerId: string; operationParentId: string } | undefined {
|
|
620
|
+
const { traceContext } = logInfo;
|
|
621
|
+
if (traceContext !== undefined) {
|
|
622
|
+
const traceParent = traceContext.traceParent;
|
|
623
|
+
const traceParentParts = traceParent !== undefined ? TraceParentRegex.exec(traceParent) : null;
|
|
624
|
+
if (traceParentParts !== null && traceParentParts.length >= 3) {
|
|
625
|
+
const triggerId = traceParentParts[1]!;
|
|
626
|
+
const operationParentId = traceParentParts[2]!;
|
|
627
|
+
return { triggerId, operationParentId };
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
private getCustomDimensions(logInfo: PlatformLogInfo): AnyValueMap {
|
|
633
|
+
const { level, invocationId, traceContext, rawMetadata } = logInfo;
|
|
634
|
+
const severity = LOG_LEVEL_SEVERITY_MAP[level].severityText;
|
|
635
|
+
return {
|
|
636
|
+
LogLevel: severity,
|
|
637
|
+
Category: traceContext?.attributes?.Category,
|
|
638
|
+
HostInstanceId: traceContext?.attributes?.HostInstanceId,
|
|
639
|
+
ProcessId: traceContext?.attributes?.ProcessId ?? process.pid,
|
|
640
|
+
InvocationId: invocationId,
|
|
641
|
+
Metadata: {
|
|
642
|
+
...rawMetadata,
|
|
643
|
+
},
|
|
644
|
+
...traceContext?.attributes,
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
### Logger provider
|
|
651
|
+
The logger provider is a wrapper around the OpenTelemetry logger provider that allows to get a logger instance.
|
|
652
|
+
|
|
653
|
+
```typescript
|
|
654
|
+
import { AzureMonitorLogExporter } from '@azure/monitor-opentelemetry-exporter';
|
|
655
|
+
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
656
|
+
import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';
|
|
657
|
+
import { ATTR_SERVICE_INSTANCE_ID, ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
658
|
+
|
|
659
|
+
....
|
|
660
|
+
|
|
661
|
+
container.bind(LOGGER_PROVIDER).toDynamicValue(() => {
|
|
662
|
+
const connectionString = otelConfiguration?.applicationInsightsConnectionString;
|
|
663
|
+
return new LoggerProvider({
|
|
664
|
+
resource: resourceFromAttributes({
|
|
665
|
+
[ATTR_SERVICE_NAME]: otelConfiguration?.serviceName,
|
|
666
|
+
[ATTR_SERVICE_INSTANCE_ID]: otelConfiguration?.serviceInstanceId,
|
|
667
|
+
[ATTR_SERVICE_VERSION]: otelConfiguration?.serviceVersion,
|
|
668
|
+
}),
|
|
669
|
+
processors: [new BatchLogRecordProcessor(new AzureMonitorLogExporter({ connectionString }))],
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## Usage
|
|
675
|
+
The trigger handler call should be wrapped in a customized invocationContext:
|
|
676
|
+
|
|
677
|
+
#### Programming model v3
|
|
678
|
+
```typescript
|
|
679
|
+
export const HTTP_REQUEST_CONTEXT_VALUE_KEY =
|
|
680
|
+
createPlatformContextValueKey<InvocationCtx>('Original HTTP request');
|
|
681
|
+
|
|
682
|
+
async function innerHttpTrigger(invocationContext: InvocationCtx, req: HttpRequest): Promise<void> {
|
|
683
|
+
const logger = container.get(LOGGER_FACTORY)('httpTriggerLogger');
|
|
684
|
+
const contextProvider = container.get(PLATFORM_CONTEXT_PROVIDER);
|
|
685
|
+
const contextManager = container.get(PLATFORM_CONTEXT_MANAGER)
|
|
686
|
+
await contextManager.runWithContext(contextProvider.providePlatformContext(invocationContext)
|
|
687
|
+
.setValue(HTTP_REQUEST_CONTEXT_VALUE_KEY, req) , async () => {
|
|
688
|
+
const wrappedContext = contextManager.active().invocationContext;
|
|
689
|
+
const originalContext = contextProvider.active().get(ORIGINAL_INVOCATION_CONTEXT_VALUE_KEY);
|
|
690
|
+
const originalReq = contextProvider.active().get(HTTP_REQUEST_CONTEXT_VALUE_KEY);
|
|
691
|
+
logger.http(`Received HTTP request: ${originalReq.method} ${originalReq.url}`, {
|
|
692
|
+
req: {
|
|
693
|
+
method: originalReq.method,
|
|
694
|
+
url: originalReq.url,
|
|
695
|
+
headers: originalReq.headers,
|
|
696
|
+
body: originalReq.body,
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
// trigger handler logic
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
#### Programming model v4
|
|
705
|
+
```typescript
|
|
706
|
+
export const HTTP_REQUEST_CONTEXT_VALUE_KEY =
|
|
707
|
+
createPlatformContextValueKey<InvocationContext>('Original HTTP request');
|
|
708
|
+
|
|
709
|
+
app.http('getAllTracks', {
|
|
710
|
+
route: '/allTracks',
|
|
711
|
+
methods: 'GET',
|
|
712
|
+
handler: async (request: HttpRequest, invocationContext: InvocationContext) => {
|
|
713
|
+
const logger = container.get(LOGGER_FACTORY)('httpTriggerLogger');
|
|
714
|
+
const contextProvider = container.get(CONTEXT_PROVIDER);
|
|
715
|
+
const contextManager = container.get(CONTEXT_MANAGER)
|
|
716
|
+
await contextManager.runWithContext(contextProvider.providePlatformContext(invocationContext)
|
|
717
|
+
.setValue(HTTP_REQUEST_CONTEXT_VALUE_KEY, request) , async () => {
|
|
718
|
+
const wrappedContext = contextManager.active().invocationContext;
|
|
719
|
+
const originalContext = contextProvider.active().get(ORIGINAL_INVOCATION_CONTEXT_VALUE_KEY);
|
|
720
|
+
const originalReq = contextProvider.active().get(HTTP_REQUEST_CONTEXT_VALUE_KEY);
|
|
721
|
+
logger.http(`Received HTTP request: ${originalReq.method} ${originalReq.url}`, {
|
|
722
|
+
request: {
|
|
723
|
+
method: request.method,
|
|
724
|
+
url: request.url,
|
|
725
|
+
headers: request.headers,
|
|
726
|
+
body: request.text(),
|
|
727
|
+
},
|
|
728
|
+
});
|
|
729
|
+
// trigger handler logic
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Configuration of Azure Functions App
|
|
737
|
+
If the OTEL logger is configured, we should skip the system logs, provided by the extension.
|
|
738
|
+
However, we need the request entries to be provided to Application insights, so we can observe the trace entries over the Azure Porrtal view:
|
|
739
|
+
|
|
740
|
+
host.json:
|
|
741
|
+
```json
|
|
742
|
+
{
|
|
743
|
+
"version": "2.0",
|
|
744
|
+
"logging": {
|
|
745
|
+
"loglevel": {
|
|
746
|
+
"default": "None",
|
|
747
|
+
"Host.Results": "Information"
|
|
748
|
+
},
|
|
749
|
+
"console": {
|
|
750
|
+
"isEnabled": false
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
"extensionBundle": {
|
|
754
|
+
"id": "Microsoft.Azure.Functions.ExtensionBundle",
|
|
755
|
+
"version": "[4.0.0, 5.0.0)"
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
## Out of the scope
|
|
761
|
+
|
|
762
|
+
### Logger name provider
|
|
763
|
+
For the well-structured project the name for the logger can be taken from its project paths, started from src and ended with the name of the service class.
|
|
764
|
+
|
|
765
|
+
E.g. Service class TrackController, placed in
|
|
766
|
+
> `packages/examples/backend/src/interfaces/rest/console/trucks/trucks.controller.ts`
|
|
767
|
+
|
|
768
|
+
can have logger name
|
|
769
|
+
> `#backend.interfaces.rest.console.trucks.TrucksController`
|
|
770
|
+
|
|
771
|
+
Example:
|
|
772
|
+
|
|
773
|
+
at **TrucksController**.getTrucks (packages/examples/backend/src/**interfaces/rest/console/trucks**/trucks.controller.ts:54:16)
|
|
774
|
+
|
|
775
|
+
at processTicksAndRejections (node:internal/process/task_queues:105:5)
|
|
776
|
+
|
|
777
|
+
at packages/extensions/transaction-manager/src/Transactional-methods.ts:31:16
|
|
778
|
+
|
|
779
|
+
### Log level provider
|
|
780
|
+
The log level provider is responsible for providing the log level for a given logger name.
|
|
781
|
+
We can use so-called **Trie Search** algorithm to find the most specific log level for a given logger name, based on the configured log levels for different logger names.
|
|
782
|
+
|
|
783
|
+
if the most specific logger name for `#backend.interfaces.rest.console.trucks.TrucksController`
|
|
784
|
+
is configured as `#backend.interfaces.rest` -> `verbose`
|
|
785
|
+
then the log level for `#backend.interfaces.rest.console.trucks.TrucksController` will be `verbose`, unless it is overridden by a more specific configuration.
|
|
786
|
+
If no log level is configured for the logger name, the global default log level will be used as a fallback.
|
|
787
|
+
|
|
788
|
+
### Log level persistence
|
|
789
|
+
In the distributed system, it is necessary to persist the log level configuration in a centralized storage, so that all instances of the application can access the same configuration.
|
|
790
|
+
Moreover, it is necessary to provide a mechanism for updating the log level configuration in real-time, so that changes can be propagated to all instances of the application without requiring a restart.
|
|
791
|
+
|
|
792
|
+
For this purpose, we can use a distributed cache like Redis or Hazelcast.
|
|
793
|
+
|
|
794
|
+
### Multiple transports
|
|
795
|
+
It is thinkable to have multiple transports for different log levels, so that we can route logs to different destinations based on their severity.
|
|
796
|
+
The cheap destinations with lower time-to-live can be used for lower log levels, while the more expensive destinations with higher time-to-live can be used for higher log levels.
|
|
797
|
+
|
|
798
|
+
For the lower log levels, we can use a BLOB Storage or a NoSQL database like CosmosDB, while for the higher log levels we can use a more expensive destination like Azure Application Insights.
|
|
799
|
+
|
|
800
|
+
### Batch log record processing
|
|
801
|
+
The logging system should support batch processing of log records, allowing developers to group multiple log entries together and send them to the logging destination in a single request, reducing the overhead of network communication and improving performance.
|
|
802
|
+
|
|
803
|
+
The processing should be configurable, allowing developers to specify the batch size, flush interval, queue size and export timeout, to optimize the performance and resource usage of the logging system based on the specific needs of the application.
|
|
804
|
+
|
|
805
|
+
This can be achieved by using the `BatchLogRecordProcessor` from the OpenTelemetry SDK.
|