-
Notifications
You must be signed in to change notification settings - Fork 153
Feature request: Provide ability to refernce and modify Log Level Numerical Thresholds #2525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @OffensiveBias-08-145, thank you for taking the time to open this issue and for writing this thoughtful proposal. I see the value in supporting this use case and I fully agree on the direction of making this an opt-in feature, however I am still not sure on what would be the best way to do this in a backwards compatible way. To help me understand better your proposal, could you please clarify if the ideal solutions are meant to be taken together or only one of them? I'm asking because changing the If this is the case, could you share an example of how you'd use it in practice, if it were Regarding the other option of adding |
@dreamorosi I can see how the issue is slightly confusing. Hopefully the below provides clarity?? Potential ideal solutions:In an ideal world I would love to see both 1 and 2 added 1. Change This would not be propgated to EXAMPLE: //=== UPDATED CLASS PROPERTY ===
class Logger extends Utility implements LoggerInterface {
//...
protected readonly logLevelThresholds: Record<Uppercase<LogLevel>, number>;
//...
}
//=== EXAMPLE USAGE WITH AN EXTENDED LOGGER ===
export class CustomLogger extends PowertoolsLogger {
constructor(options: ConstructorOptions = {}) {
//Override any accidentally passed custom log formatter
const {logFormatter, rest} = options;
super({logFormatter: new CustomLogFormatter(), ...rest});
}
//getter could also be addeded to the lib itself.
public static get logLevelThresholds(): Record<Uppercase<LogLevel>, number> {
return this.logLevelThresholds;
}
}
//...
}
// === EXAMPLE INGESTION INTO EXTERNAL METHODS ===
private getLogLevelNumberFromName(level: LogLevel): number {
let found = 0;
for (const [key, value] of Object.entries(
Logger.logLevelThresholds)) {
if (key.toUpperCase() === level) {
found = value;
break;
}
}
return found;
} 2. Add an optional As an optional, this would allow devs the discretion to add the numerical level value to their logs. By default it can go unused, and if devs want to have it, they can access it by using a custom formatter and using the property itself. //AN EXAMPLE USAGE WOULD BE AS FOLLOWS:
// === UPDATED TYPES ===
type PowertoolsLogData = LogAttributes & {
environment?: Environment;
serviceName: string;
sampleRateValue: number;
lambdaContext?: LambdaFunctionContext;
xRayTraceId?: string;
awsRegion: string;
};
type UnformattedAttributes = PowertoolsLogData & {
error?: Error;
logLevel: LogLevel;
logLevelIndex?: number; //<-- Could also be moved to PowertoolsLogData
timestamp: Date;
message: string;
};
// === USAGE IN A CUSTOM FORMATTER ===
override formatAttributes(
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem {
const baseAttributes = {
timestamp: this.formatTimestamp(attributes.timestamp),
time: attributes.timestamp.getTime(),
level: attributes.logLevel.toUpperCase(),
level_index: attributes.logLevelIndex, //<-- index passed in custom formatter
message: attributes.message,
error: attributes.error ? this.formatError(attributes.error) : null,
//....
},
};
const logItem = new LogItem({attributes: baseAttributes});
logItem.addAttributes({_data: additionalLogAttributes});
return logItem;
}
|
Apologies for the delayed response, and thank you for the explanation. I think there's a third option that would allow you to do the same thing with much less code, and without adding any significant change to the public API. In #2787 we added a new constant for At the moment the map of thresholds resides within the Logger class, but that's the only place it's used and as shown by this issue, it's needlessly hidden within the innards of the Logger. I suggest we extract the import { Logger, LogFormatter, LogItem, LogLevelThreshold } from '@aws-lambda-powertools/logger';
import type { LogAttributes, LogLevel, UnformattedAttributes } from '@aws-lambda-powertools/logger/types';
class CustomLogFormatter extends LogFormatter {
public formatAttributes(
attributes: UnformattedAttributes,
additionalLogAttributes: LogAttributes
): LogItem {
return new LogItem({
attributes: {
...attributes,
logLevel:
LogLevelThreshold[
attributes.logLevel.toUpperCase() as Uppercase<LogLevel>
],
},
}).addAttributes(additionalLogAttributes);
}
}
const logger = new Logger({
logLevel: 'info',
logFormatter: new CustomLogFormatter(),
});
export const handler = () => {
logger.info('Hello, World!');
};
/**
* Output:
* {
* "logLevel": 12,
* "timestamp": "2024-07-31T08:48:29.157Z",
* "message": "Hello, World!",
* "serviceName": "service_undefined",
* "sampleRateValue": 0
* }
*/ I'm going to put this item on the backlog and mark it as open for contributions by adding the The changes needed for this task would be roughly the following:
Note For those interested in contributing, please leave a comment below so that we can assign the issue to you and make sure we don't duplicate efforts. Also, if you have any further questions please don't hesitate to ask here or on our Discord channel. |
I will take this |
This issue is now closed. Please be mindful that future comments are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so. |
This is now released under v2.9.0 version! |
Use case
Currently our logging standard has both the numerical and string representations of the Log Level. The usage of both allow us to have increased efficiency when retrieving or searching logs from storage.
Indexing the numerical value is more efficient that its string counterpart.
Currently it is difficult to directly access the prescribed log levels when extending the Logger class or utilizing a custom log format.
Some of the workarounds include:
UnformattedAttributes
to include the LogLevel Numerical Value (Works but adds another custom interface I then need to manage)LogLevel
used inUnformattedAttributes
allows for upper and lowercase values.'If I am missing something evident please let me know.
I would be happy to open an PR for this.
Solution/User Experience
Ideal Solutions:
logLevelThresholds
changed fromprivate
toprotected
OR utilize a "getter"UnformattedAttributes
orPowertoolsLogData
that represents the numerical LogLevel.This way the numerical log level is easily passed to any Custom log Formatter instead of having to map it using
LogAttributes
or some other workaround.Adding this in the other libraries would be beneficial as well!
Alternative solutions
Creating a helper function in a Custom Log Formatter to map the string LogLevel to its numerical counterpart.
Acknowledgment
Future readers
Please react with 👍 and your use case to help us understand customer demand.
The text was updated successfully, but these errors were encountered: