@aws-lambda-powertools/logger
Version:
The logging package for the Powertools for AWS Lambda (TypeScript) library
138 lines (137 loc) • 4.97 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogAttributesStore = void 0;
require("@aws/lambda-invoke-store");
const env_1 = require("@aws-lambda-powertools/commons/utils/env");
const lodash_merge_1 = __importDefault(require("lodash.merge"));
/**
* Manages storage of log attributes with automatic context detection.
*
* This class abstracts the storage mechanism for log attributes, automatically
* choosing between AsyncLocalStorage (when in async context) and a fallback
* object (when outside async context). The decision is made at runtime on
* every method call to support Lambda's transition to async contexts.
*/
class LogAttributesStore {
#temporaryAttributesKey = Symbol('powertools.logger.temporaryAttributes');
#keysKey = Symbol('powertools.logger.keys');
#fallbackTemporaryAttributes = {};
#fallbackKeys = new Map();
#persistentAttributes = {};
#getTemporaryAttributes() {
if (!(0, env_1.shouldUseInvokeStore)()) {
return this.#fallbackTemporaryAttributes;
}
if (globalThis.awslambda?.InvokeStore === undefined) {
throw new Error('InvokeStore is not available');
}
const store = globalThis.awslambda.InvokeStore;
let stored = store.get(this.#temporaryAttributesKey);
if (stored == null) {
stored = {};
store.set(this.#temporaryAttributesKey, stored);
}
return stored;
}
#getKeys() {
if (!(0, env_1.shouldUseInvokeStore)()) {
return this.#fallbackKeys;
}
if (globalThis.awslambda?.InvokeStore === undefined) {
throw new Error('InvokeStore is not available');
}
const store = globalThis.awslambda.InvokeStore;
let stored = store.get(this.#keysKey);
if (stored == null) {
stored = new Map();
store.set(this.#keysKey, stored);
}
return stored;
}
appendTemporaryKeys(attributes) {
const tempAttrs = this.#getTemporaryAttributes();
(0, lodash_merge_1.default)(tempAttrs, attributes);
const keysMap = this.#getKeys();
for (const key of Object.keys(attributes)) {
keysMap.set(key, 'temp');
}
}
removeTemporaryKeys(keys) {
const tempAttrs = this.#getTemporaryAttributes();
const keysMap = this.#getKeys();
for (const key of keys) {
tempAttrs[key] = undefined;
if (this.#persistentAttributes[key]) {
keysMap.set(key, 'persistent');
}
else {
keysMap.delete(key);
}
}
}
getTemporaryAttributes() {
return { ...this.#getTemporaryAttributes() };
}
clearTemporaryAttributes() {
const tempAttrs = this.#getTemporaryAttributes();
const keysMap = this.#getKeys();
for (const key of Object.keys(tempAttrs)) {
if (this.#persistentAttributes[key]) {
keysMap.set(key, 'persistent');
}
else {
keysMap.delete(key);
}
}
if (!(0, env_1.shouldUseInvokeStore)()) {
this.#fallbackTemporaryAttributes = {};
return;
}
globalThis.awslambda.InvokeStore?.set(this.#temporaryAttributesKey, {});
}
setPersistentAttributes(attributes) {
const keysMap = this.#getKeys();
this.#persistentAttributes = { ...attributes };
for (const key of Object.keys(attributes)) {
keysMap.set(key, 'persistent');
}
}
getPersistentAttributes() {
return { ...this.#persistentAttributes };
}
getAllAttributes() {
const result = {};
const tempAttrs = this.#getTemporaryAttributes();
const keysMap = this.#getKeys();
// First add all persistent attributes
for (const [key, value] of Object.entries(this.#persistentAttributes)) {
if (value !== undefined) {
result[key] = value;
}
}
// Then override with temporary attributes based on keysMap
for (const [key, type] of keysMap.entries()) {
if (type === 'temp' && tempAttrs[key] !== undefined) {
result[key] = tempAttrs[key];
}
}
return result;
}
removePersistentKeys(keys) {
const keysMap = this.#getKeys();
const tempAttrs = this.#getTemporaryAttributes();
for (const key of keys) {
this.#persistentAttributes[key] = undefined;
if (tempAttrs[key]) {
keysMap.set(key, 'temp');
}
else {
keysMap.delete(key);
}
}
}
}
exports.LogAttributesStore = LogAttributesStore;