Skip to content
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

feat(fargate): use adot image for otel #2481

Merged
merged 34 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f0d3d25
feat: implement adot support on otel side
InesNi Feb 5, 2024
4736618
feat: implement adot on fargate side
InesNi Feb 5, 2024
a4137f3
refactor: expose flags to createBom function
InesNi Feb 5, 2024
ec57f09
refactor: resolve config templating in createBom function
InesNi Feb 5, 2024
e5e1059
refactor: make resolved config available to run cluster
InesNi Feb 5, 2024
48b2798
feat: make resolved config available for creating adot definition
InesNi Feb 5, 2024
14f399b
refactor: load dotenv in run-cluster
InesNi Feb 6, 2024
7778a1e
refactor: address case in which context.dotenv is undefined
InesNi Feb 8, 2024
8db0c3c
refactor(cli): merge configuration and creation of adot task definition
InesNi Feb 14, 2024
e614244
refactor(cli): move adot.js logic into run-cluster main waterfall flow
InesNi Feb 14, 2024
e877f5e
refactor(publish-metrics): remove validation and warnings
InesNi Feb 13, 2024
d2f460a
refactor(publish-metrics): change to a more descriptive name
InesNi Feb 13, 2024
68de68e
refactor(cli): separate reporter filtering from collector config asse…
InesNi Feb 13, 2024
6ff2064
refactor(cli): extract env var handling from translators
InesNi Feb 15, 2024
c9ce3c8
refactor(publish-metrics): refactor datadog translator
InesNi Feb 15, 2024
c22c38e
refactor(publish-metrics): rearrange function order for readability
InesNi Feb 15, 2024
c538bca
refactor(cli): fix async changes
InesNi Feb 15, 2024
7cf2427
refactor(cli): improve readability of change
InesNi Feb 15, 2024
4d2a951
refactor: deep clone template
InesNi Feb 16, 2024
53dd90b
refactor(publish-metrics): extract adot translators into their own file
InesNi Feb 19, 2024
667881d
refactor(publish-metrics): use one type for return
InesNi Feb 20, 2024
4c038fe
feat(publish-metrics): add unit tests for adot translator funcs
InesNi Feb 20, 2024
5e119dd
Merge branch 'main' into nidhi-art-1585-implement-adot
InesNi Feb 20, 2024
08672ad
refactor(publish-metrics): warning instead of throwing when no api set
InesNi Feb 20, 2024
fa55049
Merge branch 'main' into nidhi-art-1585-implement-adot
InesNi Feb 28, 2024
087a1c3
fix: fixing merge
InesNi Feb 28, 2024
502753f
test(cli): add unit tests for resolving config with applyScriptChanges
InesNi Feb 29, 2024
d7b318d
test: refactor tests
InesNi Feb 29, 2024
ec1af2d
Merge branch 'main' into nidhi-art-1585-implement-adot
InesNi Mar 1, 2024
980fac5
test(cli): refactor unit test
InesNi Mar 1, 2024
711daba
test(cli): add aws e2e test for adot-datadog
InesNi Mar 1, 2024
39ffd5c
test(cli): record aws e2e adot test
InesNi Mar 1, 2024
0ea3b51
Merge branch 'main' into nidhi-art-1585-implement-adot
InesNi Mar 1, 2024
6e426f4
Merge branch 'main' into nidhi-art-1585-implement-adot
InesNi Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/artillery-plugin-publish-metrics/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const NS = 'plugin:publish-metrics';
const debug = require('debug')(NS);
const A = require('async');

const {
getADOTRelevantReporterConfigs,
resolveADOTConfigSettings
} = require('./lib/open-telemetry/vendor-translators');

// List of reporters that use OpenTelemetry
const REPORTERS_USING_OTEL = [
'open-telemetry',
Expand All @@ -16,7 +21,9 @@ const REPORTERS_USING_OTEL = [
];
module.exports = {
Plugin,
LEGACY_METRICS_FORMAT: false
LEGACY_METRICS_FORMAT: false,
getADOTRelevantReporterConfigs,
resolveADOTConfigSettings
};

function Plugin(script, events) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const debug = require('debug')('plugin:publish-metrics:open-telemetry');
const vendorTranslators = require('./vendor-translators');
const { vendorTranslators } = require('./vendor-translators');
const {
diag,
DiagConsoleLogger,
Expand Down Expand Up @@ -60,9 +60,6 @@ class OTelReporter {
return this;
}

// Warn if traces are configured in multiple reporters
this.warnIfDuplicateTracesConfigured(this.translatedConfigsList);

// Create set of all engines used in test -> even though we only support Playwright and HTTP engine for now this is future compatible
this.getEngines(this.script.scenarios || []);

Expand Down Expand Up @@ -112,14 +109,7 @@ class OTelReporter {
}
}
}
warnIfDuplicateTracesConfigured(configList) {
const tracesConfigs = configList.filter((config) => config.traces);
if (tracesConfigs.length > 1) {
console.warn(
'WARNING: Multiple reporters configured for traces. Currently, you can only use one reporter at a time for reporting traces. Only the first reporter will be used.'
);
}
}

translateToOtel(config) {
return vendorTranslators[config.type](config);
}
Expand All @@ -137,6 +127,11 @@ class OTelReporter {
if (!this.metricsConfig && !this.tracesConfig) {
return done();
}

// Waiting for flush period to complete here rather than in trace/metric reporters
debug('Waiting for flush period to end');
await new Promise((resolve) => setTimeout(resolve, 10000));

if (this.metricReporter) {
await this.metricReporter.cleanup();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,6 @@ class OTelTraceBase {
}

debug('Pending traces done');
debug('Waiting for flush period to complete');
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,145 @@ function attributeListToObject(attributeList, reporterType) {
return attributes;
}

module.exports = vendorTranslators;
//////// ADOT COLLECTOR HANDLING

const ADOTSupportedTraceReporters = ['datadog'];
const ADOTSupportedMetricReporters = [];

// Getting the relevant configurations for ADOT from the full list of reporter configurations

function getADOTRelevantReporterConfigs(configList) {
const configs = configList.filter(
(reporterConfig) =>
(ADOTSupportedTraceReporters.includes(reporterConfig.type) &&
reporterConfig.traces) ||
(ADOTSupportedMetricReporters.includes(reporterConfig.type) &&
reporterConfig.metrics)
);

return configs.length > 0 ? configs : null;
}

// Handling relevant environment variables

function getADOTEnvVars(adotRelevantconfigs, dotenv) {
const envVars = {};
try {
adotRelevantconfigs.forEach((config) => {
const vendorVars = vendorSpecificEnvVarsForCollector[config.type](
config,
dotenv
);
Object.assign(envVars, vendorVars);
});
} catch (err) {
throw new Error(err);
}
return envVars;
}

const vendorSpecificEnvVarsForCollector = {
datadog: (config, dotenv) => {
const apiKey = config.apiKey || dotenv?.DD_API_KEY;
if (!apiKey) {
throw new Error(
"Datadog reporter Error: Missing Datadog API key. Provide it under 'apiKey' setting in your script or under 'DD_API_KEY' environment variable set in your dotenv file."
);
}
return { DD_API_KEY: apiKey };
}
};

// Assembling the configuration for ADOT (in OTel Collector format)

// Different vendors can be used for metrics and tracing so we need to merge all the parts of the config from each vendor into one collector config
function assembleCollectorConfig(adotRelevantConfigs) {
// Translate each vendor-specific config to OpenTelemetry Collector config
const collectorConfigList = adotRelevantConfigs.map((config) =>
vendorToCollectorConfigTranslators[config.type](config)
);

const collectorConfig = { ...collectorConfigTemplate };
// Assemble the final collector config by adding all parts of the config from each vendor
collectorConfigList.forEach((config) => {
collectorConfig.processors = Object.assign(
collectorConfig.processors,
config.processors
);
collectorConfig.exporters = Object.assign(
collectorConfig.exporters,
config.exporters
);
collectorConfig.service.pipelines = Object.assign(
collectorConfig.service.pipelines,
config.service.pipelines
);
});
return collectorConfig;
}

const collectorConfigTemplate = {
receivers: {
otlp: {
protocols: {
http: {
endpoint: '0.0.0.0:4318'
},
grpc: {
endpoint: '0.0.0.0:4317'
}
}
}
},
processors: {},
exporters: {},
service: {
pipelines: {}
}
};

// Map of functions that translate vendor-specific configuration to OpenTelemetry Collector configuration to be used by ADOT
const vendorToCollectorConfigTranslators = {
datadog: (config) => {
const collectorConfig = { ...collectorConfigTemplate };
if (config.traces) {
collectorConfig.processors['batch/trace'] = {
timeout: '10s',
send_batch_max_size: 1024,
send_batch_size: 200
};
collectorConfig.exporters['datadog/api'] = {
traces: {
trace_buffer: 100
},
api: {
key: '${env:DD_API_KEY}'
}
};
collectorConfig.service.pipelines.traces = {
receivers: ['otlp'],
processors: ['batch/trace'],
exporters: ['datadog/api']
};
}
return collectorConfig;
}
};

// Resolve the configuration settings for ADOT

function resolveADOTConfigSettings(options) {
try {
const adotConfig = assembleCollectorConfig(options.configList);
const adotEnvVars = getADOTEnvVars(options.configList, options.dotenv);
return { adotConfig, adotEnvVars };
} catch (err) {
throw new Error(err);
}
}

module.exports = {
vendorTranslators,
getADOTRelevantReporterConfigs,
resolveADOTConfigSettings
};
28 changes: 27 additions & 1 deletion packages/artillery/lib/platform/aws-ecs/legacy/aws-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module.exports = {
ensureParameterExists,
parameterExists,
putParameter,
getParameter
getParameter,
deleteParameter
};

// Wraps ecs.describeTasks to support more than 100 task ARNs in params.tasks
Expand Down Expand Up @@ -124,3 +125,28 @@ async function getParameter(path, region) {
}
}
}

async function deleteParameter(path, region) {
if (region) {
AWS.config.update({ region });
}

const ssm = new AWS.SSM({ apiVersion: '2014-11-06' });

try {
const ssmResponse = await ssm
.deleteParameter({
Name: path
})
.promise();

debug({ ssmResponse });
return ssmResponse;
} catch (ssmErr) {
if (ssmErr.code === 'ParameterNotFound') {
return false;
} else {
throw ssmErr;
}
}
}
17 changes: 15 additions & 2 deletions packages/artillery/lib/platform/aws-ecs/legacy/bom.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const BUILTIN_ENGINES = require('./plugins').getOfficialEngines();

const Table = require('cli-table3');

const { resolveConfigTemplates } = require('../../../../util');
// NOTE: Code below presumes that all paths are absolute

//Tests in Fargate run on ubuntu, which uses posix paths
Expand All @@ -32,12 +33,14 @@ function createBOM(absoluteScriptPath, extraFiles, opts, callback) {
return next(null, {
opts: {
scriptData,
absoluteScriptPath
absoluteScriptPath,
flags: opts.flags
},
localFilePaths: [absoluteScriptPath],
npmModules: []
});
},
applyScriptChanges,
getPlugins,
getCustomEngines,
getCustomJsDependencies,
Expand Down Expand Up @@ -137,7 +140,8 @@ function createBOM(absoluteScriptPath, extraFiles, opts, callback) {
return callback(null, {
files: _.uniqWith(files, _.isEqual),
modules: _.uniq(context.npmModules),
pkgDeps: context.pkgDeps
pkgDeps: context.pkgDeps,
fullyResolvedConfig: context.opts.scriptData.config
});
}
);
Expand All @@ -148,6 +152,15 @@ function isLocalModule(modName) {
return modName.startsWith('.');
}

function applyScriptChanges(context, next) {
resolveConfigTemplates(context.opts.scriptData, context.opts.flags).then(
(resolvedConfig) => {
context.opts.scriptData = resolvedConfig;
return next(null, context);
}
);
}

function getPlugins(context, next) {
let environmentPlugins = _.reduce(
_.get(context, 'opts.scriptData.config.environments', {}),
Expand Down
5 changes: 3 additions & 2 deletions packages/artillery/lib/platform/aws-ecs/legacy/create-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ async function createTest(scriptPath, options, callback) {
originalScriptPath: scriptPath,
name: options.name, // test name, eg simple-bom or aht_$UUID
manifestPath: options.manifestPath,
packageJsonPath: options.packageJsonPath
packageJsonPath: options.packageJsonPath,
flags: options.flags
};

if (typeof options.config === 'string') {
Expand Down Expand Up @@ -82,7 +83,7 @@ function prepareManifest(context, callback) {
createBOM(
fileToAnalyse,
extraFiles,
{ packageJsonPath: context.packageJsonPath },
{ packageJsonPath: context.packageJsonPath, flags: context.flags},
(err, bom) => {
debug(err);
debug(bom);
Expand Down
Loading
Loading