Skip to content

Commit

Permalink
fix(aws-lambda): reduced lambda runtimes for large number of spans
Browse files Browse the repository at this point in the history
  • Loading branch information
kirrg001 committed Sep 9, 2024
1 parent a85026e commit 9f730fe
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 25 deletions.
4 changes: 4 additions & 0 deletions packages/aws-lambda/src/identity_provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ exports.init = function init(arnInfo) {
qualifiedArn = arnInfo.arn;
};

exports.getName = function getName() {
return 'aws-lambda';
};

exports.getHostHeader = function getHostHeader() {
return qualifiedArn;
};
Expand Down
15 changes: 8 additions & 7 deletions packages/aws-lambda/test/multiple_data/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('multiple data lambda handler', function () {
});
});

describe('[batching disabled] with 100 iterations', function () {
describe('with 100 iterations and high transmission config values', function () {
this.timeout(config.getTestTimeout() * 2);
let control;

Expand All @@ -106,7 +106,9 @@ describe('multiple data lambda handler', function () {
env: {
INSTANA_AGENT_KEY: instanaAgentKey,
WITH_CONFIG: 'true',
INSTANA_NUMBER_OF_ITERATIONS: 100
INSTANA_NUMBER_OF_ITERATIONS: 100,
INSTANA_FORCE_TRANSMISSION_STARTING_AT: 500,
INSTANA_TRACING_INITIAL_TRANSMISSION_DELAY: 1000
}
});

Expand Down Expand Up @@ -160,7 +162,9 @@ describe('multiple data lambda handler', function () {
});
});

describe('[batching enabled] with 100 iterations', function () {
// TODO: This test does not use any batchable spans.
// We could also extend the test to enable batching.
describe('with 100 iterations and default behavior', function () {
this.timeout(config.getTestTimeout() * 2);
let control;

Expand All @@ -172,10 +176,7 @@ describe('multiple data lambda handler', function () {
env: {
INSTANA_AGENT_KEY: instanaAgentKey,
WITH_CONFIG: 'true',
INSTANA_NUMBER_OF_ITERATIONS: 100,
INSTANA_SPANBATCHING_ENABLED: 'true',
INSTANA_FORCE_TRANSMISSION_STARTING_AT: 10,
INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS: 100
INSTANA_NUMBER_OF_ITERATIONS: 100
}
});

Expand Down
4 changes: 4 additions & 0 deletions packages/collector/src/pidStore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Object.defineProperty(exports, 'pid', {
}
});

exports.getName = function getName() {
return 'default-identity';
};

exports.getEntityId = function getEntityId() {
return internalPidStore.pid;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function preInit() {
function init(config, downstreamConnection, processIdentityProvider) {
log.init(/** @type {log.LoggerConfig} */ (config));
util.hasThePackageBeenInitializedTooLate();
config = normalizeConfig(config);
config = normalizeConfig(config, processIdentityProvider);
secrets.init(/** @type {secrets.SecretOption} */ (config));
util.requireHook.init(config);
tracing.init(config, downstreamConnection, processIdentityProvider);
Expand Down
35 changes: 22 additions & 13 deletions packages/core/src/tracing/spanBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,8 @@ let isActive = false;
/** @type {number} */
let activatedAt = null;

let minDelayBeforeSendingSpans = 1000;
if (process.env.INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS != null) {
minDelayBeforeSendingSpans = parseInt(process.env.INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS, 10);
if (isNaN(minDelayBeforeSendingSpans)) {
minDelayBeforeSendingSpans = 1000;
}
}

/** @type {number} */
let initialDelayBeforeSendingSpans;
let initialTransmissionDelay;
/** @type {number} */
let transmissionDelay;
/** @type {number} */
Expand Down Expand Up @@ -98,7 +90,19 @@ exports.init = function init(config, _downstreamConnection) {
forceTransmissionStartingAt = config.tracing.forceTransmissionStartingAt;
transmissionDelay = config.tracing.transmissionDelay;
batchingEnabled = config.tracing.spanBatchingEnabled;
initialDelayBeforeSendingSpans = Math.max(transmissionDelay, minDelayBeforeSendingSpans);
initialTransmissionDelay = config.tracing.initialTransmissionDelay;

// TODO: drop undocumented env variable in v4 major release
if (process.env.INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS != null) {
initialTransmissionDelay = parseInt(process.env.INSTANA_DEV_MIN_DELAY_BEFORE_SENDING_SPANS, 10);
if (isNaN(initialTransmissionDelay)) {
initialTransmissionDelay = config.tracing.initialTransmissionDelay;
}
}

// TODO: remove in v4 and make initialTransmissionDelay configurable instead
initialTransmissionDelay = Math.max(transmissionDelay, initialTransmissionDelay);

isFaaS = false;
transmitImmediate = false;

Expand Down Expand Up @@ -146,7 +150,7 @@ exports.activate = function activate(extraConfig) {
// On AWS Lambda we wait till the handler finishes and then transmit all collected spans via
// `sendBundle`. Any detected span will be sent directly to the BE.
if (!isFaaS) {
transmissionTimeoutHandle = setTimeout(transmitSpans, initialDelayBeforeSendingSpans);
transmissionTimeoutHandle = setTimeout(transmitSpans, initialTransmissionDelay);
transmissionTimeoutHandle.unref();
}

Expand Down Expand Up @@ -201,8 +205,8 @@ exports.addSpan = function (span) {
addToBucket(span);
}

// NOTE: we send out spans directly if the number of spans reaches > 500 [default] and if the min delay is reached.
if (spans.length >= forceTransmissionStartingAt && Date.now() - minDelayBeforeSendingSpans > activatedAt) {
// NOTE: we send out spans directly if the number of spans reaches > X [default] and if the min delay is reached.
if (spans.length >= forceTransmissionStartingAt && Date.now() - initialTransmissionDelay > activatedAt) {
transmitSpans();
}
}
Expand Down Expand Up @@ -402,6 +406,11 @@ function batchingBucketKey(span) {
}

/**
* IMPORTANT: Only some instrumentations are enabled to be batchable.
* e.g. mysql, pg, redis, elasticsearch, etc.
* Batching spans means to collect multiple spans of the same type
* and merge them into one span.
*
* @param {import('./cls').InstanaBaseSpan} span
* @returns {boolean}
*/
Expand Down
33 changes: 29 additions & 4 deletions packages/core/src/util/normalizeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
'use strict';

const supportedTracingVersion = require('../tracing/supportedVersion');

const deepMerge = require('../util/deepMerge');
const constants = require('../tracing/constants');

/**
Expand All @@ -18,6 +18,7 @@ const constants = require('../tracing/constants');
* @property {boolean} [automaticTracingEnabled]
* @property {boolean} [activateImmediately]
* @property {number} [forceTransmissionStartingAt]
* @property {number} [initialTransmissionDelay]
* @property {number} [maxBufferedSpans]
* @property {number} [transmissionDelay]
* @property {number} [stackTraceLength]
Expand Down Expand Up @@ -91,7 +92,7 @@ logger = require('../logger').getLogger('configuration', newLogger => {
});

/** @type {InstanaConfig} */
const defaults = {
const defaultsBase = {
serviceName: null,
packageJsonPath: null,

Expand All @@ -108,6 +109,7 @@ const defaults = {
forceTransmissionStartingAt: 500,
maxBufferedSpans: 1000,
transmissionDelay: 1000,
initialTransmissionDelay: 1000,
http: {
extraHttpHeadersToCapture: []
},
Expand All @@ -126,8 +128,17 @@ const defaults = {
}
};

const validKafkaHeaderFormats = ['binary', 'string', 'both'];
/** @type {Record<string, InstanaConfig>} */
const identityProviderDefaults = {
'aws-lambda': {
tracing: { forceTransmissionStartingAt: 10, transmissionDelay: 100, initialTransmissionDelay: 100 }
}
};

/** @type InstanaConfig */
let defaults = {};

const validKafkaHeaderFormats = ['binary', 'string', 'both'];
const validSecretsMatcherModes = ['equals-ignore-case', 'equals', 'contains-ignore-case', 'contains', 'regex', 'none'];

/**
Expand All @@ -136,13 +147,20 @@ const validSecretsMatcherModes = ['equals-ignore-case', 'equals', 'contains-igno

/**
* @param {InstanaConfig} [config]
* @param {import('../../../collector/src/pidStore')} [identityProvider]
* @returns {InstanaConfig}
*/
module.exports = function normalizeConfig(config) {
module.exports = function normalizeConfig(config, identityProvider) {
if (config == null) {
config = {};
}

if (identityProvider && identityProvider.getName && identityProviderDefaults[identityProvider.getName()]) {
defaults = deepMerge(defaultsBase, identityProviderDefaults[identityProvider.getName()]);
} else {
defaults = defaultsBase;
}

normalizeServiceName(config);
normalizePackageJsonPath(config);
normalizeMetricsConfig(config);
Expand Down Expand Up @@ -338,6 +356,13 @@ function normalizeTracingTransmission(config) {
'config.tracing.forceTransmissionStartingAt',
'INSTANA_FORCE_TRANSMISSION_STARTING_AT'
);

config.tracing.initialTransmissionDelay = normalizeSingleValue(
config.tracing.initialTransmissionDelay,
defaults.tracing.initialTransmissionDelay,
'config.tracing.initialTransmissionDelay',
'INSTANA_TRACING_INITIAL_TRANSMISSION_DELAY'
);
}

/**
Expand Down

0 comments on commit 9f730fe

Please sign in to comment.