Skip to content

🌊 Streams: Normalized format for wired streams#205113

Merged
flash1293 merged 102 commits intoelastic:mainfrom
flash1293:flash1293/streams/otel-mode
May 28, 2025
Merged

🌊 Streams: Normalized format for wired streams#205113
flash1293 merged 102 commits intoelastic:mainfrom
flash1293:flash1293/streams/otel-mode

Conversation

@flash1293
Copy link
Contributor

@flash1293 flash1293 commented Dec 23, 2024

This PR extends streams to allow mixed otel/ecs querying.

Walkthrough (slightly outdated):

otel_streams.mov
Screenshot 2025-03-07 at 17 15 27

To test

  • Start up PR, enable streams via POST kbn:/api/streams/_enable
  • Redirect all incoming logs to streams:
PUT _ingest/pipeline/logs@custom
{
  "processors": [
    {
      "reroute": {
        "destination": "logs"
      }
    }
  ]
}
  • Send some logs
  • They will be trandslated to namespaced ECS and can be queried the same way

Some demo actions:

# Make sure trial license is active (because of synthetic source)

# Enable streams
POST kbn:/api/streams/_enable

# Fork some data to be able to edit mapping and stuff
POST kbn:/api/streams/logs/_fork
{
  "stream": { "name": "logs.child" },
  "if": {
    "field": "attributes.custom_field",
    "operator": "exists"
  }
}
# Routing could have been done on "custom_field" as well

# Send some ECS-formatted data
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2"
}

# Send some OTel-formatted data
POST logs/_doc
{
  "body": {
    "text": "Hello OTEL world"
  },
  "severity_text": "warn",
  "resource": {
    "attributes": {
      "host.name": "my-mbp",
      "host.ip": "1.2.3.4"
    }
  },
  "attributes": {
    "custom_field": "value"
  }
}

# See how it's stored as namespaced ECS (beware automatic aliasing)
GET logs.child/_search

# See the fields and their aliases
GET kbn:/api/streams/logs.child

# Nested data treatment (objects flattened, arrays kept)
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2",
  "nested_custom_field": {
    "deeply": {
      "deeply": {
        "nested": "value"
      }
    }
  },
  "array_values": [
    { "deeply": { "nested": 123 }},
    { "deeply": { "nested": 456 }}
  ]
}

GET logs.child/_search

# Map a field (show alias in app)
PUT kbn:/api/streams/logs.child/_ingest
{
  "ingest": {
    "lifecycle": {
      "inherit": {}
    },
    "processing": [],
    "routing": [],
    "wired": {
      "fields": {
        "attributes.custom_value": {
          "type": "keyword"
        }
      }
    }
  }
}
# Trying to map "custom_value" will result in an error - only attributes.* and resource_attributes.* can be mapped

# End experiment
POST kbn:/api/streams/_disable

Do on separate PRs

  • More dedicated integration tests
  • Replace the painless implementation of normalization with an Elasticsearch processor (not shipped yet)
  • Remove the dot expander processors once Elasticsearch allows accessing flattened field names

simianhacker and others added 27 commits December 17, 2024 15:59
@dgieselaar dgieselaar added the Feature:Streams This is the label for the Streams Project label Jan 6, 2025
@flash1293 flash1293 changed the title Otel compat mode 🌊 Otel compat mode Feb 4, 2025
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
streamsApp 468 469 +1

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/streams-schema 212 220 +8

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
streamsApp 424.6KB 425.1KB +490.0B

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
@kbn/streams-schema 17 16 -1
Unknown metric groups

API count

id before after diff
@kbn/streams-schema 221 229 +8

History

@flash1293 flash1293 merged commit 440aeab into elastic:main May 28, 2025
8 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.19

https://github.com/elastic/kibana/actions/runs/15298591946

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.19 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 205113

Questions ?

Please refer to the Backport tool documentation

@flash1293
Copy link
Contributor Author

💚 All backports created successfully

Status Branch Result
8.19

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

flash1293 added a commit to flash1293/kibana that referenced this pull request May 28, 2025
This PR extends streams to allow mixed otel/ecs querying.

Walkthrough (slightly outdated):

https://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585

<img width="492" alt="Screenshot 2025-03-07 at 17 15 27"
src="https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5"
/>

# To test

* Start up PR, enable streams via `POST kbn:/api/streams/_enable`
* Redirect all incoming logs to streams:
```
PUT _ingest/pipeline/logs@custom
{
  "processors": [
    {
      "reroute": {
        "destination": "logs"
      }
    }
  ]
}
```
* Send some logs
* They will be trandslated to namespaced ECS and can be queried the same
way

Some demo actions:
```
# Make sure trial license is active (because of synthetic source)

# Enable streams
POST kbn:/api/streams/_enable

# Fork some data to be able to edit mapping and stuff
POST kbn:/api/streams/logs/_fork
{
  "stream": { "name": "logs.child" },
  "if": {
    "field": "attributes.custom_field",
    "operator": "exists"
  }
}
# Routing could have been done on "custom_field" as well

# Send some ECS-formatted data
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2"
}

# Send some OTel-formatted data
POST logs/_doc
{
  "body": {
    "text": "Hello OTEL world"
  },
  "severity_text": "warn",
  "resource": {
    "attributes": {
      "host.name": "my-mbp",
      "host.ip": "1.2.3.4"
    }
  },
  "attributes": {
    "custom_field": "value"
  }
}

# See how it's stored as namespaced ECS (beware automatic aliasing)
GET logs.child/_search

# See the fields and their aliases
GET kbn:/api/streams/logs.child

# Nested data treatment (objects flattened, arrays kept)
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2",
  "nested_custom_field": {
    "deeply": {
      "deeply": {
        "nested": "value"
      }
    }
  },
  "array_values": [
    { "deeply": { "nested": 123 }},
    { "deeply": { "nested": 456 }}
  ]
}

GET logs.child/_search

# Map a field (show alias in app)
PUT kbn:/api/streams/logs.child/_ingest
{
  "ingest": {
    "lifecycle": {
      "inherit": {}
    },
    "processing": [],
    "routing": [],
    "wired": {
      "fields": {
        "attributes.custom_value": {
          "type": "keyword"
        }
      }
    }
  }
}
# Trying to map "custom_value" will result in an error - only attributes.* and resource_attributes.* can be mapped

# End experiment
POST kbn:/api/streams/_disable
```

## Do on separate PRs

* More dedicated integration tests
* Replace the painless implementation of normalization with an
Elasticsearch processor (not shipped yet)
* Remove the dot expander processors once Elasticsearch allows accessing
flattened field names

---------

Co-authored-by: Chris Cowan <chris@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 440aeab)

# Conflicts:
#	x-pack/test/api_integration/deployment_agnostic/apis/observability/streams/enrichment.ts
akowalska622 pushed a commit to akowalska622/kibana that referenced this pull request May 29, 2025
This PR extends streams to allow mixed otel/ecs querying.

Walkthrough (slightly outdated):


https://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585


<img width="492" alt="Screenshot 2025-03-07 at 17 15 27"
src="https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5"
/>

# To test

* Start up PR, enable streams via `POST kbn:/api/streams/_enable`
* Redirect all incoming logs to streams:
```
PUT _ingest/pipeline/logs@custom
{
  "processors": [
    {
      "reroute": {
        "destination": "logs"
      }
    }
  ]
}
```
* Send some logs
* They will be trandslated to namespaced ECS and can be queried the same
way

Some demo actions:
```
# Make sure trial license is active (because of synthetic source)

# Enable streams
POST kbn:/api/streams/_enable

# Fork some data to be able to edit mapping and stuff
POST kbn:/api/streams/logs/_fork
{
  "stream": { "name": "logs.child" },
  "if": {
    "field": "attributes.custom_field",
    "operator": "exists"
  }
}
# Routing could have been done on "custom_field" as well

# Send some ECS-formatted data
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2"
}

# Send some OTel-formatted data
POST logs/_doc
{
  "body": {
    "text": "Hello OTEL world"
  },
  "severity_text": "warn",
  "resource": {
    "attributes": {
      "host.name": "my-mbp",
      "host.ip": "1.2.3.4"
    }
  },
  "attributes": {
    "custom_field": "value"
  }
}

# See how it's stored as namespaced ECS (beware automatic aliasing)
GET logs.child/_search

# See the fields and their aliases
GET kbn:/api/streams/logs.child

# Nested data treatment (objects flattened, arrays kept)
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2",
  "nested_custom_field": {
    "deeply": {
      "deeply": {
        "nested": "value"
      }
    }
  },
  "array_values": [
    { "deeply": { "nested": 123 }},
    { "deeply": { "nested": 456 }}
  ]
}

GET logs.child/_search

# Map a field (show alias in app)
PUT kbn:/api/streams/logs.child/_ingest
{
  "ingest": {
    "lifecycle": {
      "inherit": {}
    },
    "processing": [],
    "routing": [],
    "wired": {
      "fields": {
        "attributes.custom_value": {
          "type": "keyword"
        }
      }
    }
  }
}
# Trying to map "custom_value" will result in an error - only attributes.* and resource_attributes.* can be mapped

# End experiment
POST kbn:/api/streams/_disable
```

## Do on separate PRs

* More dedicated integration tests
* Replace the painless implementation of normalization with an
Elasticsearch processor (not shipped yet)
* Remove the dot expander processors once Elasticsearch allows accessing
flattened field names

---------

Co-authored-by: Chris Cowan <chris@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
kdelemme added a commit that referenced this pull request May 29, 2025
## Summary

Update scout test according to latest change with normalized fields:
#205113
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request May 29, 2025
## Summary

Update scout test according to latest change with normalized fields:
elastic#205113

(cherry picked from commit 567b4d5)
kibanamachine added a commit that referenced this pull request May 29, 2025
# Backport

This will backport the following commits from `main` to `8.19`:
- [fix(streams): wired scout test
(#221838)](#221838)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Kevin
Delemme","email":"kevin.delemme@elastic.co"},"sourceCommit":{"committedDate":"2025-05-29T14:45:35Z","message":"fix(streams):
wired scout test (#221838)\n\n## Summary\n\nUpdate scout test according
to latest change with normalized
fields:\nhttps://github.com//pull/205113","sha":"567b4d5c6bd8e1c8916d606906054e9939d89935","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:version","v9.1.0","v8.19.0","author:obs-ux-management"],"title":"fix(streams):
wired scout
test","number":221838,"url":"https://github.com/elastic/kibana/pull/221838","mergeCommit":{"message":"fix(streams):
wired scout test (#221838)\n\n## Summary\n\nUpdate scout test according
to latest change with normalized
fields:\nhttps://github.com//pull/205113","sha":"567b4d5c6bd8e1c8916d606906054e9939d89935"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/221838","number":221838,"mergeCommit":{"message":"fix(streams):
wired scout test (#221838)\n\n## Summary\n\nUpdate scout test according
to latest change with normalized
fields:\nhttps://github.com//pull/205113","sha":"567b4d5c6bd8e1c8916d606906054e9939d89935"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Kevin Delemme <kevin.delemme@elastic.co>
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label May 30, 2025
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.
cc: @flash1293

1 similar comment
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.
cc: @flash1293

flash1293 added a commit that referenced this pull request Jun 2, 2025
)

# Backport

This will backport the following commits from `main` to `8.19`:
- [🌊 Streams: Normalized format for wired streams
(#205113)](#205113)

<!--- Backport version: 10.0.0 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Joe
Reuter","email":"johannes.reuter@elastic.co"},"sourceCommit":{"committedDate":"2025-05-28T11:08:39Z","message":"🌊
Streams: Normalized format for wired streams (#205113)\n\nThis PR
extends streams to allow mixed otel/ecs querying.\n\nWalkthrough
(slightly
outdated):\n\n\nhttps://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585\n\n\n<img
width=\"492\" alt=\"Screenshot 2025-03-07 at 17 15
27\"\nsrc=\"https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5\"\n/>\n\n#
To test\n\n* Start up PR, enable streams via `POST
kbn:/api/streams/_enable`\n* Redirect all incoming logs to
streams:\n```\nPUT _ingest/pipeline/logs@custom\n{\n \"processors\": [\n
{\n \"reroute\": {\n \"destination\": \"logs\"\n }\n }\n ]\n}\n```\n*
Send some logs\n* They will be trandslated to namespaced ECS and can be
queried the same\nway\n\nSome demo actions:\n```\n# Make sure trial
license is active (because of synthetic source)\n\n# Enable
streams\nPOST kbn:/api/streams/_enable\n\n# Fork some data to be able to
edit mapping and stuff\nPOST kbn:/api/streams/logs/_fork\n{\n
\"stream\": { \"name\": \"logs.child\" },\n \"if\": {\n \"field\":
\"attributes.custom_field\",\n \"operator\": \"exists\"\n }\n}\n#
Routing could have been done on \"custom_field\" as well\n\n# Send some
ECS-formatted data\nPOST logs/_doc\n{\n \"message\": \"Hello world\",\n
\"log.level\": \"warn\",\n \"host\": {\n \"name\": \"my-mbp\",\n \"ip\":
\"1.2.3.4\"\n },\n \"custom_field\": \"value2\"\n}\n\n# Send some
OTel-formatted data\nPOST logs/_doc\n{\n \"body\": {\n \"text\": \"Hello
OTEL world\"\n },\n \"severity_text\": \"warn\",\n \"resource\": {\n
\"attributes\": {\n \"host.name\": \"my-mbp\",\n \"host.ip\":
\"1.2.3.4\"\n }\n },\n \"attributes\": {\n \"custom_field\": \"value\"\n
}\n}\n\n# See how it's stored as namespaced ECS (beware automatic
aliasing)\nGET logs.child/_search\n\n# See the fields and their
aliases\nGET kbn:/api/streams/logs.child\n\n# Nested data treatment
(objects flattened, arrays kept)\nPOST logs/_doc\n{\n \"message\":
\"Hello world\",\n \"log.level\": \"warn\",\n \"host\": {\n \"name\":
\"my-mbp\",\n \"ip\": \"1.2.3.4\"\n },\n \"custom_field\": \"value2\",\n
\"nested_custom_field\": {\n \"deeply\": {\n \"deeply\": {\n \"nested\":
\"value\"\n }\n }\n },\n \"array_values\": [\n { \"deeply\": {
\"nested\": 123 }},\n { \"deeply\": { \"nested\": 456 }}\n ]\n}\n\nGET
logs.child/_search\n\n# Map a field (show alias in app)\nPUT
kbn:/api/streams/logs.child/_ingest\n{\n \"ingest\": {\n \"lifecycle\":
{\n \"inherit\": {}\n },\n \"processing\": [],\n \"routing\": [],\n
\"wired\": {\n \"fields\": {\n \"attributes.custom_value\": {\n
\"type\": \"keyword\"\n }\n }\n }\n }\n}\n# Trying to map
\"custom_value\" will result in an error - only attributes.* and
resource_attributes.* can be mapped\n\n# End experiment\nPOST
kbn:/api/streams/_disable\n```\n\n## Do on separate PRs\n\n* More
dedicated integration tests\n* Replace the painless implementation of
normalization with an\nElasticsearch processor (not shipped yet)\n*
Remove the dot expander processors once Elasticsearch allows
accessing\nflattened field names\n\n---------\n\nCo-authored-by: Chris
Cowan <chris@elastic.co>\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"440aeabd398d3ca29e578f076a3292f5a61ec217","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:obs-ux-logs","backport:version","Feature:Streams","v9.1.0","v8.19.0"],"title":"🌊
Streams: Normalized format for wired
streams","number":205113,"url":"https://github.com/elastic/kibana/pull/205113","mergeCommit":{"message":"🌊
Streams: Normalized format for wired streams (#205113)\n\nThis PR
extends streams to allow mixed otel/ecs querying.\n\nWalkthrough
(slightly
outdated):\n\n\nhttps://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585\n\n\n<img
width=\"492\" alt=\"Screenshot 2025-03-07 at 17 15
27\"\nsrc=\"https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5\"\n/>\n\n#
To test\n\n* Start up PR, enable streams via `POST
kbn:/api/streams/_enable`\n* Redirect all incoming logs to
streams:\n```\nPUT _ingest/pipeline/logs@custom\n{\n \"processors\": [\n
{\n \"reroute\": {\n \"destination\": \"logs\"\n }\n }\n ]\n}\n```\n*
Send some logs\n* They will be trandslated to namespaced ECS and can be
queried the same\nway\n\nSome demo actions:\n```\n# Make sure trial
license is active (because of synthetic source)\n\n# Enable
streams\nPOST kbn:/api/streams/_enable\n\n# Fork some data to be able to
edit mapping and stuff\nPOST kbn:/api/streams/logs/_fork\n{\n
\"stream\": { \"name\": \"logs.child\" },\n \"if\": {\n \"field\":
\"attributes.custom_field\",\n \"operator\": \"exists\"\n }\n}\n#
Routing could have been done on \"custom_field\" as well\n\n# Send some
ECS-formatted data\nPOST logs/_doc\n{\n \"message\": \"Hello world\",\n
\"log.level\": \"warn\",\n \"host\": {\n \"name\": \"my-mbp\",\n \"ip\":
\"1.2.3.4\"\n },\n \"custom_field\": \"value2\"\n}\n\n# Send some
OTel-formatted data\nPOST logs/_doc\n{\n \"body\": {\n \"text\": \"Hello
OTEL world\"\n },\n \"severity_text\": \"warn\",\n \"resource\": {\n
\"attributes\": {\n \"host.name\": \"my-mbp\",\n \"host.ip\":
\"1.2.3.4\"\n }\n },\n \"attributes\": {\n \"custom_field\": \"value\"\n
}\n}\n\n# See how it's stored as namespaced ECS (beware automatic
aliasing)\nGET logs.child/_search\n\n# See the fields and their
aliases\nGET kbn:/api/streams/logs.child\n\n# Nested data treatment
(objects flattened, arrays kept)\nPOST logs/_doc\n{\n \"message\":
\"Hello world\",\n \"log.level\": \"warn\",\n \"host\": {\n \"name\":
\"my-mbp\",\n \"ip\": \"1.2.3.4\"\n },\n \"custom_field\": \"value2\",\n
\"nested_custom_field\": {\n \"deeply\": {\n \"deeply\": {\n \"nested\":
\"value\"\n }\n }\n },\n \"array_values\": [\n { \"deeply\": {
\"nested\": 123 }},\n { \"deeply\": { \"nested\": 456 }}\n ]\n}\n\nGET
logs.child/_search\n\n# Map a field (show alias in app)\nPUT
kbn:/api/streams/logs.child/_ingest\n{\n \"ingest\": {\n \"lifecycle\":
{\n \"inherit\": {}\n },\n \"processing\": [],\n \"routing\": [],\n
\"wired\": {\n \"fields\": {\n \"attributes.custom_value\": {\n
\"type\": \"keyword\"\n }\n }\n }\n }\n}\n# Trying to map
\"custom_value\" will result in an error - only attributes.* and
resource_attributes.* can be mapped\n\n# End experiment\nPOST
kbn:/api/streams/_disable\n```\n\n## Do on separate PRs\n\n* More
dedicated integration tests\n* Replace the painless implementation of
normalization with an\nElasticsearch processor (not shipped yet)\n*
Remove the dot expander processors once Elasticsearch allows
accessing\nflattened field names\n\n---------\n\nCo-authored-by: Chris
Cowan <chris@elastic.co>\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"440aeabd398d3ca29e578f076a3292f5a61ec217"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/205113","number":205113,"mergeCommit":{"message":"🌊
Streams: Normalized format for wired streams (#205113)\n\nThis PR
extends streams to allow mixed otel/ecs querying.\n\nWalkthrough
(slightly
outdated):\n\n\nhttps://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585\n\n\n<img
width=\"492\" alt=\"Screenshot 2025-03-07 at 17 15
27\"\nsrc=\"https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5\"\n/>\n\n#
To test\n\n* Start up PR, enable streams via `POST
kbn:/api/streams/_enable`\n* Redirect all incoming logs to
streams:\n```\nPUT _ingest/pipeline/logs@custom\n{\n \"processors\": [\n
{\n \"reroute\": {\n \"destination\": \"logs\"\n }\n }\n ]\n}\n```\n*
Send some logs\n* They will be trandslated to namespaced ECS and can be
queried the same\nway\n\nSome demo actions:\n```\n# Make sure trial
license is active (because of synthetic source)\n\n# Enable
streams\nPOST kbn:/api/streams/_enable\n\n# Fork some data to be able to
edit mapping and stuff\nPOST kbn:/api/streams/logs/_fork\n{\n
\"stream\": { \"name\": \"logs.child\" },\n \"if\": {\n \"field\":
\"attributes.custom_field\",\n \"operator\": \"exists\"\n }\n}\n#
Routing could have been done on \"custom_field\" as well\n\n# Send some
ECS-formatted data\nPOST logs/_doc\n{\n \"message\": \"Hello world\",\n
\"log.level\": \"warn\",\n \"host\": {\n \"name\": \"my-mbp\",\n \"ip\":
\"1.2.3.4\"\n },\n \"custom_field\": \"value2\"\n}\n\n# Send some
OTel-formatted data\nPOST logs/_doc\n{\n \"body\": {\n \"text\": \"Hello
OTEL world\"\n },\n \"severity_text\": \"warn\",\n \"resource\": {\n
\"attributes\": {\n \"host.name\": \"my-mbp\",\n \"host.ip\":
\"1.2.3.4\"\n }\n },\n \"attributes\": {\n \"custom_field\": \"value\"\n
}\n}\n\n# See how it's stored as namespaced ECS (beware automatic
aliasing)\nGET logs.child/_search\n\n# See the fields and their
aliases\nGET kbn:/api/streams/logs.child\n\n# Nested data treatment
(objects flattened, arrays kept)\nPOST logs/_doc\n{\n \"message\":
\"Hello world\",\n \"log.level\": \"warn\",\n \"host\": {\n \"name\":
\"my-mbp\",\n \"ip\": \"1.2.3.4\"\n },\n \"custom_field\": \"value2\",\n
\"nested_custom_field\": {\n \"deeply\": {\n \"deeply\": {\n \"nested\":
\"value\"\n }\n }\n },\n \"array_values\": [\n { \"deeply\": {
\"nested\": 123 }},\n { \"deeply\": { \"nested\": 456 }}\n ]\n}\n\nGET
logs.child/_search\n\n# Map a field (show alias in app)\nPUT
kbn:/api/streams/logs.child/_ingest\n{\n \"ingest\": {\n \"lifecycle\":
{\n \"inherit\": {}\n },\n \"processing\": [],\n \"routing\": [],\n
\"wired\": {\n \"fields\": {\n \"attributes.custom_value\": {\n
\"type\": \"keyword\"\n }\n }\n }\n }\n}\n# Trying to map
\"custom_value\" will result in an error - only attributes.* and
resource_attributes.* can be mapped\n\n# End experiment\nPOST
kbn:/api/streams/_disable\n```\n\n## Do on separate PRs\n\n* More
dedicated integration tests\n* Replace the painless implementation of
normalization with an\nElasticsearch processor (not shipped yet)\n*
Remove the dot expander processors once Elasticsearch allows
accessing\nflattened field names\n\n---------\n\nCo-authored-by: Chris
Cowan <chris@elastic.co>\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"440aeabd398d3ca29e578f076a3292f5a61ec217"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jun 2, 2025
zacharyparikh pushed a commit to zacharyparikh/kibana that referenced this pull request Jun 4, 2025
This PR extends streams to allow mixed otel/ecs querying.

Walkthrough (slightly outdated):


https://github.com/user-attachments/assets/9d6280ff-57b2-43d8-9c81-dfbfabb64585


<img width="492" alt="Screenshot 2025-03-07 at 17 15 27"
src="https://github.com/user-attachments/assets/792fbbc2-6cbe-42fe-96b3-eea2b6959fe5"
/>

# To test

* Start up PR, enable streams via `POST kbn:/api/streams/_enable`
* Redirect all incoming logs to streams:
```
PUT _ingest/pipeline/logs@custom
{
  "processors": [
    {
      "reroute": {
        "destination": "logs"
      }
    }
  ]
}
```
* Send some logs
* They will be trandslated to namespaced ECS and can be queried the same
way

Some demo actions:
```
# Make sure trial license is active (because of synthetic source)

# Enable streams
POST kbn:/api/streams/_enable

# Fork some data to be able to edit mapping and stuff
POST kbn:/api/streams/logs/_fork
{
  "stream": { "name": "logs.child" },
  "if": {
    "field": "attributes.custom_field",
    "operator": "exists"
  }
}
# Routing could have been done on "custom_field" as well

# Send some ECS-formatted data
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2"
}

# Send some OTel-formatted data
POST logs/_doc
{
  "body": {
    "text": "Hello OTEL world"
  },
  "severity_text": "warn",
  "resource": {
    "attributes": {
      "host.name": "my-mbp",
      "host.ip": "1.2.3.4"
    }
  },
  "attributes": {
    "custom_field": "value"
  }
}

# See how it's stored as namespaced ECS (beware automatic aliasing)
GET logs.child/_search

# See the fields and their aliases
GET kbn:/api/streams/logs.child

# Nested data treatment (objects flattened, arrays kept)
POST logs/_doc
{
  "message": "Hello world",
  "log.level": "warn",
  "host": {
    "name": "my-mbp",
    "ip": "1.2.3.4"
  },
  "custom_field": "value2",
  "nested_custom_field": {
    "deeply": {
      "deeply": {
        "nested": "value"
      }
    }
  },
  "array_values": [
    { "deeply": { "nested": 123 }},
    { "deeply": { "nested": 456 }}
  ]
}

GET logs.child/_search

# Map a field (show alias in app)
PUT kbn:/api/streams/logs.child/_ingest
{
  "ingest": {
    "lifecycle": {
      "inherit": {}
    },
    "processing": [],
    "routing": [],
    "wired": {
      "fields": {
        "attributes.custom_value": {
          "type": "keyword"
        }
      }
    }
  }
}
# Trying to map "custom_value" will result in an error - only attributes.* and resource_attributes.* can be mapped

# End experiment
POST kbn:/api/streams/_disable
```

## Do on separate PRs

* More dedicated integration tests
* Replace the painless implementation of normalization with an
Elasticsearch processor (not shipped yet)
* Remove the dot expander processors once Elasticsearch allows accessing
flattened field names

---------

Co-authored-by: Chris Cowan <chris@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
zacharyparikh pushed a commit to zacharyparikh/kibana that referenced this pull request Jun 4, 2025
## Summary

Update scout test according to latest change with normalized fields:
elastic#205113
nickpeihl pushed a commit to nickpeihl/kibana that referenced this pull request Jun 12, 2025
## Summary

Update scout test according to latest change with normalized fields:
elastic#205113
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels Feature:Streams This is the label for the Streams Project release_note:skip Skip the PR/issue when compiling release notes Team:obs-onboarding Observability Onboarding Team v8.19.0 v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants