Skip to content

Commit

Permalink
[7.x] Prepare APM agent configuration for production use (#78697) (#7…
Browse files Browse the repository at this point in the history
…9569)

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
joshdover and kibanamachine authored Oct 6, 2020
1 parent 9deeb0f commit 3c1a71f
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 24 deletions.
5 changes: 3 additions & 2 deletions packages/kbn-apm-config-loader/src/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ describe('ApmConfiguration', () => {
resetAllMocks();
});

it('sets the correct service name', () => {
it('sets the correct service name and version', () => {
packageMock.raw = {
version: '9.2.1',
};
const config = new ApmConfiguration(mockedRootDir, {}, false);
expect(config.getConfig('myservice').serviceName).toBe('myservice-9_2_1');
expect(config.getConfig('myservice').serviceName).toBe('myservice');
expect(config.getConfig('myservice').serviceVersion).toBe('9.2.1');
});

it('sets the git revision from `git rev-parse` command in non distribution mode', () => {
Expand Down
29 changes: 26 additions & 3 deletions packages/kbn-apm-config-loader/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@ const getDefaultConfig = (isDistributable: boolean): ApmAgentConfig => {
return {
active: false,
globalLabels: {},
// Do not use a centralized controlled config
centralConfig: false,
// Capture all exceptions that are not caught
logUncaughtExceptions: true,
// Can be performance intensive, disabling by default
breakdownMetrics: false,
};
}

return {
active: false,
serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443',
Expand Down Expand Up @@ -60,14 +67,14 @@ export class ApmConfiguration {
) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { version, build } = require(join(this.rootDir, 'package.json'));
this.kibanaVersion = version.replace(/\./g, '_');
this.kibanaVersion = version;
this.pkgBuild = build;
}

public getConfig(serviceName: string): ApmAgentConfig {
return {
...this.getBaseConfig(),
serviceName: `${serviceName}-${this.kibanaVersion}`,
serviceName,
};
}

Expand All @@ -76,7 +83,8 @@ export class ApmConfiguration {
const apmConfig = merge(
getDefaultConfig(this.isDistributable),
this.getConfigFromKibanaConfig(),
this.getDevConfig()
this.getDevConfig(),
this.getDistConfig()
);

const rev = this.getGitRev();
Expand All @@ -88,6 +96,8 @@ export class ApmConfiguration {
if (uuid) {
apmConfig.globalLabels.kibana_uuid = uuid;
}

apmConfig.serviceVersion = this.kibanaVersion;
this.baseConfig = apmConfig;
}

Expand Down Expand Up @@ -123,6 +133,19 @@ export class ApmConfiguration {
}
}

/** Config keys that cannot be overridden in production builds */
private getDistConfig(): ApmAgentConfig {
if (!this.isDistributable) {
return {};
}

return {
// Headers & body may contain sensitive info
captureHeaders: false,
captureBody: 'off',
};
}

private getGitRev() {
if (this.isDistributable) {
return this.pkgBuild.sha;
Expand Down
18 changes: 16 additions & 2 deletions src/apm.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,22 @@ module.exports = function (serviceName = name) {

apmConfig = loadConfiguration(process.argv, ROOT_DIR, isKibanaDistributable);
const conf = apmConfig.getConfig(serviceName);
require('elastic-apm-node').start(conf);
const apm = require('elastic-apm-node');

// Filter out all user PII
apm.addFilter((payload) => {
try {
if (payload.context && payload.context.user && typeof payload.context.user === 'object') {
Object.keys(payload.context.user).forEach((key) => {
payload.context.user[key] = '[REDACTED]';
});
}
} finally {
return payload;
}
});

apm.start(conf);
};

module.exports.getConfig = (serviceName) => {
Expand All @@ -50,4 +65,3 @@ module.exports.getConfig = (serviceName) => {
}
return {};
};
module.exports.isKibanaDistributable = isKibanaDistributable;
1 change: 1 addition & 0 deletions src/cli/cluster/cluster_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class ClusterManager {
type: 'server',
log: this.log,
argv: serverArgv,
apmServiceName: 'kibana',
})),
];

Expand Down
2 changes: 2 additions & 0 deletions src/cli/cluster/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ interface WorkerOptions {
title?: string;
watch?: boolean;
baseArgv?: string[];
apmServiceName?: string;
}

export class Worker extends EventEmitter {
Expand Down Expand Up @@ -89,6 +90,7 @@ export class Worker extends EventEmitter {
NODE_OPTIONS: process.env.NODE_OPTIONS || '',
kbnWorkerType: this.type,
kbnWorkerArgv: JSON.stringify([...(opts.baseArgv || baseArgv), ...(opts.argv || [])]),
ELASTIC_APM_SERVICE_NAME: opts.apmServiceName || '',
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
* under the License.
*/

require('../apm')(process.env.ELASTIC_APM_PROXY_SERVICE_NAME || 'kibana-proxy');
require('../apm')(process.env.ELASTIC_APM_SERVICE_NAME || 'kibana-proxy');
require('../setup_node_env');
require('./cli');
5 changes: 3 additions & 2 deletions src/core/public/apm_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { InternalApplicationStart } from './application';

interface ApmConfig {
// AgentConfigOptions is not exported from @elastic/apm-rum
active?: boolean;
globalLabels?: Record<string, string>;
}

Expand All @@ -39,10 +40,10 @@ export class ApmSystem {
private readonly enabled: boolean;
/**
* `apmConfig` would be populated with relevant APM RUM agent
* configuration if server is started with `ELASTIC_APM_ACTIVE=true`
* configuration if server is started with elastic.apm.* config.
*/
constructor(private readonly apmConfig?: ApmConfig) {
this.enabled = process.env.IS_KIBANA_DISTRIBUTABLE !== 'true' && apmConfig != null;
this.enabled = apmConfig != null && !!apmConfig.active;
}

async setup() {
Expand Down
4 changes: 4 additions & 0 deletions src/legacy/server/config/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const HANDLED_IN_NEW_PLATFORM = Joi.any().description(
);
export default () =>
Joi.object({
elastic: Joi.object({
apm: HANDLED_IN_NEW_PLATFORM,
}).default(),

pkg: Joi.object({
version: Joi.string().default(Joi.ref('$version')),
branch: Joi.string().default(Joi.ref('$branch')),
Expand Down
18 changes: 4 additions & 14 deletions src/legacy/ui/apm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,20 @@
* under the License.
*/

import { getConfig, isKibanaDistributable } from '../../../apm';
import { getConfig } from '../../../apm';
import agent from 'elastic-apm-node';

const apmEnabled = !isKibanaDistributable && process.env.ELASTIC_APM_ACTIVE === 'true';

export function apmImport() {
return apmEnabled ? 'import { init } from "@elastic/apm-rum"' : '';
}

export function apmInit(config) {
return apmEnabled ? `init(${config})` : '';
}
const apmEnabled = getConfig()?.active;

export function getApmConfig(requestPath) {
if (!apmEnabled) {
return null;
}
const config = {
...getConfig('kibana-frontend'),
...{
active: true,
pageLoadTransactionName: requestPath,
},
pageLoadTransactionName: requestPath,
};

/**
* Get current active backend transaction to make distrubuted tracing
* work for rendering the app
Expand Down

0 comments on commit 3c1a71f

Please sign in to comment.