Skip to content

Commit

Permalink
Merge branch 'main' into 139589-hosts-view-tech-preview
Browse files Browse the repository at this point in the history
  • Loading branch information
neptunian committed Sep 15, 2022
2 parents 2ea72c2 + e5bc7be commit d0ff576
Show file tree
Hide file tree
Showing 27 changed files with 1,526 additions and 62 deletions.
5 changes: 5 additions & 0 deletions packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export type ApmApplicationMetricFields = Partial<{
'jvm.memory.heap.used': number;
'jvm.memory.non_heap.used': number;
'jvm.thread.count': number;
'faas.billed_duration': number;
'faas.timeout': number;
'faas.coldstart_duration': number;
'faas.duration': number;
}>;

export type ApmUserAgentFields = Partial<{
Expand Down Expand Up @@ -104,6 +108,7 @@ export type ApmFields = Fields &
'cloud.region': string;
'host.os.platform': string;
'faas.id': string;
'faas.name': string;
'faas.coldstart': boolean;
'faas.execution': string;
'faas.trigger.type': string;
Expand Down
2 changes: 2 additions & 0 deletions packages/kbn-apm-synthtrace/src/lib/apm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
import { service } from './service';
import { browser } from './browser';
import { serverlessFunction } from './serverless_function';
import { getTransactionMetrics } from './processors/get_transaction_metrics';
import { getSpanDestinationMetrics } from './processors/get_span_destination_metrics';
import { getChromeUserAgentDefaults } from './defaults/get_chrome_user_agent_defaults';
Expand All @@ -27,6 +28,7 @@ export const apm = {
getApmWriteTargets,
ApmSynthtraceEsClient,
ApmSynthtraceKibanaClient,
serverlessFunction,
};

export type { ApmSynthtraceEsClient, ApmException };
88 changes: 88 additions & 0 deletions packages/kbn-apm-synthtrace/src/lib/apm/serverless.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { generateLongId, generateShortId } from '../utils/generate_id';
import { ApmFields } from './apm_fields';
import { BaseSpan } from './base_span';
import { Metricset } from './metricset';

export type FaasTriggerType = 'http' | 'pubsub' | 'datasource' | 'timer' | 'other';

export class Serverless extends BaseSpan {
private readonly metric: Metricset<ApmFields>;

constructor(fields: ApmFields) {
const faasExection = generateLongId();
const triggerType = 'other';
super({
...fields,
'processor.event': 'transaction',
'transaction.id': generateShortId(),
'transaction.sampled': true,
'faas.execution': faasExection,
'faas.trigger.type': triggerType,
'transaction.name': fields['transaction.name'] || fields['faas.name'],
'transaction.type': 'request',
});
this.metric = new Metricset<ApmFields>({
...fields,
'metricset.name': 'app',
'faas.execution': faasExection,
'faas.id': fields['service.name'],
});
}

duration(duration: number) {
this.fields['transaction.duration.us'] = duration * 1000;
return this;
}

coldStart(coldstart: boolean) {
this.fields['faas.coldstart'] = coldstart;
this.metric.fields['faas.coldstart'] = coldstart;
return this;
}

billedDuration(billedDuration: number) {
this.metric.fields['faas.billed_duration'] = billedDuration;
return this;
}

faasTimeout(faasTimeout: number) {
this.metric.fields['faas.timeout'] = faasTimeout;
return this;
}

memory({ total, free }: { total: number; free: number }) {
this.metric.fields['system.memory.total'] = total;
this.metric.fields['system.memory.actual.free'] = free;
return this;
}

coldStartDuration(coldStartDuration: number) {
this.metric.fields['faas.coldstart_duration'] = coldStartDuration;
return this;
}

faasDuration(faasDuration: number) {
this.metric.fields['faas.duration'] = faasDuration;
return this;
}

timestamp(time: number): this {
super.timestamp(time);
this.metric.fields['@timestamp'] = time;
return this;
}

serialize(): ApmFields[] {
const transaction = super.serialize();
const metric = this.metric.serialize();
return [...transaction, ...metric];
}
}
45 changes: 45 additions & 0 deletions packages/kbn-apm-synthtrace/src/lib/apm/serverless_function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { Entity } from '../entity';
import { generateShortId } from '../utils/generate_id';
import { ApmFields } from './apm_fields';
import { ServerlessInstance } from './serverless_instance';

export class ServerlessFunction extends Entity<ApmFields> {
instance({ instanceName, ...apmFields }: { instanceName: string } & ApmFields) {
return new ServerlessInstance({
...this.fields,
['service.node.name']: instanceName,
'host.name': instanceName,
...apmFields,
});
}
}

export function serverlessFunction({
functionName,
serviceName,
environment,
agentName,
}: {
functionName: string;
environment: string;
agentName: string;
serviceName?: string;
}) {
const faasId = `arn:aws:lambda:us-west-2:${generateShortId()}:function:${functionName}`;
return new ServerlessFunction({
'service.name': serviceName || faasId,
'faas.id': faasId,
'faas.name': functionName,
'service.environment': environment,
'agent.name': agentName,
'service.runtime.name': 'AWS_lambda',
});
}
22 changes: 22 additions & 0 deletions packages/kbn-apm-synthtrace/src/lib/apm/serverless_instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { Entity } from '../entity';
import { ApmFields } from './apm_fields';
import { FaasTriggerType, Serverless } from './serverless';

export class ServerlessInstance extends Entity<ApmFields> {
invocation(params: { transactionName?: string; faasTriggerType?: FaasTriggerType } = {}) {
const { transactionName, faasTriggerType = 'other' } = params;
return new Serverless({
...this.fields,
'transaction.name': transactionName,
'faas.trigger.type': faasTriggerType,
});
}
}
103 changes: 69 additions & 34 deletions packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,90 @@
*/

import { apm, timerange } from '../..';
import { ApmFields } from '../lib/apm/apm_fields';
import { Scenario } from '../cli/scenario';
import { getLogger } from '../cli/utils/get_common_services';
import { RunOptions } from '../cli/utils/parse_run_cli_flags';
import { ApmFields } from '../lib/apm/apm_fields';
import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment';

const ENVIRONMENT = getSynthtraceEnvironment(__filename);

const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => {
const logger = getLogger(runOptions);

return {
generate: ({ from, to }) => {
const range = timerange(from, to);
const timestamps = range.ratePerMinute(180);

const instance = apm
.service({ name: 'lambda-python', environment: ENVIRONMENT, agentName: 'python' })
.instance('instance');

const traceEventsSetups = [
{ functionName: 'lambda-python-1', coldStart: true },
{ functionName: 'lambda-python-2', coldStart: false },
];

const traceEvents = ({ functionName, coldStart }: typeof traceEventsSetups[0]) => {
return timestamps.generator((timestamp) =>
instance
.transaction({ transactionName: 'GET /order/{id}' })
.defaults({
'service.runtime.name': 'AWS_Lambda_python3.8',
'cloud.provider': 'aws',
'cloud.service.name': 'lambda',
'cloud.region': 'us-east-1',
'faas.id': `arn:aws:lambda:us-west-2:123456789012:function:${functionName}`,
'faas.coldstart': coldStart,
'faas.trigger.type': 'other',
})
const cloudFields: ApmFields = {
'cloud.provider': 'aws',
'cloud.service.name': 'lambda',
'cloud.region': 'us-west-2',
};

const instanceALambdaPython = apm
.serverlessFunction({
serviceName: 'aws-lambdas',
environment: ENVIRONMENT,
agentName: 'python',
functionName: 'fn-python-1',
})
.instance({ instanceName: 'instance_A', ...cloudFields });

const instanceALambdaNode = apm
.serverlessFunction({
serviceName: 'aws-lambdas',
environment: ENVIRONMENT,
agentName: 'nodejs',
functionName: 'fn-node-1',
})
.instance({ instanceName: 'instance_A', ...cloudFields });

const instanceALambdaNode2 = apm
.serverlessFunction({
environment: ENVIRONMENT,
agentName: 'nodejs',
functionName: 'fn-node-2',
})
.instance({ instanceName: 'instance_A', ...cloudFields });

const memory = {
total: 536870912, // 0.5gb
free: 94371840, // ~0.08 gb
};

const awsLambdaEvents = timestamps.generator((timestamp) => {
return [
instanceALambdaPython
.invocation()
.duration(1000)
.timestamp(timestamp)
.coldStart(true)
.billedDuration(4000)
.faasTimeout(10000)
.memory(memory)
.coldStartDuration(4000)
.faasDuration(4000),
instanceALambdaNode
.invocation()
.duration(1000)
.success()
);
};
.timestamp(timestamp)
.coldStart(false)
.billedDuration(4000)
.faasTimeout(10000)
.memory(memory)
.faasDuration(4000),
instanceALambdaNode2
.invocation()
.duration(1000)
.timestamp(timestamp)
.coldStart(false)
.billedDuration(4000)
.faasTimeout(10000)
.memory(memory)
.faasDuration(4000),
];
});

return traceEventsSetups
.map((traceEventsSetup) =>
logger.perf('generating_apm_events', () => traceEvents(traceEventsSetup))
)
.reduce((p, c) => p.merge(c));
return awsLambdaEvents;
},
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({

return {
splitSeriesAccessors: splitColumnIds.length ? splitColumnIds : [],
stackAccessors: isStacked && xColumnId ? [xColumnId] : [],
stackAccessors: isStacked ? [xColumnId || 'unifiedX'] : [],
id: generateSeriesId(
layer,
splitColumnIds.length ? splitColumnIds : [EMPTY_ACCESSOR],
Expand Down
9 changes: 8 additions & 1 deletion src/plugins/charts/public/static/components/warnings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ export function Warnings({ warnings }: { warnings: React.ReactNode[] }) {
panelPaddingSize="none"
closePopover={() => setOpen(false)}
button={
<EuiButtonEmpty color="warning" iconType="alert" onClick={() => setOpen(!open)} size="xs">
<EuiButtonEmpty
color="warning"
iconType="alert"
onClick={() => setOpen(!open)}
size="xs"
data-test-subj="chart-inline-warning-button"
>
{i18n.translate('charts.warning.warningLabel', {
defaultMessage:
'{numberWarnings, number} {numberWarnings, plural, one {warning} other {warnings}}',
Expand All @@ -39,6 +45,7 @@ export function Warnings({ warnings }: { warnings: React.ReactNode[] }) {
css={{
padding: euiThemeVars.euiSizeS,
}}
data-test-subj="chart-inline-warning"
>
<EuiText size="s">{w}</EuiText>
</div>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d0ff576

Please sign in to comment.