Skip to content

feat(log4js): added option to capture info logs#2659

Open
aryamohanan wants to merge 5 commits into
mainfrom
feat-log4js
Open

feat(log4js): added option to capture info logs#2659
aryamohanan wants to merge 5 commits into
mainfrom
feat-log4js

Conversation

@aryamohanan

@aryamohanan aryamohanan commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds support for capturing info-level logs for log4js. By default, log capture starts at WARN and above. When configured, INFO logs can also be captured.

Reference: https://github.com/log4js-node/log4js-node/blob/master/lib/levels.js#L96

https://log4js-node.github.io/log4js-node/api.html

Configuration

The log capture level can be configured using either:

  • Environment variable: INSTANA_LOG_LEVEL_CAPTURE
  • In-code configuration: tracing.logLevelCapture

Supported values:

  • INFO
  • WARN (default)
  • ERROR
  • OFF

Log capture behavior

Configuration Captured log levels
INFO INFO, WARN, ERROR, FATAL
WARN WARN, ERROR, FATAL
ERROR ERROR, FATAL
OFF No log spans are captured.

ref: https://jsw.ibm.com/browse/INSTA-101942
tech spec: https://github.ibm.com/instana/technical-documentation/blob/master/tracing/specification/README.md#log-spans

let isActive = false;

const LEVEL_MAP = {
5000: LOG_LEVEL.TRACE,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aryamohanan
aryamohanan marked this pull request as ready for review July 17, 2026 05:54
@aryamohanan
aryamohanan requested a review from a team as a code owner July 17, 2026 05:54
Comment thread packages/core/src/tracing/instrumentation/logging/log4js.js Outdated
@@ -44,7 +54,9 @@ function shimLog(originalLog) {
}

const actualLevel = levels && levels.getLevel(level, levels.INFO);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats this exactly? Can you pls give an example?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already there before.

This is my understanding: getLevel() is used to resolve the provided log4js level into a standard Level object before applying our existing mapping. This handles different custom inputs supported by log4js.

Examples:

logger.log('ERROR', 'Something failed');

resolves to:

Level { level: 40000, levelStr: 'ERROR', colour: 'red' }

If an custom numeric value is provided:

logger.log(3, 'Something wrong');

getLevel() cannot resolve the value, so it falls back to levels.INFO:

Level { level: 20000, levelStr: 'INFO', colour: 'green' }

This ensures we always get a valid log4js Level object before applying our Instana log level mapping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems redundant to me or?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think they're doing the same thing. getLevel() first converts the input into a log4js Level object (for example, from "ERROR" or a Level instance). Our LEVEL_MAP only maps the numeric value from that object (for example, 40000 -> LOG_LEVEL.ERROR).

We could potentially remove getLevel(), but then we'd need to handle all the input formats that log4js accepts ourselves. Since this code was already there, I assumed it was intentionally relying on log4js to normalize the input before applying our mapping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused.

If I print these:

LEVEL Level { level: 50000, levelStr: 'FATAL', colour: 'magenta' }
[class Level] {
  levels: [
    Level { level: 5e-324, levelStr: 'ALL', colour: 'grey' },
    Level { level: 5000, levelStr: 'TRACE', colour: 'blue' },
    Level { level: 10000, levelStr: 'DEBUG', colour: 'cyan' },
    Level { level: 20000, levelStr: 'INFO', colour: 'green' },
    Level { level: 30000, levelStr: 'WARN', colour: 'yellow' },
    Level { level: 40000, levelStr: 'ERROR', colour: 'red' },
    Level { level: 50000, levelStr: 'FATAL', colour: 'magenta' },
    Level { level: 9007199254740992, levelStr: 'MARK', colour: 'grey' },
    Level {
      level: 1.7976931348623157e+308,
      levelStr: 'OFF',
      colour: 'grey'
    }
  ],
  ALL: Level { level: 5e-324, levelStr: 'ALL', colour: 'grey' },
  TRACE: Level { level: 5000, levelStr: 'TRACE', colour: 'blue' },
  DEBUG: Level { level: 10000, levelStr: 'DEBUG', colour: 'cyan' },
  INFO: Level { level: 20000, levelStr: 'INFO', colour: 'green' },
  WARN: Level { level: 30000, levelStr: 'WARN', colour: 'yellow' },
  ERROR: Level { level: 40000, levelStr: 'ERROR', colour: 'red' },
  FATAL: Level { level: 50000, levelStr: 'FATAL', colour: 'magenta' },
  MARK: Level { level: 9007199254740992, levelStr: 'MARK', colour: 'grey' },
  OFF: Level {
    level: 1.7976931348623157e+308,
    levelStr: 'OFF',
    colour: 'grey'
  }
}
ACTUAL LEVEL Level { level: 50000, levelStr: 'FATAL', colour: 'magenta' }

@sonarqubecloud

Copy link
Copy Markdown

@aryamohanan
aryamohanan requested a review from kirrg001 July 20, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants