Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
2d4ae4d
initial version
rStelmach Jan 20, 2026
b3994ff
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Jan 20, 2026
d69068d
adjust tests, remove leftovers after tests
rStelmach Jan 20, 2026
ba3178d
bring back old text
rStelmach Jan 20, 2026
ac09e43
add useMemo
rStelmach Jan 20, 2026
fef5496
split tests, add auto-enable wired, add telemetry
rStelmach Jan 21, 2026
d061a61
modify hook
rStelmach Jan 21, 2026
4460583
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Jan 21, 2026
0c1d817
modify component
rStelmach Jan 22, 2026
96b1647
fix sending logs to `logs` instead of creating classic stream
rStelmach Jan 22, 2026
475586a
adjust comments
rStelmach Jan 22, 2026
f3a1ee6
adjust script for kubernetes flows
rStelmach Jan 22, 2026
acef8cc
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 22, 2026
c4dd828
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Jan 22, 2026
54f2a8e
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 23, 2026
f8e2009
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 23, 2026
5509218
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 26, 2026
e9998e9
add new approach for wiring logs
rStelmach Jan 26, 2026
1ceb73a
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 28, 2026
932f1eb
Merge branch 'main' into 301-wired-streams-onboarding
flash1293 Jan 28, 2026
b7c8a20
fix test flakiness
rStelmach Jan 28, 2026
5d7564f
use streams plugin instead of http for streams, adjust styling comments
rStelmach Jan 29, 2026
24e66b0
Changes from node scripts/lint_ts_projects --fix
kibanamachine Jan 29, 2026
f051edf
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Jan 29, 2026
987100a
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Jan 29, 2026
aaf7221
add hover message and modify modal to contain more information
rStelmach Jan 30, 2026
d7bc3e9
adjust modal
rStelmach Jan 30, 2026
6d0eb2a
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Jan 30, 2026
edcb708
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Jan 30, 2026
79adf91
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 2, 2026
4547996
fix logs links
rStelmach Feb 3, 2026
5272997
Changes from node scripts/lint_ts_projects --fix
kibanamachine Feb 3, 2026
3fdc796
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Feb 3, 2026
f9e45a5
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 3, 2026
c22b3e9
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 3, 2026
601ba2a
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 5, 2026
ccc50a8
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 9, 2026
ce54d13
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 9, 2026
4a14598
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 9, 2026
e2860f3
address ralphs comments
rStelmach Feb 9, 2026
46ffc62
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 9, 2026
78212d0
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 11, 2026
8b9b638
inject resource/wired_streams processor into the user's OTel Collecto…
rStelmach Feb 11, 2026
eab2286
rStelmach Feb 16, 2026
66fd7a6
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 16, 2026
89a2c15
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 16, 2026
85c40d6
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 18, 2026
d033e2e
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 18, 2026
9fda690
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 18, 2026
c9827de
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 19, 2026
7e569ba
fix dashboards
rStelmach Feb 19, 2026
a629796
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 19, 2026
848dc23
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 23, 2026
07e8dc1
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 24, 2026
2e30db2
Merge branch 'main' into 301-wired-streams-onboarding
rStelmach Feb 24, 2026
d713301
make wired streams onboarding work with split logs endpoint
rStelmach Feb 24, 2026
a8b373d
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 24, 2026
55fb033
fix tests
rStelmach Feb 24, 2026
7f1a78a
Merge branch 'main' into 301-wired-streams-onboarding
flash1293 Feb 26, 2026
55cdc84
address comments
rStelmach Feb 27, 2026
24e4062
set subobjects: false for ECS stream component templates and update t…
rStelmach Feb 27, 2026
0586e5f
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 27, 2026
3975b7d
addrsss comments
rStelmach Feb 27, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ export interface PackageClient {
pkgVersion?: string,
isInputIncluded?: (input: TemplateAgentPolicyInput) => boolean,
prerelease?: boolean,
ignoreUnverified?: boolean
ignoreUnverified?: boolean,
injectWiredStreamsRouting?: boolean
): Promise<string>;

reinstallEsAssets(
Expand Down Expand Up @@ -326,7 +327,8 @@ class PackageClientImpl implements PackageClient {
pkgVersion?: string,
isInputIncluded?: (input: TemplateAgentPolicyInput) => boolean,
prerelease?: boolean,
ignoreUnverified?: boolean
ignoreUnverified?: boolean,
injectWiredStreamsRouting?: boolean
) {
await this.#runPreflight(READ_PACKAGE_INFO_AUTHZ);

Expand All @@ -343,7 +345,8 @@ class PackageClientImpl implements PackageClient {
'yml',
isInputIncluded,
prerelease,
ignoreUnverified
ignoreUnverified,
injectWiredStreamsRouting
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export async function getTemplateInputs(
format: 'yml',
isInputIncluded?: (input: TemplateAgentPolicyInput) => boolean,
prerelease?: boolean,
ignoreUnverified?: boolean
ignoreUnverified?: boolean,
injectWiredStreamsRouting?: boolean
): Promise<string>;
export async function getTemplateInputs(
soClient: SavedObjectsClientContract,
Expand All @@ -109,7 +110,8 @@ export async function getTemplateInputs(
format: 'json',
isInputIncluded?: (input: TemplateAgentPolicyInput) => boolean,
prerelease?: boolean,
ignoreUnverified?: boolean
ignoreUnverified?: boolean,
injectWiredStreamsRouting?: boolean
): Promise<{ inputs: TemplateAgentPolicyInput[] }>;
export async function getTemplateInputs(
soClient: SavedObjectsClientContract,
Expand All @@ -118,7 +120,8 @@ export async function getTemplateInputs(
format: Format,
isInputIncluded: (input: TemplateAgentPolicyInput) => boolean = () => true,
prerelease?: boolean,
ignoreUnverified?: boolean
ignoreUnverified?: boolean,
injectWiredStreamsRouting: boolean = false
) {
const experimentalFeature = appContextService.getExperimentalFeatures();

Expand Down Expand Up @@ -195,6 +198,28 @@ export async function getTemplateInputs(
inputIdsDestinationMap
).filter(isInputIncluded);

if (injectWiredStreamsRouting) {
for (const input of inputs) {
const inputStreams = input.streams as Array<{
data_stream?: { type?: string };
processors?: Array<Record<string, unknown>>;
}>;
if (inputStreams) {
for (const stream of inputStreams) {
if (stream.data_stream?.type === 'logs') {
stream.processors = stream.processors || [];
stream.processors.unshift({
add_fields: {
target: '@metadata',
fields: { raw_index: 'logs.ecs' },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flash1293 I assumed that we want logs.ecs here since fleet integrations use ECS fields if I am not wrong. That said, I guess they might just work fine with either logs.ecs or logs.ote wdyt? shoudl we keep it ecs here as suggested?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logs.ecs seems right to me. Yeah, these are used by Elastic agent, so they ship ECS data

},
});
}
}
}
}
}

let otelcolConfig;
if (experimentalFeature.enableOtelIntegrations) {
// Template inputs don't have package info cache, so pass undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,4 +384,85 @@ describe('Fleet - getTemplateInputs', () => {

expect(template).toMatchSnapshot();
});

it('should inject wired streams routing processor for log streams when enabled', async () => {
const soMock = savedObjectsClientMock.create();
soMock.get.mockResolvedValue({ attributes: {} } as any);
const template = await getTemplateInputs(
soMock,
'redis',
'1.18.0',
'json',
undefined,
undefined,
undefined,
true // injectWiredStreamsRouting
);

const logInput = template.inputs.find((input) => input.type === 'logfile');
expect(logInput).toBeDefined();
if (logInput && logInput.streams) {
for (const stream of logInput.streams as Array<{
data_stream?: { type?: string };
processors?: Array<{ add_fields?: { target: string; fields: { raw_index: string } } }>;
}>) {
if (stream.data_stream?.type === 'logs') {
expect(stream.processors).toBeDefined();
expect(stream.processors![0]).toEqual({
add_fields: {
target: '@metadata',
fields: { raw_index: 'logs.ecs' },
},
});
}
}
}
});

it('should NOT inject wired streams routing processor when disabled', async () => {
const soMock = savedObjectsClientMock.create();
soMock.get.mockResolvedValue({ attributes: {} } as any);
const templateWithRouting = await getTemplateInputs(
soMock,
'redis',
'1.18.0',
'json',
undefined,
undefined,
undefined,
true
);
const templateWithoutRouting = await getTemplateInputs(
soMock,
'redis',
'1.18.0',
'json',
undefined,
undefined,
undefined,
false
);

// With routing should have the processor
const logInputWithRouting = templateWithRouting.inputs.find(
(input) => input.type === 'logfile'
);
const logInputWithoutRouting = templateWithoutRouting.inputs.find(
(input) => input.type === 'logfile'
);

if (logInputWithRouting?.streams && logInputWithoutRouting?.streams) {
const streamWithRouting = (
logInputWithRouting.streams as Array<{ processors?: unknown[] }>
)[0];
const streamWithoutRouting = (
logInputWithoutRouting.streams as Array<{ processors?: unknown[] }>
)[0];

const routingProcessorCount = streamWithRouting.processors?.length ?? 0;
const noRoutingProcessorCount = streamWithoutRouting.processors?.length ?? 0;

expect(routingProcessorCount).toBe(noRoutingProcessorCount + 1);
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ describe('generateLayer', () => {
});
// No attributes passthrough object for ECS streams
expect(properties.attributes).toBeUndefined();

// ECS streams use subobjects: false to keep dotted field names as flat keys
expect(result.template.mappings?.subobjects).toBe(false);
});

it('should use OTel settings for OTel-based root streams', () => {
Expand Down Expand Up @@ -418,6 +421,9 @@ describe('generateLayer', () => {
});
// No attributes passthrough object for ECS streams
expect(properties.attributes).toBeUndefined();

// ECS child streams also use subobjects: false
expect(result.template.mappings?.subobjects).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export function generateLayer(
mappings: {
dynamic: false,
properties: mappingProperties,
...(isEcsStream && { subobjects: false as const }),
},
},
version: ASSET_VERSION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Streams, emptyAssets } from '@kbn/streams-schema';
import { MAX_PRIORITY } from '@kbn/streams-plugin/server/lib/streams/index_templates/generate_index_template';
import type { InheritedFieldDefinition } from '@kbn/streams-schema/src/fields';
import { get, omit } from 'lodash';
import type { JsonObject } from '@kbn/utility-types';
import type { DeploymentAgnosticFtrProviderContext } from '../../ftr_provider_context';
import type { StreamsSupertestRepositoryClient } from './helpers/repository_client';
import {
Expand Down Expand Up @@ -473,8 +474,8 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
expect(result._index).to.match(new RegExp(`^\\.ds\\-${rootStream.replace('.', '\\.')}-.*`));
expect(result._source).to.have.property('@timestamp', '2024-01-01T00:00:00.000Z');
expect(result._source).to.have.property('message', 'test message');
expect(result._source).to.have.property('stream');
expect((result._source as any).stream).to.have.property('name', rootStream);
// With subobjects: false, stream.name is a flat dotted key
expect((result._source as JsonObject)['stream.name']).to.eql(rootStream);
});

it('Index an ECS doc with nested fields', async () => {
Expand All @@ -492,8 +493,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
const result = await indexAndAssertTargetStream(esClient, rootStream, doc);
expect(result._source).to.have.property('@timestamp', '2024-01-01T00:00:00.000Z');
expect(result._source).to.have.property('message', 'test message');
expect(result._source).to.have.property('stream');
expect((result._source as any).stream).to.have.property('name', rootStream);
expect((result._source as JsonObject)['stream.name']).to.eql(rootStream);
});

it(`Fork ${rootStream} to ${rootStream}.apache`, async () => {
Expand Down Expand Up @@ -541,8 +541,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
const result = await indexAndAssertTargetStream(esClient, `${rootStream}.apache`, doc);
expect(result._source).to.have.property('@timestamp', '2024-01-01T00:00:10.000Z');
expect(result._source).to.have.property('message', 'Apache access log');
expect(result._source).to.have.property('stream');
expect((result._source as any).stream).to.have.property('name', `${rootStream}.apache`);
expect((result._source as JsonObject)['stream.name']).to.eql(`${rootStream}.apache`);
});

it(`Fork ${rootStream}.apache to ${rootStream}.apache.error`, async () => {
Expand Down Expand Up @@ -574,11 +573,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
);
expect(result._source).to.have.property('@timestamp', '2024-01-01T00:00:20.000Z');
expect(result._source).to.have.property('message', 'Apache error log');
expect(result._source).to.have.property('stream');
expect((result._source as any).stream).to.have.property(
'name',
`${rootStream}.apache.error`
);
expect((result._source as JsonObject)['stream.name']).to.eql(`${rootStream}.apache.error`);
});

it(`Does not index to ${rootStream}.apache.error if routing is disabled`, async () => {
Expand Down Expand Up @@ -912,11 +907,17 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
}
}

const isEcs = streams[0].startsWith('logs.ecs');
const mappingsResponse = await esClient.indices.getMapping({ index: streams });
for (const { mappings } of Object.values(mappingsResponse)) {
for (const [field, fieldConfig] of Object.entries(expectedFields)) {
const fieldPath = field.split('.').join('.properties.');
expect(get(mappings.properties, fieldPath)).to.eql(omit(fieldConfig, ['from']));
if (isEcs) {
// With subobjects: false, dotted field names are literal keys in mappings
expect(get(mappings.properties, [field])).to.eql(omit(fieldConfig, ['from']));
} else {
const fieldPath = field.split('.').join('.properties.');
expect(get(mappings.properties, fieldPath)).to.eql(omit(fieldConfig, ['from']));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,33 @@ export const OBSERVABILITY_ONBOARDING_FLOW_DATASET_DETECTED_TELEMETRY_EVENT: Eve
context: flowContextSchema,
},
};

export const OBSERVABILITY_ONBOARDING_WIRED_STREAMS_AUTO_ENABLED_EVENT: EventTypeOpts<{
flow_type: string;
success: boolean;
error_message?: string;
}> = {
eventType: 'observability_onboarding_wired_streams_auto_enabled',
schema: {
flow_type: {
type: 'keyword',
_meta: {
description:
'The onboarding flow type where auto-enable was triggered (otel_host, otel_kubernetes, elastic_agent_kubernetes, auto_detect)',
},
},
success: {
type: 'boolean',
_meta: {
description: 'Whether the auto-enable operation succeeded',
},
},
error_message: {
type: 'text',
_meta: {
description: 'Error message if auto-enable failed',
optional: true,
},
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"optionalPlugins": [
"cloud",
"usageCollection",
"streams",
],
"requiredBundles": [
"kibanaReact"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dependsOn:
- '@kbn/react-kibana-mount'
- '@kbn/react-query'
- '@kbn/core-security-server'
- '@kbn/streams-plugin'
- '@kbn/data-views-plugin'
tags:
- plugin
- prod
Expand Down
Loading
Loading