[APM][OTel] Add EDOT support in the Synthtrace OTel client (#214141)

Closes #212564 

## Summary

This PR adds EDOT data and scenarios to the OTel synthtrace client. The
previous OTel class now lives in `otel_native` folder and the EDOT one
in `otel_edot`. It updates the otel native service name and the old
tests and adds a simple test for EDOT.
⚠️ Currently the edot service doesn't have an error document (on the
[otel demo env](https://otel.demo.elastic.co) I couldn't find any) so
there won't be any errors for the `adservice-edot-synth` - same as in
[the
demo](https://otel.demo.elastic.co/app/apm/services/adservice/errors?comparisonEnabled=true&environment=ENVIRONMENT_ALL&kuery=&latencyAggregationType=avg&offset=1d&rangeFrom=2025-03-12T12:49:15.506Z&rangeTo=2025-03-12T13:04:19.779Z&serviceGroup=&transactionType=request)

## Testing
Run: 
- ```node scripts/synthtrace otel_edot_simple_trace.ts ```
- and ```node scripts/synthtrace otel_simple_trace.ts```

Go to APM service inventory
- Both services should be visible
  

![image](https://github.com/user-attachments/assets/b698cc14-d40a-4925-861f-4da0d9707f48)

- Service overview and other tabs should be visible 
  - Otel native case: 
  

![image](https://github.com/user-attachments/assets/4c423ff0-2dee-4eb4-b69b-057bad3a4747)

![image](https://github.com/user-attachments/assets/407907bd-212e-486e-bc2a-0e2370f21be5)

  - EDOT case
 

![image](https://github.com/user-attachments/assets/3766e1e2-a8d7-45d4-887d-b67533a1b3eb)

![image](https://github.com/user-attachments/assets/aff544fa-72b5-4826-963f-2b4c44d517bb)
This commit is contained in:
jennypavlova 2025-03-12 16:50:51 +01:00 committed by GitHub
parent ad3b7fce11
commit ded1b15b87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 664 additions and 30 deletions

View file

@ -36,5 +36,6 @@ export { appendHash, hashKeysOf } from './src/lib/utils/hash';
export type { ESDocumentWithOperation, SynthtraceESAction, SynthtraceGenerator } from './src/types';
export { log, type LogDocument, LONG_FIELD_NAME } from './src/lib/logs';
export { syntheticsMonitor, type SyntheticsMonitorDocument } from './src/lib/synthetics';
export { otel, type OtelDocument } from './src/lib/otel';
export { otel, type OtelDocument } from './src/lib/otel/otel_native';
export { otelEdot, type OtelEdotDocument } from './src/lib/otel/otel_edot';
export { type EntityFields, entities } from './src/lib/entities';

View file

@ -0,0 +1,251 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { Fields } from '../../entity';
import { Serializable } from '../../serializable';
import { OtelEdotMetric } from './metric';
import { OtelEdotTransaction } from './transaction';
interface OtelEdotSharedResourceAttributes {
'service.name'?: string;
'agent.name'?: string;
'agent.version'?: string;
'metricset.interval'?: string;
'service.instance.id'?: string;
'telemetry.sdk.language'?: string;
'telemetry.sdk.name'?: string;
'telemetry.sdk.version'?: string;
}
export interface OtelEdotDocument extends Fields {
data_stream?: {
dataset: string;
namespace: string;
type: string;
};
attributes?: {
'timestamp.us'?: number;
'metricset.name'?: string;
[key: string]: any;
};
resource?: {
attributes?: OtelEdotSharedResourceAttributes;
dropped_attributes_count?: number;
schema_url?: string;
};
scope?: {
attributes?: {
'service.framework.name'?: string;
'service.framework.version'?: string;
};
dropped_attributes_count?: number;
name?: string;
};
name?: string;
trace_id?: string;
trace?: { id: string };
span_id?: string;
span?: { id: string };
dropped_attributes_count?: number;
dropped_events_count?: number;
dropped_links_count?: number;
timestamp_us?: number;
}
class OtelEdot extends Serializable<OtelEdotDocument> {
constructor(fields: OtelEdotDocument) {
super({
...fields,
});
}
metric() {
return new OtelEdotMetric({
...this.fields,
attributes: {
'service.name': 'adservice-edot-synth',
'span.kind': 'SPAN_KIND_INTERNAL',
'span.name': 'SynchronizationContext#drain',
'status.code': 'STATUS_CODE_UNSET',
'metricset.name': 'service_summary',
'processor.event': 'metric',
},
data_stream: {
dataset: 'generic.otel',
namespace: 'default',
type: 'metrics',
},
metrics: {
'traces.span.metrics.calls': 1,
},
resource: {
attributes: {
'agent.name': 'opentelemetry/java/elastic',
'agent.version': '1.0.1-SNAPSHOT',
'app.label.name': 'otel-demo-blue-adservice-edot-synth',
'cloud.account.id': 'elastic-product',
'cloud.availability_zone': 'us-central1-a',
'cloud.platform': 'gcp_kubernetes_engine',
'cloud.provider': 'gcp',
'container.id': 'e4f5dd426472aacd6124e85a0cd8a1ef55c263374c16179d1bf75292224c2dc0',
'deployment.environment': 'opentelemetry-demo',
'host.arch': 'amd64',
'host.id': '8645892066193866279',
'host.name': 'gke-demo-elastic-co-pool-5-29a9d3db-t79s',
'k8s.cluster.name': 'demo-elastic-co',
'k8s.deployment.name': 'otel-demo-blue-adservice-edot-synth',
'k8s.namespace.name': 'otel-blue',
'k8s.node.name': 'gke-demo-elastic-co-pool-5-29a9d3db-t79s',
'k8s.pod.ip': '10.12.3.63',
'k8s.pod.name': 'otel-demo-blue-adservice-edot-synth-7c68c8f968-tvf54',
'k8s.pod.start_time': '2025-01-15T12:51:39Z',
'k8s.pod.uid': 'da7a8507-53be-421c-8d77-984f12397213',
'k8s.replicaset.name': 'otel-demo-blue-adservice-edot-synth-7c68c8f968',
'os.description': 'Linux 5.15.109+',
'os.type': 'linux',
'process.command_line':
'/opt/java/openjdk/bin/java -javaagent:/usr/src/app/opentelemetry-javaagent.jar oteldemo.AdServiceEdotSynth',
'process.executable.path': '/opt/java/openjdk/bin/java',
'process.pid': 1,
'process.runtime.description': 'Eclipse Adoptium OpenJDK 64-Bit Server VM 21.0.5+11-LTS',
'process.runtime.name': 'OpenJDK Runtime Environment',
'process.runtime.version': '21.0.5+11-LTS',
'service.instance.id': 'da7a8507-53be-421c-8d77-984f12397213',
'service.name': 'adservice-edot-synth',
'service.namespace': 'opentelemetry-demo',
'telemetry.distro.name': 'elastic',
'telemetry.distro.version': '1.0.1-SNAPSHOT',
'telemetry.sdk.language': 'java',
'telemetry.sdk.name': 'opentelemetry',
'telemetry.sdk.version': '1.43.0',
},
},
scope: {
dropped_attributes_count: 0,
name: 'spanmetricsconnector',
},
});
}
transaction(id: string) {
return new OtelEdotTransaction({
...this.fields,
attributes: {
'app.ads.ad_request_type': 'TARGETED',
'app.ads.ad_response_type': 'TARGETED',
'app.ads.contextKeys': '[travel]',
'app.ads.contextKeys.count': 1,
'app.ads.count': 1,
'event.outcome': 'success',
'event.success_count': 1,
'network.peer.address': '10.12.9.56',
'network.peer.port': 41208,
'network.type': 'ipv4',
'processor.event': 'transaction',
'rpc.grpc.status_code': 0,
'rpc.method': 'GetAds',
'rpc.service': 'oteldemo.AdServiceEdotSynth',
'rpc.system': 'grpc',
'server.address': 'otel-demo-blue-adservice-edot-synth',
'server.port': 8080,
'session.id': 'ce3ed7c7-47d7-42a5-baae-86d0a716752d',
'thread.id': 9412,
'thread.name': 'grpc-default-executor-23',
'timestamp.us': 1740679709260508,
'transaction.duration.us': 551,
'transaction.id': id,
'transaction.name': 'oteldemo.AdServiceEdotSynth/GetAds',
'transaction.representative_count': 1,
'transaction.result': 'OK',
'transaction.root': false,
'transaction.sampled': true,
'transaction.type': 'request',
},
data_stream: {
dataset: 'generic.otel',
namespace: 'default',
type: 'traces',
},
duration: 551551,
kind: 'Server',
name: 'oteldemo.AdServiceEdotSynth/GetAds',
// parent_span_id: 'b8fc0a55e4ae6b53',
resource: {
attributes: {
'agent.name': 'opentelemetry/java/elastic',
'agent.version': '1.0.1-SNAPSHOT',
'app.label.name': 'otel-demo-blue-adservice-edot-synth',
'cloud.account.id': 'elastic-product',
'cloud.availability_zone': 'us-central1-a',
'cloud.platform': 'gcp_kubernetes_engine',
'cloud.provider': 'gcp',
'container.id': 'e4f5dd426472aacd6124e85a0cd8a1ef55c263374c16179d1bf75292224c2dc0',
'deployment.environment': 'opentelemetry-demo',
'host.arch': 'amd64',
'host.id': '8645892066193866279',
'host.name': 'gke-demo-elastic-co-pool-5-29a9d3db-t79s',
'k8s.cluster.name': 'demo-elastic-co',
'k8s.deployment.name': 'otel-demo-blue-adservice-edot-synth',
'k8s.namespace.name': 'otel-blue',
'k8s.node.name': 'gke-demo-elastic-co-pool-5-29a9d3db-t79s',
'k8s.pod.ip': '10.12.3.63',
'k8s.pod.name': 'otel-demo-blue-adservice-edot-synth-7c68c8f968-tvf54',
'k8s.pod.start_time': '2025-01-15T12:51:39Z',
'k8s.pod.uid': 'da7a8507-53be-421c-8d77-984f12397213',
'k8s.replicaset.name': 'otel-demo-blue-adservice-edot-synth-7c68c8f968',
'os.description': 'Linux 5.15.109+',
'os.type': 'linux',
'process.command_line':
'/opt/java/openjdk/bin/java -javaagent:/usr/src/app/opentelemetry-javaagent.jar oteldemo.AdServiceEdotSynth',
'process.executable.path': '/opt/java/openjdk/bin/java',
'process.pid': 1,
'process.runtime.description': 'Eclipse Adoptium OpenJDK 64-Bit Server VM 21.0.5+11-LTS',
'process.runtime.name': 'OpenJDK Runtime Environment',
'process.runtime.version': '21.0.5+11-LTS',
'service.instance.id': 'da7a8507-53be-421c-8d77-984f12397213',
'service.name': 'adservice-edot-synth',
'service.namespace': 'opentelemetry-demo',
'telemetry.distro.name': 'elastic',
'telemetry.distro.version': '1.0.1-SNAPSHOT',
'telemetry.sdk.language': 'java',
'telemetry.sdk.name': 'opentelemetry',
'telemetry.sdk.version': '1.43.0',
},
// schema_url: 'https://opentelemetry.io/schemas/1.24.0',
},
scope: {
attributes: {
'service.framework.name': 'io.opentelemetry.grpc-1.6',
'service.framework.version': '2.9.0-alpha',
},
dropped_attributes_count: 0,
name: 'io.opentelemetry.grpc-1.6',
// version: '2.9.0-alpha',
},
span_id: '8884909eca61b9d5',
status: {
code: 'Unset',
},
trace_id: '70219abfdc4f0e17ca0975a339c2c135',
});
}
}
export function create(id: string): OtelEdot {
return new OtelEdot({
trace_id: id,
dropped_attributes_count: 0,
dropped_events_count: 0,
dropped_links_count: 0,
});
}
export const otelEdot = {
create,
};

View file

@ -0,0 +1,77 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { OtelEdotDocument } from '.';
import { Serializable } from '../../serializable';
export interface OtelEdotMetricDocument extends OtelEdotDocument {
attributes?: {
'metricset.name'?: string;
'processor.event'?: string;
'event.outcome'?: string;
'service.name'?: string;
'span.name'?: string;
'span.kind'?: string;
'status.code'?: string;
'span.destination.service.resource'?: string;
};
metrics?: {
service_summary?: number;
'traces.span.metrics.calls'?: number;
};
resource?: {
attributes?: {
'agent.name'?: string;
'agent.version'?: string;
'app.label.name'?: string;
'cloud.account.id'?: string;
'cloud.availability_zone'?: string;
'cloud.platform'?: string;
'cloud.provider'?: string;
'container.id'?: string;
'deployment.environment'?: string;
'host.arch'?: string;
'host.id'?: string;
'host.name'?: string;
'k8s.cluster.name'?: string;
'k8s.deployment.name'?: string;
'k8s.namespace.name'?: string;
'k8s.node.name'?: string;
'k8s.pod.ip'?: string;
'k8s.pod.name'?: string;
'k8s.pod.uid'?: string;
'k8s.replicaset.name'?: string;
'k8s.pod.start_time'?: string;
'os.description'?: string;
'os.type'?: string;
'process.command_args'?: string;
'process.command_line'?: string;
'process.executable.path'?: string;
'process.pid'?: number;
'process.runtime.description'?: string;
'process.runtime.name'?: string;
'process.runtime.version'?: string;
'service.instance.id'?: string;
'service.name'?: string;
'service.namespace'?: string;
'telemetry.distro.name'?: string;
'telemetry.distro.version'?: string;
'telemetry.sdk.language'?: string;
'telemetry.sdk.name'?: string;
'telemetry.sdk.version'?: string;
};
};
}
export class OtelEdotMetric extends Serializable<OtelEdotMetricDocument> {
constructor(fields: OtelEdotMetricDocument) {
super({
...fields,
});
}
}

View file

@ -0,0 +1,113 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { OtelEdotDocument } from '.';
import { Serializable } from '../../serializable';
export interface OtelEdotTransactionDocument extends OtelEdotDocument {
attributes?: {
'event.outcome'?: string;
'event.success_count'?: number;
'processor.event'?: string;
'timestamp.us'?: number;
'transaction.duration.us'?: number;
'transaction.id'?: string;
'transaction.name'?: string;
'transaction.representative_count'?: number;
'transaction.result'?: string;
'transaction.root'?: boolean;
'transaction.sampled'?: boolean;
'transaction.type'?: string;
'http.response.status_code'?: number;
'http.request.method'?: string;
'url.full'?: string;
'service.name'?: string;
'service.namespace'?: string;
'service.instance.id'?: string;
'service.target.name'?: string;
'service.target.type'?: string;
'span.name'?: string;
'span.destination.service.resource'?: string;
'app.ads.ad_request_type'?: string;
'app.ads.ad_response_type'?: string;
'app.ads.contextKeys'?: string;
'app.ads.contextKeys.count'?: number;
'app.ads.count'?: number;
'network.peer.address'?: string;
'network.peer.port'?: number;
'network.type'?: string;
'rpc.grpc.status_code'?: number;
'rpc.method'?: string;
'rpc.service'?: string;
'rpc.system'?: string;
'server.address'?: string;
'server.port'?: number;
'session.id'?: string;
'thread.id'?: number;
'thread.name'?: string;
};
status?: {
code?: string;
};
dropped_events_count?: number;
dropped_links_count?: number;
duration?: number;
kind?: string;
name?: string;
resource?: {
attributes?: {
'agent.name'?: string;
'agent.version'?: string;
'app.label.name'?: string;
'cloud.account.id'?: string;
'cloud.availability_zone'?: string;
'cloud.platform'?: string;
'cloud.provider'?: string;
'container.id'?: string;
'deployment.environment'?: string;
'host.arch'?: string;
'host.id'?: string;
'host.name'?: string;
'k8s.cluster.name'?: string;
'k8s.deployment.name'?: string;
'k8s.namespace.name'?: string;
'k8s.node.name'?: string;
'k8s.pod.ip'?: string;
'k8s.pod.name'?: string;
'k8s.pod.uid'?: string;
'k8s.pod.start_time'?: string;
'k8s.replicaset.name'?: string;
'os.description'?: string;
'os.type'?: string;
'process.command_args'?: string;
'process.command_line'?: string;
'process.executable.path'?: string;
'process.pid'?: number;
'process.runtime.description'?: string;
'process.runtime.name'?: string;
'process.runtime.version'?: string;
'service.instance.id'?: string;
'service.name'?: string;
'service.namespace'?: string;
'telemetry.distro.name'?: string;
'telemetry.distro.version'?: string;
'telemetry.sdk.language'?: string;
'telemetry.sdk.name'?: string;
'telemetry.sdk.version'?: string;
};
};
}
export class OtelEdotTransaction extends Serializable<OtelEdotTransactionDocument> {
constructor(fields: OtelEdotTransactionDocument) {
super({
...fields,
});
}
}

View file

@ -7,8 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import type { OtelDocument } from '../../..';
import { Serializable } from '../serializable';
import type { OtelDocument } from '../../../..';
import { Serializable } from '../../serializable';
export interface OtelErrorDocument extends OtelDocument {
'event.name'?: string;

View file

@ -7,8 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { Fields } from '../entity';
import { Serializable } from '../serializable';
import type { Fields } from '../../entity';
import { Serializable } from '../../serializable';
import { OtelError } from './error';
import { OtelMetric } from './metric';
import { OtelTransaction } from './transaction';
@ -91,7 +91,7 @@ class Otel extends Serializable<OtelDocument> {
attributes: {
'agent.name': 'opentelemetry/go',
'agent.version': '1.28.0',
'service.name': 'sendotlp-synth',
'service.name': 'sendotlp-otel-native-synth',
'service.instance.id': '89117ac1-0dbf-4488-9e17-4c2c3b76943a',
},
dropped_attributes_count: 0,
@ -99,11 +99,11 @@ class Otel extends Serializable<OtelDocument> {
},
scope: {
attributes: {
'service.framework.name': 'sendotlp-synth',
'service.framework.name': 'sendotlp-otel-native-synth',
'service.framework.version': '',
},
dropped_attributes_count: 0,
name: 'sendotlp-synth',
name: 'sendotlp-otel-native-synth',
},
span_id: spanId,
});
@ -116,10 +116,10 @@ class Otel extends Serializable<OtelDocument> {
'metricset.name': 'service_destination',
'processor.event': 'metric',
'event.outcome': 'success',
'service.target.name': 'foo_service',
'service.target.name': 'foo_service-otel-native-synth',
'service.target.type': 'http',
'span.name': 'child1',
'span.destination.service.resource': 'foo_service:8080',
'span.destination.service.resource': 'foo_service-otel-native-synth:8080',
},
data_stream: {
dataset: 'service_destination.10m.otel',
@ -134,7 +134,7 @@ class Otel extends Serializable<OtelDocument> {
'agent.name': 'opentelemetry/nodejs',
'agent.version': '1.28.0',
'service.instance.id': '89117ac1-0dbf-4488-9e17-4c2c3b76943a',
'service.name': 'sendotlp-synth',
'service.name': 'sendotlp-otel-native-synth',
'metricset.interval': '10m',
'telemetry.sdk.name': 'opentelemetry',
'telemetry.sdk.language': 'nodejs',
@ -183,18 +183,18 @@ class Otel extends Serializable<OtelDocument> {
'agent.name': 'otlp',
'agent.version': '1.28.0',
'service.instance.id': '89117ac1-0dbf-4488-9e17-4c2c3b76943a',
'service.name': 'sendotlp-synth',
'service.name': 'sendotlp-otel-native-synth',
},
dropped_attributes_count: 0,
schema_url: 'https://opentelemetry.io/schemas/1.26.0',
},
scope: {
attributes: {
'service.framework.name': 'sendotlp-synth',
'service.framework.name': 'sendotlp-otel-native-synth',
'service.framework.version': '',
},
dropped_attributes_count: 0,
name: 'sendotlp-synth',
name: 'sendotlp-otel-native-synth',
},
span_id: id,
status: {

View file

@ -8,7 +8,7 @@
*/
import { OtelDocument } from '.';
import { Serializable } from '../serializable';
import { Serializable } from '../../serializable';
export interface OtelMetricDocument extends OtelDocument {
attributes?: {

View file

@ -8,7 +8,7 @@
*/
import { OtelDocument } from '.';
import { Serializable } from '../serializable';
import { Serializable } from '../../serializable';
export interface OtelTransactionDocument extends OtelDocument {
attributes?: {

View file

@ -0,0 +1,47 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { generateShortId, OtelEdotDocument, otelEdot } from '@kbn/apm-synthtrace-client';
import { times } from 'lodash';
import { Scenario } from '../cli/scenario';
import { withClient } from '../lib/utils/with_client';
const scenario: Scenario<OtelEdotDocument> = async (runOptions) => {
return {
generate: ({ range, clients: { otelEsClient } }) => {
const { numOtelTraces = 5 } = runOptions.scenarioOpts || {};
const { logger } = runOptions;
const traceId = generateShortId();
const spanId = generateShortId();
const otelEdotDocs = times(numOtelTraces / 2).map((index) => otelEdot.create(traceId));
const otelWithMetricsAndErrors = range
.interval('30s')
.rate(1)
.generator((timestamp) =>
otelEdotDocs.flatMap((otelEdotd) => {
return [
otelEdotd.metric().timestamp(timestamp),
otelEdotd.transaction(spanId).timestamp(timestamp),
];
})
);
return [
withClient(
otelEsClient,
logger.perf('generating_otel_trace', () => otelWithMetricsAndErrors)
),
];
},
};
};
export default scenario;

View file

@ -0,0 +1,115 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import url from 'url';
import { synthtraceOtel } from '../../../synthtrace';
import { adserviceEdot } from '../../fixtures/synthtrace/adservice_edot';
import { checkA11y } from '../../support/commands';
const start = '2021-10-10T00:00:00.000Z';
const end = '2021-10-10T00:15:00.000Z';
const serviceInstanceId = 'da7a8507-53be-421c-8d77-984f12397213';
const serviceOverviewPath = '/app/apm/services/adservice-edot-synth/overview';
const baseUrl = url.format({
pathname: serviceOverviewPath,
query: { rangeFrom: start, rangeTo: end },
});
describe('Service Overview', () => {
before(() => {
synthtraceOtel.index(
adserviceEdot({
from: new Date(start).getTime(),
to: new Date(end).getTime(),
})
);
});
after(() => {
synthtraceOtel.clean();
});
describe('renders', () => {
beforeEach(() => {
cy.loginAsViewerUser();
cy.visitKibana(baseUrl);
});
it('renders all components on the page', () => {
cy.contains('adservice-edot-synth');
// set skipFailures to true to not fail the test when there are accessibility failures
checkA11y({ skipFailures: true });
cy.getByTestSubj('latencyChart');
cy.getByTestSubj('throughput');
cy.getByTestSubj('transactionsGroupTable');
cy.getByTestSubj('serviceOverviewErrorsTable');
cy.getByTestSubj('dependenciesTable');
cy.getByTestSubj('instancesLatencyDistribution');
cy.getByTestSubj('serviceOverviewInstancesTable');
});
});
describe('service icons', () => {
beforeEach(() => {
cy.loginAsViewerUser();
});
it('show information on click', () => {
cy.intercept('GET', '/internal/apm/services/adservice-edot-synth/metadata/details?*').as(
'metadataDetailsRequest'
);
cy.visitKibana(baseUrl);
cy.getByTestSubj('opentelemetry').click();
cy.wait('@metadataDetailsRequest');
cy.contains('dt', 'Language');
cy.contains('dd', 'java');
});
});
describe('instances table', () => {
beforeEach(() => {
cy.loginAsViewerUser();
});
it('has data in the table', () => {
cy.visitKibana(baseUrl);
cy.contains('adservice-edot-synth');
cy.getByTestSubj('serviceInstancesTableContainer');
cy.contains(serviceInstanceId);
});
});
describe('transactions', () => {
beforeEach(() => {
cy.loginAsViewerUser();
});
it('navigates to transaction detail page', () => {
cy.visitKibana(baseUrl);
cy.contains('Transactions').click();
cy.contains('a', 'oteldemo.AdServiceEdotSynth/GetAds').click();
cy.contains('h5', 'oteldemo.AdServiceEdotSynth/GetAds');
});
});
describe('errors', () => {
beforeEach(() => {
cy.loginAsViewerUser();
cy.visitKibana(baseUrl);
});
it('navigates to the errors page', () => {
cy.contains('adservice-edot-synth');
cy.contains('a', 'View errors').click();
cy.url().should('include', '/adservice-edot-synth/errors');
});
});
});

View file

@ -14,13 +14,13 @@ const start = '2021-10-10T00:00:00.000Z';
const end = '2021-10-10T00:15:00.000Z';
const serviceInstanceId = '89117ac1-0dbf-4488-9e17-4c2c3b76943a';
const serviceOverviewPath = '/app/apm/services/sendotlp-synth/overview';
const serviceOverviewPath = '/app/apm/services/sendotlp-otel-native-synth/overview';
const baseUrl = url.format({
pathname: serviceOverviewPath,
query: { rangeFrom: start, rangeTo: end },
});
const transactionTabPath = '/app/apm/services/sendotlp-synth/transactions/view';
const transactionTabPath = '/app/apm/services/sendotlp-otel-native-synth/transactions/view';
const transactionUrl = url.format({
pathname: transactionTabPath,
query: { rangeFrom: start, rangeTo: end, transactionName: 'parent-synth' },
@ -47,7 +47,7 @@ describe('Service Overview', () => {
});
it('renders all components on the page', () => {
cy.contains('sendotlp-synth');
cy.contains('sendotlp-otel-native-synth');
// set skipFailures to true to not fail the test when there are accessibility failures
checkA11y({ skipFailures: true });
cy.getByTestSubj('latencyChart');
@ -66,16 +66,17 @@ describe('Service Overview', () => {
});
it('show information on click', () => {
cy.intercept('GET', '/internal/apm/services/sendotlp-synth/metadata/details?*').as(
'metadataDetailsRequest'
);
cy.intercept(
'GET',
'/internal/apm/services/sendotlp-otel-native-synth/metadata/details?*'
).as('metadataDetailsRequest');
cy.visitKibana(baseUrl);
cy.getByTestSubj('service').click();
cy.wait('@metadataDetailsRequest');
cy.contains('dt', 'Framework name');
cy.contains('dd', 'sendotlp-synth');
cy.contains('dd', 'sendotlp-otel-native-synth');
cy.getByTestSubj('opentelemetry').click();
cy.contains('dt', 'Language');
@ -90,7 +91,7 @@ describe('Service Overview', () => {
it('has data in the table', () => {
cy.visitKibana(baseUrl);
cy.contains('sendotlp-synth');
cy.contains('sendotlp-otel-native-synth');
cy.getByTestSubj('serviceInstancesTableContainer');
cy.contains(serviceInstanceId);
});
@ -102,9 +103,10 @@ describe('Service Overview', () => {
});
it('persists transaction type selected when clicking on Transactions tab', () => {
cy.intercept('GET', '/internal/apm/services/sendotlp-synth/transaction_types?*').as(
'transactionTypesRequest'
);
cy.intercept(
'GET',
'/internal/apm/services/sendotlp-otel-native-synth/transaction_types?*'
).as('transactionTypesRequest');
cy.visitKibana(baseUrl);
@ -138,14 +140,14 @@ describe('Service Overview', () => {
cy.visitKibana(baseUrl);
});
it('errors table is populated', () => {
cy.contains('sendotlp-synth');
cy.contains('sendotlp-otel-native-synth');
cy.contains('*errors.errorString');
});
it('navigates to the errors page', () => {
cy.contains('sendotlp-synth');
cy.contains('sendotlp-otel-native-synth');
cy.contains('a', 'View errors').click();
cy.url().should('include', '/sendotlp-synth/errors');
cy.url().should('include', '/sendotlp-otel-native-synth/errors');
});
it('navigates to error detail page', () => {

View file

@ -0,0 +1,28 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { generateShortId, otelEdot, timerange } from '@kbn/apm-synthtrace-client';
import { times } from 'lodash';
export function adserviceEdot({ from, to }: { from: number; to: number }) {
const range = timerange(from, to);
const traceId = generateShortId();
const spanId = generateShortId();
const otelAdserviceEdot = times(2).map((index) => otelEdot.create(traceId));
return range
.interval('1s')
.rate(1)
.generator((timestamp) =>
otelAdserviceEdot.flatMap((otelDoc) => {
return [
otelDoc.metric().timestamp(timestamp),
otelDoc.transaction(spanId).timestamp(timestamp),
];
})
);
}