Skip to content

Commit da1adac

Browse files
flash1293cursoragentkibanamachineclaude
authored
Decentralize synthtrace scenarios: colocate with plugin code (#270157)
## Summary Implements Phase 1 and Phase 2 of #259332. ### Phase 1 — Enable colocated scenarios (non-breaking) - Removes the `choices` restriction from `run_synthtrace.ts` so the CLI accepts any file path (absolute or relative), not just built-in scenario names - Exports `Scenario`, `ScenarioInitOptions`, `RunOptions`, `getSynthtraceEnvironment`, `ComponentTemplateName`, `IndexTemplateName`, `timestampDateMapping`, and `withClient` from the `@kbn/synthtrace` public API, so plugins can define colocated scenarios without importing from internal paths ### Phase 2 — Move scenarios to their respective plugins | Destination | Scenarios moved | |---|---| | `x-pack/solutions/observability/plugins/apm/test/scenarios/` | ~40 APM scenarios (traces, services, metrics, OTel, mobile, Lambda, etc.) + APM-specific helpers | | `x-pack/solutions/observability/plugins/infra/test/scenarios/` | 6 infra scenarios (`infra_aws_rds`, `infra_docker_containers`, `infra_hosts_ecs`, `infra_hosts_semconv`, `infra_k8s_containers`, `infra_k8s_pods`) | | `x-pack/solutions/observability/plugins/synthetics/test/scenarios/` | `degraded_synthetics_monitors` | | `x-pack/platform/plugins/shared/streams/test/scenarios/` | 14 logs/HTTP scenarios + logs/HTTP helpers | | Kept in `@kbn/synthtrace` | 7 multi-domain cross-cutting scenarios (`logs_and_metrics*`, `logs_traces_hosts`, `kubernetes_logs_traces_pods`, `infra_hosts_*_with_apm_hosts`, `distributed_unstructured_logs`) + `sre_incidents/` + `sigevents/` subdirs | Each destination plugin's `tsconfig.json` is updated to include `test/scenarios/**/*` and add `@kbn/synthtrace` to `kbn_references`. An `.eslintrc.js` disabling `import/no-default-export` is added to each scenarios directory to allow the `export default` pattern required by the `Scenario` type. ### Usage after this PR ```bash # Colocated scenario by path node scripts/synthtrace.js ./x-pack/solutions/observability/plugins/apm/test/scenarios/distributed_trace.ts # Built-in scenario name still works (backward compatible) node scripts/synthtrace.js simple_trace ``` ## Test plan - [ ] `node scripts/check_changes.ts` passes - [ ] Type check passes for `@kbn/synthtrace`, `apm`, `infra`, `synthetics`, and `streams` packages - [ ] `node scripts/synthtrace.js simple_trace` still works (backward compat) - [ ] `node scripts/synthtrace.js ./x-pack/solutions/observability/plugins/apm/test/scenarios/distributed_trace.ts` works with a colocated path Closes #259332 Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4da84e4 commit da1adac

104 files changed

Lines changed: 1306 additions & 946 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/platform/packages/shared/kbn-synthtrace/EXAMPLES.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,21 @@ const esEvents = toElasticsearchOutput([
9393
For live data ingestion:
9494

9595
```sh
96-
node scripts/synthtrace simple_trace.ts --target=http://admin:changeme@localhost:9200 --live
96+
node scripts/synthtrace simple_trace --target=http://admin:changeme@localhost:9200 --live
9797
```
9898

9999
For a fixed time window:
100100

101101
```sh
102-
node scripts/synthtrace simple_trace.ts --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now
102+
node scripts/synthtrace simple_trace --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now
103103
```
104104

105105
### Local Development
106106

107107
When running the CLI locally, you can simply use the following command to ingest data to a locally running Elasticsearch and Kibana instance:
108108

109109
```sh
110-
node scripts/synthtrace simple_trace.ts
110+
node scripts/synthtrace simple_trace
111111
```
112112

113113
_Assuming both Elasticsearch and Kibana are running on the default localhost ports with default credentials._
@@ -119,23 +119,23 @@ If the Kibana URL differs from the Elasticsearch URL in protocol or hostname, yo
119119
For example when running ES (with ssl) and Kibana (without ssl) locally in Serverless mode:
120120

121121
```sh
122-
node scripts/synthtrace simple_trace.ts --target=https://elastic_serverless:changeme@localhost:9200 --kibana=http://elastic_serverless:changeme@localhost:5601
122+
node scripts/synthtrace simple_trace --target=https://elastic_serverless:changeme@localhost:9200 --kibana=http://elastic_serverless:changeme@localhost:5601
123123
```
124124

125125
### Using CLI for Elastic Cloud URLs
126126

127127
If you are ingesting data to Elastic Cloud, you can pass the `--target` option with the Elastic Cloud URL:
128128

129129
```sh
130-
node scripts/synthtrace simple_trace.ts --target=https://<username>:<password>@your-cloud-cluster.kb.us-west2.gcp.elastic-cloud.com/
130+
node scripts/synthtrace simple_trace --target=https://<username>:<password>@your-cloud-cluster.kb.us-west2.gcp.elastic-cloud.com/
131131
```
132132

133133
### Using CLI with an API key
134134

135135
You can use a Kibana API key for authentication by passing the `--apiKey` option:
136136

137137
```sh
138-
node scripts/synthtrace simple_trace.ts --target=https://my-deployment.es.us-central1.gcp.elastic.cloud --apiKey="your-api-key"
138+
node scripts/synthtrace simple_trace --target=https://my-deployment.es.us-central1.gcp.elastic.cloud --apiKey="your-api-key"
139139
```
140140

141141
## Scenario Examples

src/platform/packages/shared/kbn-synthtrace/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@ Via the CLI, you can run scenarios, either using a fixed time range or continuou
115115
For live data ingestion:
116116

117117
```sh
118-
node scripts/synthtrace simple_trace.ts --target=http://admin:changeme@localhost:9200 --live
118+
node scripts/synthtrace simple_trace --target=http://admin:changeme@localhost:9200 --live
119119
```
120120

121121
For a fixed time window:
122122

123123
```sh
124-
node scripts/synthtrace simple_trace.ts --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now
124+
node scripts/synthtrace simple_trace --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now
125125
```
126126

127127
The script will try to automatically find bootstrapped APM indices. **If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.**
@@ -131,7 +131,7 @@ The script will try to automatically find bootstrapped APM indices. **If these i
131131
When running the CLI locally, you can simply use the following command to ingest data to a locally running Elasticsearch and Kibana instance:
132132

133133
```sh
134-
node scripts/synthtrace simple_trace.ts
134+
node scripts/synthtrace simple_trace
135135
```
136136

137137
_Assuming both Elasticsearch and Kibana are running on the default localhost ports with default credentials._
@@ -144,7 +144,7 @@ For example when running ES (with ssl) and Kibana (without ssl) locally in Serve
144144
Also use `localhost` instead of `127.0.0.1` as the hostname as `127.0.0.1` will likely not work with self-signed certificates.
145145

146146
```sh
147-
node scripts/synthtrace simple_trace.ts --target=https://elastic_serverless:changeme@localhost:9200 --kibana=http://elastic_serverless:changeme@localhost:5601
147+
node scripts/synthtrace simple_trace --target=https://elastic_serverless:changeme@localhost:9200 --kibana=http://elastic_serverless:changeme@localhost:5601
148148
```
149149

150150
#### Using CLI for Elastic Cloud URLs
@@ -153,15 +153,15 @@ If you are ingesting data to Elastic Cloud, you can pass the `--target` option w
153153
Or you can pass only `--kibana` and the CLI will infer the Elasticsearch URL from the Kibana URL. Or pass both if URLs are not in default scheme.
154154

155155
```sh
156-
node scripts/synthtrace simple_trace.ts --target=https://<username>:<password>@your-cloud-cluster.kb.us-west2.gcp.elastic-cloud.com/
156+
node scripts/synthtrace simple_trace --target=https://<username>:<password>@your-cloud-cluster.kb.us-west2.gcp.elastic-cloud.com/
157157
```
158158

159159
#### Using CLI with an API key
160160

161161
You can use a Kibana API key for authentication by passing the `--apiKey` option. When the `--apiKey` is provided, it will be used for authentication with both Elasticsearch and Kibana, taking precedence over other types of authentication.
162162

163163
```sh
164-
node scripts/synthtrace simple_trace.ts --target=https://my-deployment.es.us-central1.gcp.elastic.cloud --apiKey="your-api-key"
164+
node scripts/synthtrace simple_trace --target=https://my-deployment.es.us-central1.gcp.elastic.cloud --apiKey="your-api-key"
165165
```
166166

167167
For more CLI examples, see [Examples](./EXAMPLES.md#cli-examples).

src/platform/packages/shared/kbn-synthtrace/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,31 @@ export {
2121
type GetClientsReturn,
2222
} from './src/cli/utils/clients_manager';
2323
export type { ApmSynthtraceEsClient } from './src/lib/apm/client/apm_synthtrace_es_client';
24+
export { ComponentTemplateName } from './src/lib/apm/client/apm_synthtrace_es_client';
2425
export type { InfraSynthtraceEsClient } from './src/lib/infra/infra_synthtrace_es_client';
2526
export type { LogsSynthtraceEsClient } from './src/lib/logs/logs_synthtrace_es_client';
2627
export type { SyntheticsSynthtraceEsClient } from './src/lib/synthetics/synthetics_synthtrace_es_client';
2728
export {
2829
addObserverVersionTransform,
2930
deleteSummaryFieldTransform,
3031
} from './src/lib/utils/transform_helpers';
31-
export { indexAll } from './src/lib/utils/with_client';
32+
export { indexAll, withClient } from './src/lib/utils/with_client';
33+
export type { Scenario, ScenarioInitOptions } from './src/cli/scenario';
34+
export type { RunOptions } from './src/cli/utils/parse_run_cli_flags';
35+
export { getSynthtraceEnvironment } from './src/lib/utils/get_synthtrace_environment';
36+
export { IndexTemplateName } from './src/lib/logs/custom_logsdb_index_templates';
37+
export { timestampDateMapping } from './src/lib/logs/custom_logsdb_indices';
3238
export * from './src/scenarios/agent_builder';
3339

3440
export { sigEvents } from './src/lib/service_graph_logs';
3541

42+
export {
43+
getNumberOpt,
44+
getBooleanOpt,
45+
getStringOpt,
46+
} from './src/scenarios/helpers/scenario_opts_helpers';
47+
export { getAtIndexOrRandom } from './src/scenarios/helpers/get_at_index_or_random';
48+
3649
export {
3750
APM_METRICS_SERVICE_NAMES,
3851
APM_METRICS_DASHBOARD_SERVICES,

src/platform/packages/shared/kbn-synthtrace/moon.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ dependsOn:
2222
- '@kbn/dev-utils'
2323
- '@kbn/elastic-agent-utils'
2424
- '@kbn/zod'
25-
- '@kbn/sample-log-parser'
2625
- '@kbn/tooling-log'
2726
- '@kbn/streams-schema'
2827
- '@kbn/streamlang'

src/platform/packages/shared/kbn-synthtrace/src/cli/run_synthtrace.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,18 @@
1010
import datemath from '@kbn/datemath';
1111
import type { Argv } from 'yargs';
1212
import yargs from 'yargs/yargs';
13-
import { readdirSync } from 'fs';
14-
import path from 'path';
1513
import { intervalToMs } from './utils/interval_to_ms';
1614
import { parseRunCliFlags } from './utils/parse_run_cli_flags';
1715
import { startHistoricalDataUpload } from './utils/start_historical_data_upload';
1816
import { startLiveDataUpload } from './utils/start_live_data_upload';
1917

20-
function getBuiltinScenarios() {
21-
return readdirSync(path.resolve(__dirname, '../scenarios')).map((s) => s.replace(/\.ts$/, ''));
22-
}
23-
2418
function options(y: Argv) {
2519
return y
2620
.usage('$0 <files ...>')
2721
.positional('files', {
28-
describe: 'Name of scenario',
22+
describe: 'Name of a built-in scenario or a path (absolute or relative) to a scenario file',
2923
demandOption: true,
3024
string: true,
31-
choices: getBuiltinScenarios(),
3225
})
3326
.option('target', {
3427
describe: 'Elasticsearch target',
@@ -145,6 +138,10 @@ function options(y: Argv) {
145138
'$0 simple_logs --target=https://elastic:changeme@localhost:9200 --insecure',
146139
'Connect to HTTPS Elasticsearch with self-signed certificates'
147140
)
141+
.example(
142+
'$0 ./x-pack/solutions/observability/plugins/apm/test/scenarios/distributed_trace.ts',
143+
'Run a colocated scenario by path'
144+
)
148145
.showHelpOnFail(false)
149146
.wrap(null);
150147
}

src/platform/packages/shared/kbn-synthtrace/src/cli/utils/parse_run_cli_flags.ts

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,109 @@ import { pick } from 'lodash';
1212
import path from 'path';
1313
import { LogLevel } from '../../lib/utils/create_logger';
1414
import type { RunCliFlags } from '../run_synthtrace';
15+
import { discoverRepoRoot } from './read_kibana_config';
16+
17+
const REPO_ROOT = discoverRepoRoot();
18+
19+
/**
20+
* Maps short scenario names to their colocated plugin paths.
21+
* Populated when scenarios were moved out of @kbn/synthtrace in
22+
* https://github.com/elastic/kibana/pull/270157.
23+
*/
24+
const SCENARIO_ALIASES: Record<string, string> = {
25+
agent_config: 'x-pack/solutions/observability/plugins/apm/test/scenarios/agent_config.ts',
26+
apache_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/apache_logs.ts',
27+
apm_jvm_metrics_type_conflict:
28+
'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_jvm_metrics_type_conflict.ts',
29+
apm_metrics_dashboards:
30+
'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_metrics_dashboards.ts',
31+
apm_ml_anomalies: 'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_ml_anomalies.ts',
32+
apm_service_legacy_to_otel_metrics:
33+
'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_service_legacy_to_otel_metrics.ts',
34+
apm_service_multi_env_otel_migration:
35+
'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_service_multi_env_otel_migration.ts',
36+
apm_service_overlapping_otel_metrics:
37+
'x-pack/solutions/observability/plugins/apm/test/scenarios/apm_service_overlapping_otel_metrics.ts',
38+
aws_lambda: 'x-pack/solutions/observability/plugins/apm/test/scenarios/aws_lambda.ts',
39+
azure_functions: 'x-pack/solutions/observability/plugins/apm/test/scenarios/azure_functions.ts',
40+
cloud_services_icons:
41+
'x-pack/solutions/observability/plugins/apm/test/scenarios/cloud_services_icons.ts',
42+
complete_trace: 'x-pack/solutions/observability/plugins/apm/test/scenarios/complete_trace.ts',
43+
composite_spans: 'x-pack/solutions/observability/plugins/apm/test/scenarios/composite_spans.ts',
44+
continuous_rollups:
45+
'x-pack/solutions/observability/plugins/apm/test/scenarios/continuous_rollups.ts',
46+
degraded_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/degraded_logs.ts',
47+
degraded_synthetics_monitors:
48+
'x-pack/solutions/observability/plugins/synthetics/test/scenarios/degraded_synthetics_monitors.ts',
49+
diagnostic_service_map:
50+
'x-pack/solutions/observability/plugins/apm/test/scenarios/diagnostic_service_map.ts',
51+
distributed_trace:
52+
'x-pack/solutions/observability/plugins/apm/test/scenarios/distributed_trace.ts',
53+
distributed_trace_long:
54+
'x-pack/solutions/observability/plugins/apm/test/scenarios/distributed_trace_long.ts',
55+
error_with_missing_transaction_sampled:
56+
'x-pack/solutions/observability/plugins/apm/test/scenarios/error_with_missing_transaction_sampled.ts',
57+
failed_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/failed_logs.ts',
58+
high_throughput: 'x-pack/solutions/observability/plugins/apm/test/scenarios/high_throughput.ts',
59+
http_access_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/http_access_logs.ts',
60+
http_access_logs_otel:
61+
'x-pack/platform/plugins/shared/streams/test/scenarios/http_access_logs_otel.ts',
62+
infra_aws_rds: 'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_aws_rds.ts',
63+
infra_docker_containers:
64+
'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_docker_containers.ts',
65+
infra_hosts_ecs: 'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_hosts_ecs.ts',
66+
infra_hosts_semconv:
67+
'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_hosts_semconv.ts',
68+
infra_k8s_containers:
69+
'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_k8s_containers.ts',
70+
infra_k8s_pods: 'x-pack/solutions/observability/plugins/infra/test/scenarios/infra_k8s_pods.ts',
71+
kafka_topics: 'x-pack/solutions/observability/plugins/apm/test/scenarios/kafka_topics.ts',
72+
kubernetes_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/kubernetes_logs.ts',
73+
low_throughput: 'x-pack/solutions/observability/plugins/apm/test/scenarios/low_throughput.ts',
74+
many_dependencies:
75+
'x-pack/solutions/observability/plugins/apm/test/scenarios/many_dependencies.ts',
76+
many_errors: 'x-pack/solutions/observability/plugins/apm/test/scenarios/many_errors.ts',
77+
many_instances: 'x-pack/solutions/observability/plugins/apm/test/scenarios/many_instances.ts',
78+
many_otel_services:
79+
'x-pack/solutions/observability/plugins/apm/test/scenarios/many_otel_services.ts',
80+
many_services: 'x-pack/solutions/observability/plugins/apm/test/scenarios/many_services.ts',
81+
many_transactions:
82+
'x-pack/solutions/observability/plugins/apm/test/scenarios/many_transactions.ts',
83+
messaging_systems_mixed:
84+
'x-pack/solutions/observability/plugins/apm/test/scenarios/messaging_systems_mixed.ts',
85+
missing_service_environment:
86+
'x-pack/solutions/observability/plugins/apm/test/scenarios/missing_service_environment.ts',
87+
mobile: 'x-pack/solutions/observability/plugins/apm/test/scenarios/mobile.ts',
88+
otel_exit_span_missing_destination:
89+
'x-pack/solutions/observability/plugins/apm/test/scenarios/otel_exit_span_missing_destination.ts',
90+
otel_logs_and_metrics_only:
91+
'x-pack/platform/plugins/shared/streams/test/scenarios/otel_logs_and_metrics_only.ts',
92+
otel_simple_trace:
93+
'x-pack/solutions/observability/plugins/apm/test/scenarios/otel_simple_trace.ts',
94+
other_bucket_group:
95+
'x-pack/solutions/observability/plugins/apm/test/scenarios/other_bucket_group.ts',
96+
sample_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/sample_logs.ts',
97+
serverless_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/serverless_logs.ts',
98+
service_map: 'x-pack/solutions/observability/plugins/apm/test/scenarios/service_map.ts',
99+
service_map_oom: 'x-pack/solutions/observability/plugins/apm/test/scenarios/service_map_oom.ts',
100+
service_summary_field_version_dependent:
101+
'x-pack/solutions/observability/plugins/apm/test/scenarios/service_summary_field_version_dependent.ts',
102+
services_without_transactions:
103+
'x-pack/solutions/observability/plugins/apm/test/scenarios/services_without_transactions.ts',
104+
simple_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/simple_logs.ts',
105+
simple_non_ecs_logs:
106+
'x-pack/platform/plugins/shared/streams/test/scenarios/simple_non_ecs_logs.ts',
107+
simple_otel_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/simple_otel_logs.ts',
108+
simple_trace: 'x-pack/solutions/observability/plugins/apm/test/scenarios/simple_trace.ts',
109+
slash_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/slash_logs.ts',
110+
span_links: 'x-pack/solutions/observability/plugins/apm/test/scenarios/span_links.ts',
111+
trace_with_orphan_items:
112+
'x-pack/solutions/observability/plugins/apm/test/scenarios/trace_with_orphan_items.ts',
113+
trace_with_service_names_with_slashes:
114+
'x-pack/solutions/observability/plugins/apm/test/scenarios/trace_with_service_names_with_slashes.ts',
115+
unstructured_logs: 'x-pack/platform/plugins/shared/streams/test/scenarios/unstructured_logs.ts',
116+
variance: 'x-pack/solutions/observability/plugins/apm/test/scenarios/variance.ts',
117+
};
15118

16119
function getParsedFiles(flags: RunCliFlags) {
17120
const { _: parsedFiles } = flags;
@@ -21,13 +124,20 @@ function getParsedFiles(flags: RunCliFlags) {
21124
}
22125

23126
const filesPath = parsedFiles.map((parsedFile) => {
24-
const foundPath = [
25-
path.resolve(parsedFile),
26-
path.resolve(`${parsedFile}.ts`),
127+
const aliasRelPath = SCENARIO_ALIASES[parsedFile];
128+
const candidates = [
129+
// Alias lookup for scenarios moved out of @kbn/synthtrace to plugin directories.
130+
...(aliasRelPath ? [path.resolve(REPO_ROOT, aliasRelPath)] : []),
131+
// Built-in scenarios that remain in @kbn/synthtrace.
27132
path.resolve(__dirname, '../../scenarios', parsedFile),
28133
path.resolve(__dirname, '../../scenarios', `${parsedFile}.ts`),
29134
path.resolve(__dirname, '../../scenarios', `${parsedFile}.js`),
30-
].find((p) => existsSync(p));
135+
// Absolute or CWD-relative path provided directly.
136+
path.resolve(parsedFile),
137+
path.resolve(`${parsedFile}.ts`),
138+
];
139+
140+
const foundPath = candidates.find((p) => existsSync(p));
31141

32142
if (!foundPath) {
33143
throw new Error(`Could not find scenario file for: "${parsedFile}"`);

src/platform/packages/shared/kbn-synthtrace/src/cli/utils/read_kibana_config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import fs from 'fs';
1212
import yaml from 'js-yaml';
1313
import { REPO_ROOT } from '@kbn/repo-info';
1414

15+
export const discoverRepoRoot = (): string => REPO_ROOT;
16+
1517
export type KibanaConfig = ReturnType<typeof readKibanaConfig>;
1618

1719
export const readKibanaConfig = () => {

src/platform/packages/shared/kbn-synthtrace/src/cli/utils/workers/run_worker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export function runWorker<TWorkerData>({
4747

4848
worker.on('error', (error) => {
4949
logger.error(error);
50-
reject();
50+
reject(error);
5151
});
5252

5353
worker.on('exit', (code) => {

src/platform/packages/shared/kbn-synthtrace/src/scenarios/helpers/get_at_index_or_random.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99

1010
import { randomInt } from 'crypto';
1111

12-
// Utility function to get a random element from an array
13-
export const getAtIndexOrRandom = <T>(values: T[], index?: number) =>
14-
values[index ?? randomInt(values.length)];
12+
/**
13+
* Returns `values[index]` when index is provided, otherwise picks a uniformly random element.
14+
* Throws if the array is empty to surface programming errors early.
15+
*/
16+
export const getAtIndexOrRandom = <T>(values: T[], index?: number): T => {
17+
if (values.length === 0) {
18+
throw new Error('getAtIndexOrRandom called with an empty array');
19+
}
20+
return values[index ?? randomInt(values.length)];
21+
};

0 commit comments

Comments
 (0)