Logs: Added support for numeric log levels (#87366)

* logs: add support for numeric loglevels

* Log types: add a numeric level map to LogLevel

* getLogLevelFromKey: adapt to support numeric levels

* Formatting

* getLogLevelFromKey: accept strings or numbers

---------

Co-authored-by: Matias Chomicki <matyax@gmail.com>
This commit is contained in:
Dmitry Bashkatov
2024-06-05 14:56:36 +03:00
committed by GitHub
parent f262880b68
commit 17525ad43f
5 changed files with 61 additions and 12 deletions

View File

@@ -92,15 +92,15 @@ For the logs where a `level` label is specified, we use the value of this label
**Supported log levels and mapping of log level abbreviation and expressions:**
| Log level | Color | Supported expressions |
| :-------- | :--------- | ---------------------------------------- |
| critical | purple | emerg, fatal, alert, crit, critical |
| error | red | err, eror, error |
| warning | yellow | warn, warning |
| info | green | info, information, informational, notice |
| debug | blue | dbug, debug |
| trace | light blue | trace |
| unknown | grey | \* |
| Log level | Color | Supported expressions |
| :-------- | :--------- | ---------------------------------------------- |
| critical | purple | emerg, fatal, alert, crit, critical, 0, 1, 2 |
| error | red | err, eror, error, 3 |
| warning | yellow | warn, warning, 4 |
| info | green | info, information, informational, notice, 5, 6 |
| debug | blue | dbug, debug, 7 |
| trace | light blue | trace |
| unknown | grey | \* |
### Highlight searched words

View File

@@ -33,6 +33,21 @@ export enum LogLevel {
unknown = 'unknown',
}
/**
* Mapping of log level abbreviation to canonical log level.
* Supported levels are reduce to limit color variation.
*/
export const NumericLogLevel: Record<string, LogLevel> = {
'0': LogLevel.critical,
'1': LogLevel.critical,
'2': LogLevel.critical,
'3': LogLevel.error,
'4': LogLevel.warning,
'5': LogLevel.info,
'6': LogLevel.info,
'7': LogLevel.debug,
};
// Used for meta information such as common labels or returned log rows in logs view in Explore
export enum LogsMetaKind {
Number,

View File

@@ -425,7 +425,7 @@ export function logSeriesToLogsModel(
let logLevel = LogLevel.unknown;
const logLevelKey = (logLevelField && logLevelField.values[j]) || (labels && labels['level']);
if (logLevelKey) {
if (typeof logLevelKey === 'number' || typeof logLevelKey === 'string') {
logLevel = getLogLevelFromKey(logLevelKey);
} else {
logLevel = getLogLevel(entry);

View File

@@ -63,8 +63,30 @@ describe('getLogLevelFromKey()', () => {
it('returns correct log level when level is capitalized', () => {
expect(getLogLevelFromKey('INFO')).toBe(LogLevel.info);
});
it('returns unknown log level when level is integer', () => {
expect(getLogLevelFromKey(1)).toBe(LogLevel.unknown);
describe('Numeric log levels', () => {
it('returns critical', () => {
expect(getLogLevelFromKey(0)).toBe(LogLevel.critical);
expect(getLogLevelFromKey('0')).toBe(LogLevel.critical);
expect(getLogLevelFromKey('1')).toBe(LogLevel.critical);
expect(getLogLevelFromKey('2')).toBe(LogLevel.critical);
});
it('returns error', () => {
expect(getLogLevelFromKey('3')).toBe(LogLevel.error);
});
it('returns warning', () => {
expect(getLogLevelFromKey('4')).toBe(LogLevel.warning);
});
it('returns info', () => {
expect(getLogLevelFromKey('5')).toBe(LogLevel.info);
expect(getLogLevelFromKey('6')).toBe(LogLevel.info);
});
it('returns debug', () => {
expect(getLogLevelFromKey('7')).toBe(LogLevel.debug);
});
it('returns unknown log level when level is an unexpected integer', () => {
expect(getLogLevelFromKey('8')).toBe(LogLevel.unknown);
expect(getLogLevelFromKey(8)).toBe(LogLevel.unknown);
});
});
});

View File

@@ -13,6 +13,7 @@ import {
MutableDataFrame,
QueryResultMeta,
LogsVolumeType,
NumericLogLevel,
} from '@grafana/data';
import { getDataframeFields } from './components/logParser';
@@ -49,6 +50,17 @@ export function getLogLevelFromKey(key: string | number): LogLevel {
if (level) {
return level;
}
if (typeof key === 'string') {
// The level did not match any entry of LogLevel. It might be unknown or a numeric level.
const numericLevel = parseInt(key, 10);
// Safety check to confirm that we're parsing a number and not a number with a string.
// For example `parseInt('1abcd', 10)` outputs 1
if (key.length === numericLevel.toString().length) {
return NumericLogLevel[key] || LogLevel.unknown;
}
} else if (typeof key === 'number') {
return NumericLogLevel[key] || LogLevel.unknown;
}
return LogLevel.unknown;
}