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

[APM] Generate stack monitoring data #118302

Merged
merged 15 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
14 changes: 4 additions & 10 deletions packages/elastic-apm-synthtrace/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,10 @@
* Side Public License, v 1.
*/

export { service } from './lib/service';
export { browser } from './lib/browser';
export { apm } from './lib/apm';
export { stackMonitoring } from './lib/stack_monitoring';

export { timerange } from './lib/timerange';
export { getTransactionMetrics } from './lib/utils/get_transaction_metrics';
export { getSpanDestinationMetrics } from './lib/utils/get_span_destination_metrics';
export { getObserverDefaults } from './lib/defaults/get_observer_defaults';
export { getChromeUserAgentDefaults } from './lib/defaults/get_chrome_user_agent_defaults';
export { toElasticsearchOutput } from './lib/output/to_elasticsearch_output';
export { getBreakdownMetrics } from './lib/utils/get_breakdown_metrics';

export { cleanWriteTargets } from './lib/utils/clean_write_targets';
export { getWriteTargets } from './lib/utils/get_write_targets';
export { SynthtraceEsClient } from './lib/client/synthtrace_es_client';
export { createLogger, LogLevel } from './lib/utils/create_logger';
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* Side Public License, v 1.
*/

import { Fields } from './entity';
import { Serializable } from './serializable';
import { generateLongId, generateShortId } from './utils/generate_id';
import { ApmFields } from './apm_fields';
import { Serializable } from '../serializable';
import { generateLongId, generateShortId } from '../utils/generate_id';

export class ApmError extends Serializable {
constructor(fields: Fields) {
export class ApmError extends Serializable<ApmFields> {
constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'error',
Expand Down
78 changes: 78 additions & 0 deletions packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 { Fields } from '../entity';

export type ApmApplicationMetricFields = Partial<{
'system.process.memory.size': number;
'system.memory.actual.free': number;
'system.memory.total': number;
'system.cpu.total.norm.pct': number;
'system.process.memory.rss.bytes': number;
'system.process.cpu.total.norm.pct': number;
}>;

export type ApmUserAgentFields = Partial<{
'user_agent.original': string;
'user_agent.os.name': string;
'user_agent.name': string;
'user_agent.device.name': string;
'user_agent.version': number;
}>;

export interface ApmException {
message: string;
}

export type ApmFields = Fields &
Partial<{
'agent.name': string;
'agent.version': string;
'container.id': string;
'ecs.version': string;
'event.outcome': string;
'event.ingested': number;
'error.id': string;
'error.exception': ApmException[];
'error.grouping_name': string;
'error.grouping_key': string;
'host.name': string;
'kubernetes.pod.uid': string;
'metricset.name': string;
'observer.version': string;
'observer.version_major': number;
'parent.id': string;
'processor.event': string;
'processor.name': string;
'trace.id': string;
'transaction.name': string;
'transaction.type': string;
'transaction.id': string;
'transaction.duration.us': number;
'transaction.duration.histogram': {
values: number[];
counts: number[];
};
'transaction.sampled': true;
'service.name': string;
'service.environment': string;
'service.node.name': string;
'span.id': string;
'span.name': string;
'span.type': string;
'span.subtype': string;
'span.duration.us': number;
'span.destination.service.name': string;
'span.destination.service.resource': string;
'span.destination.service.type': string;
'span.destination.service.response_time.sum.us': number;
'span.destination.service.response_time.count': number;
'span.self_time.count': number;
'span.self_time.sum.us': number;
}> &
ApmApplicationMetricFields;
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
* Side Public License, v 1.
*/

import { Fields } from './entity';
import { Serializable } from './serializable';
import { Serializable } from '../serializable';
import { Span } from './span';
import { Transaction } from './transaction';
import { generateLongId } from './utils/generate_id';
import { generateLongId } from '../utils/generate_id';
import { ApmFields } from './apm_fields';

export class BaseSpan extends Serializable {
export class BaseSpan extends Serializable<ApmFields> {
private readonly _children: BaseSpan[] = [];

constructor(fields: Fields) {
constructor(fields: ApmFields) {
super({
...fields,
'event.outcome': 'unknown',
Expand Down Expand Up @@ -60,7 +60,7 @@ export class BaseSpan extends Serializable {
return this;
}

serialize(): Fields[] {
serialize(): ApmFields[] {
return [this.fields, ...this._children.flatMap((child) => child.serialize())];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
* Side Public License, v 1.
*/

import { Entity, UserAgentFields } from './entity';
import { ApmFields, ApmUserAgentFields } from './apm_fields';
import { Entity } from '../entity';
import { RumSpan } from './rum_span';
import { RumTransaction } from './rum_transaction';

export class Browser extends Entity {
export class Browser extends Entity<ApmFields> {
transaction(transactionName: string, transactionType: string = 'page-load') {
return new RumTransaction({
...this.fields,
Expand All @@ -29,7 +30,7 @@ export class Browser extends Entity {
}
}

export function browser(serviceName: string, production: string, userAgent: UserAgentFields) {
export function browser(serviceName: string, production: string, userAgent: ApmUserAgentFields) {
return new Browser({
'agent.name': 'rum-js',
'service.name': serviceName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,52 @@
*/

import { Client } from '@elastic/elasticsearch';
import { uploadEvents } from '../../scripts/utils/upload_events';
import { Fields } from '../entity';
import { cleanWriteTargets } from '../utils/clean_write_targets';
import { uploadEvents } from '../../../scripts/utils/upload_events';
import { Fields } from '../../entity';
import { cleanWriteTargets } from '../../utils/clean_write_targets';
import { getBreakdownMetrics } from '../utils/get_breakdown_metrics';
import { getSpanDestinationMetrics } from '../utils/get_span_destination_metrics';
import { getTransactionMetrics } from '../utils/get_transaction_metrics';
import { getWriteTargets } from '../utils/get_write_targets';
import { Logger } from '../utils/logger';
import { getApmWriteTargets } from '../utils/get_apm_write_targets';
import { Logger } from '../../utils/create_logger';
import { apmEventsToElasticsearchOutput } from '../utils/apm_events_to_elasticsearch_output';

export class SynthtraceEsClient {
export class ApmSynthtraceEsClient {
constructor(private readonly client: Client, private readonly logger: Logger) {}

private getWriteTargets() {
return getWriteTargets({ client: this.client });
return getApmWriteTargets({ client: this.client });
}

clean() {
return this.getWriteTargets().then((writeTargets) =>
cleanWriteTargets({ client: this.client, writeTargets, logger: this.logger })
cleanWriteTargets({
client: this.client,
targets: Object.values(writeTargets),
logger: this.logger,
})
);
}

async index(events: Fields[]) {
const eventsToIndex = [
...events,
...getTransactionMetrics(events),
...getSpanDestinationMetrics(events),
...getBreakdownMetrics(events),
];

const writeTargets = await this.getWriteTargets();

const eventsToIndex = apmEventsToElasticsearchOutput({
events: [
...events,
...getTransactionMetrics(events),
...getSpanDestinationMetrics(events),
...getBreakdownMetrics(events),
],
writeTargets,
});

await uploadEvents({
batchSize: 1000,
client: this.client,
clientWorkers: 5,
events: eventsToIndex,
logger: this.logger,
writeTargets,
});

return this.client.indices.refresh({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* Side Public License, v 1.
*/

import { UserAgentFields } from '../entity';
import { ApmUserAgentFields } from '../../apm/apm_fields';

export function getChromeUserAgentDefaults(): UserAgentFields {
export function getChromeUserAgentDefaults(): ApmUserAgentFields {
return {
'user_agent.original':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* Side Public License, v 1.
*/

import { Fields } from '../entity';
import { ApmFields } from '../apm_fields';

export function getObserverDefaults(): Fields {
export function getObserverDefaults(): ApmFields {
return {
'observer.version': '7.16.0',
'observer.version_major': 7,
Expand Down
30 changes: 30 additions & 0 deletions packages/elastic-apm-synthtrace/src/lib/apm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 { service } from './service';
import { browser } from './browser';
import { getTransactionMetrics } from './utils/get_transaction_metrics';
import { getSpanDestinationMetrics } from './utils/get_span_destination_metrics';
import { getObserverDefaults } from './defaults/get_observer_defaults';
import { getChromeUserAgentDefaults } from './defaults/get_chrome_user_agent_defaults';
import { apmEventsToElasticsearchOutput } from './utils/apm_events_to_elasticsearch_output';
import { getBreakdownMetrics } from './utils/get_breakdown_metrics';
import { getApmWriteTargets } from './utils/get_apm_write_targets';
import { ApmSynthtraceEsClient } from './client/apm_synthtrace_es_client';

export const apm = {
service,
browser,
getTransactionMetrics,
getSpanDestinationMetrics,
getObserverDefaults,
getChromeUserAgentDefaults,
apmEventsToElasticsearchOutput,
getBreakdownMetrics,
getApmWriteTargets,
ApmSynthtraceEsClient,
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
*/

import { ApmError } from './apm_error';
import { ApplicationMetricFields, Entity } from './entity';
import { Entity } from '../entity';
import { Metricset } from './metricset';
import { Span } from './span';
import { Transaction } from './transaction';
import { ApmApplicationMetricFields, ApmFields } from './apm_fields';

export class Instance extends Entity {
export class Instance extends Entity<ApmFields> {
transaction(transactionName: string, transactionType = 'request') {
return new Transaction({
...this.fields,
Expand Down Expand Up @@ -43,7 +44,7 @@ export class Instance extends Entity {
return this;
}

appMetrics(metrics: ApplicationMetricFields) {
appMetrics(metrics: ApmApplicationMetricFields) {
return new Metricset({
...this.fields,
'metricset.name': 'app',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
* Side Public License, v 1.
*/

import { Fields } from './entity';
import { Serializable } from './serializable';
import { Serializable } from '../serializable';
import { ApmFields } from './apm_fields';

export class Metricset extends Serializable {
constructor(fields: Fields) {
export class Metricset extends Serializable<ApmFields> {
constructor(fields: ApmFields) {
super({
'processor.event': 'metric',
'processor.name': 'metric',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
* Side Public License, v 1.
*/

import { Entity } from './entity';
import { Entity } from '../entity';
import { ApmFields } from './apm_fields';
import { Instance } from './instance';

export class Service extends Entity {
export class Service extends Entity<ApmFields> {
instance(instanceName: string) {
return new Instance({
...this.fields,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
*/

import { BaseSpan } from './base_span';
import { Fields } from './entity';
import { generateShortId } from './utils/generate_id';
import { generateShortId } from '../utils/generate_id';
import { ApmFields } from './apm_fields';

export class Span extends BaseSpan {
constructor(fields: Fields) {
constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'span',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

import { ApmError } from './apm_error';
import { BaseSpan } from './base_span';
import { Fields } from './entity';
import { generateShortId } from './utils/generate_id';
import { generateShortId } from '../utils/generate_id';
import { ApmFields } from './apm_fields';

export class Transaction extends BaseSpan {
private _sampled: boolean = true;
private readonly _errors: ApmError[] = [];

constructor(fields: Fields) {
constructor(fields: ApmFields) {
super({
...fields,
'processor.event': 'transaction',
Expand Down
Loading