Skip to content

Conversation

@abhilash-sivan
Copy link
Contributor

@abhilash-sivan abhilash-sivan commented Dec 16, 2025

refs https://jsw.ibm.com/browse/INSTA-63750

Current PR

  • Accept stack trace configuration (tracing.global.stack-trace-length and stack-trace) from the agent.
  • Support in-code configuration via tracing.global.stackTraceLength and stackTrace, while keeping tracing.stackTraceLength for backward compatibility.
  • Configuration precedence (highest to lowest):
    agent → tracing.global.stackTraceLength → tracing.stackTraceLength → env var → default
  • Introduce a maximum limit of 500 for stackTraceLength; the default remains 10.
  • Apply agent configuration when present.
  • Enforce the configured stackTraceLength limit in setErrorDetails to demonstrate that the limit is applied.

Next PR

  • Extend the stackTraceLength limit to the getStackTrace function and add the required tests. done in this pr
  • Apply the stackTrace mode and add corresponding tests.

@abhilash-sivan abhilash-sivan marked this pull request as ready for review December 17, 2025 06:34
@abhilash-sivan abhilash-sivan requested a review from a team as a code owner December 17, 2025 06:34
@abhilash-sivan abhilash-sivan marked this pull request as draft December 17, 2025 06:43
@abhilash-sivan abhilash-sivan changed the title feat: accept stack trace config from agent and apply limit of 50 feat: accept stack trace config from agent Dec 17, 2025
@abhilash-sivan abhilash-sivan marked this pull request as ready for review December 17, 2025 10:34
@abhilash-sivan abhilash-sivan changed the title feat: accept stack trace config from agent feat: accept stack trace config from agent and env, and apply Dec 19, 2025
} else {
logger?.warn(
`The value of config.tracing.stackTrace has the non-supported type ${typeof config.tracing.stackTrace}. ` +
`Valid values are: ${validStackTraceModes.join(', ')}. Using default: all`
Copy link
Contributor

Choose a reason for hiding this comment

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

This is also validation.

Copy link
Contributor

@kirrg001 kirrg001 left a comment

Choose a reason for hiding this comment

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

Pre-approving

@abhilash-sivan abhilash-sivan changed the title feat: unified stack trace configuration from agent config and env vars feat: unified stack trace configuration from agent, in-code and env vars Dec 22, 2025
const envVar = 'INSTANA_STACK_TRACE';

if (isAgentConfig) {
const configPath = 'stack-trace value from agent';
Copy link
Contributor

Choose a reason for hiding this comment

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

What is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

configPath is used only for logging purposes.
isAgentConfig is used to identify the source of the configuration, as we apply different rules for agent and non-agent sources.

If the configuration comes from the agent, it takes precedence, and we do not evaluate any other sources.

If the configuration comes from in-code settings, it eventually resolves to the default value if config is not provided.

The isAgentConfig flag helps determine whether we should exit early or continue processing.

This is part of an optimisation effort. Previously, similar logic existed separately for agent and non-agent normalisation, which has now been merged.

}

const validatedConfigGlobal = validateStackTraceMode(
tracingObj?.global?.stackTrace,
Copy link
Contributor

Choose a reason for hiding this comment

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

Its a bit confusing that for agent we forward the config value without global (see unannounced) but for incode we use the global usage here. That needs to be corrected, hard to follow the code.

if (isAgentConfig) {
const configPath = 'stack-trace-length value from agent';

const validatedAgentConfig = validateStackTraceLength(tracingObj?.stackTraceLength, configPath);
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like we still mix validation and normalization :D
The parent caller should deal with that - otherwise you are coupling the code too much

}

const validatedConfig = validateStackTraceLength(tracingObj?.stackTraceLength, 'config.tracing.stackTraceLength');
if (validatedConfig != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Deprecation warning missing

Copy link
Contributor

@kirrg001 kirrg001 left a comment

Choose a reason for hiding this comment

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

See comments

resetEnv();
});

describe('normalize()', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function is now split into 2 and has some logic change (removed validation)

@abhilash-sivan abhilash-sivan force-pushed the feat-stack-trace-config-agent branch from 686b641 to bb4cf08 Compare December 29, 2025 14:10
stackTraceMode = agentTraceConfig.stackTrace;
}

// stackTraceLength is valid when set to any number, including 0
Copy link
Contributor

Choose a reason for hiding this comment

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

// stackTraceLength is valid when set to any number, including 0

Why do we have to do another validation check here? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At activation time, extraConfig?.tracing will be present, and stackTrace may or may not be set by the agent.
If we blindly assign the value, it may be undefined, which would overwrite the existing stackTraceMode.
Therefore, we need to check for its existence before assigning it.

The same applies to length, but in this case we must also support 0 as a valid value.
For that reason, we check the type to confirm validity.

Only when these checks pass do we overwrite the previously resolved value (from core, environment, or default).

ps: we follow this similar logic already:

if (isIgnoreEndpointsEmpty && extraConfig?.tracing?.ignoreEndpoints) {


module.exports.configNormalizers = configNormalizers;
module.exports.configValidators = {
stackTraceValidation: require('./configValidators/stackTraceValidation')
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets keep requires on top. There is a way to lazy load modules, but not part of this PR.

if (config.tracing.global?.stackTrace !== undefined) {
const modeResult = validateStackTraceMode(config.tracing.global.stackTrace);
if (!modeResult.isValid) {
logger.warn(`Invalid config.tracing.global.stackTrace: ${modeResult.error}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: if not valid, you have to return and use the default

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that is already covered in the logic. We validate first and then call the normaliser. The normaliser already returns the default in the relevant cases.

);
config.tracing.stackTraceLength = defaults.tracing.stackTraceLength;
function normalizeTracingStackTrace(config) {
if (config.tracing.global?.stackTrace !== undefined) {
Copy link
Contributor

@kirrg001 kirrg001 Dec 29, 2025

Choose a reason for hiding this comment

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

if (config.tracing.global?.stackTrace !== undefined) {
const modeResult = validateStackTraceMode(config.tracing.global.stackTrace);
if (!modeResult.isValid) {
logger.warn(Invalid config.tracing.global.stackTrace: ${modeResult.error});
}
}
config.tracing.stackTrace = configNormalizers.stackTrace.normalizeStackTraceMode(config);

Why do we call normalize if config.tracing.global?.stackTrace is not set?
The logic in this fn does not look right to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the same as the previous case: the normaliser returns default values under the relevant conditions, such as when the value is not set or when an invalid value is provided.

Unlike the agent (unannounced), we always call the normaliser here. For the unannounced case, the normaliser is only called when a valid configuration is present.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will change this to be in line with unannounced!

Copy link
Contributor

@kirrg001 kirrg001 left a comment

Choose a reason for hiding this comment

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

See comments

@sonarqubecloud
Copy link

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.

3 participants