normalize-for-stream.asciidoc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. [role="xpack"]
  2. [[normalize-for-stream-processor]]
  3. === Normalize for Stream processor
  4. ++++
  5. <titleabbrev>Normalize for Stream</titleabbrev>
  6. ++++
  7. Detects whether a document is OpenTelemetry-compliant and if not -
  8. normalizes it as described below. If used in combination with the OTel-related
  9. mappings such as the ones defined in `logs-otel@template`, the resulting
  10. document can be queried seamlessly by clients that expect either https://www.elastic.co/guide/en/ecs/current/index.html[ECS] or https://github.com/open-telemetry/semantic-conventions[OpenTelemetry-Semantic-Conventions] formats.
  11. preview::["This processor is in tech preview and is not available in our serverless offering."]
  12. [[normalize-for-stream-detecting]]
  13. ==== Detecting OpenTelemetry compliance
  14. The processor detects OpenTelemetry compliance by checking the following fields:
  15. * `resource` exists as a key and the value is a map
  16. * `resource` either doesn't contain an `attributes` field, or contains an `attributes` field of type map
  17. * `scope` is either missing or a map
  18. * `attributes` is either missing or a map
  19. * `body` is either missing or a map
  20. * `body` either doesn't contain a `text` field, or contains a `text` field of type `String`
  21. * `body` either doesn't contain a `structured` field, or contains a `structured` field that is not of type `String`
  22. If all of these conditions are met, the document is considered OpenTelemetry-compliant and is not modified by the processor.
  23. [[normalize-for-stream-normalization]]
  24. ==== Normalization
  25. If the document is not OpenTelemetry-compliant, the processor normalizes it as follows:
  26. * Specific ECS fields are renamed to have their corresponding OpenTelemetry Semantic Conventions attribute names. These include the following:
  27. +
  28. |======
  29. | ECS Field | Semantic Conventions Attribute |
  30. | `span.id` | `span_id` |
  31. | `trace.id` | `trace_id` |
  32. | `message` | `body.text` |
  33. | `log.level` | `severity_text` |
  34. |======
  35. +
  36. The processor first looks for the nested form of the ECS field and if such does not exist, it looks for a top-level field with the dotted field name.
  37. * Other specific ECS fields that describe resources and have corresponding counterparts in the OpenTelemetry Semantic Conventions are moved to the `resource.attribtues` map. Fields that are considered resource attributes are such that conform to the following conditions:
  38. ** They are ECS fields that have corresponding counterparts (either with
  39. the same name or with a different name) in OpenTelemetry Semantic Conventions.
  40. ** The corresponding OpenTelemetry attribute is defined in
  41. https://github.com/open-telemetry/semantic-conventions/tree/main/model[Semantic Conventions]
  42. within a group that is defined as `type: enitity`.
  43. * All other fields, except for `@timestamp`, are moved to the `attributes` map.
  44. * All non-array entries of the `attributes` and `resource.attributes` maps are flattened. Flattening means that nested objects are merged into their parent object, and the keys are concatenated with a dot. See examples below.
  45. [[normalize-for-stream-examples]]
  46. ==== Examples
  47. If an OpenTelemetry-compliant document is detected, the processor does nothing. For example, the following document will stay unchanged:
  48. ```json
  49. {
  50. "resource": {
  51. "attributes": {
  52. "service.name": "my-service"
  53. }
  54. },
  55. "scope": {
  56. "name": "my-library",
  57. "version": "1.0.0"
  58. },
  59. "attributes": {
  60. "http.method": "GET"
  61. },
  62. "body": {
  63. "text": "Hello, world!"
  64. }
  65. }
  66. ```
  67. If a non-OpenTelemetry-compliant document is detected, the processor normalizes it. For example, the following document:
  68. ```json
  69. {
  70. "@timestamp": "2023-10-01T12:00:00Z",
  71. "service": {
  72. "name": "my-service",
  73. "version": "1.0.0",
  74. "environment": "production",
  75. "language": {
  76. "name": "python",
  77. "version": "3.8"
  78. }
  79. },
  80. "log": {
  81. "level": "INFO"
  82. },
  83. "message": "Hello, world!",
  84. "http": {
  85. "method": "GET",
  86. "url": {
  87. "path": "/api/v1/resource"
  88. },
  89. "headers": [
  90. {
  91. "name": "Authorization",
  92. "value": "Bearer token"
  93. },
  94. {
  95. "name": "User-Agent",
  96. "value": "my-client/1.0"
  97. }
  98. ]
  99. },
  100. "span" : {
  101. "id": "1234567890abcdef"
  102. },
  103. "span.id": "abcdef1234567890",
  104. "trace.id": "abcdef1234567890abcdef1234567890"
  105. }
  106. ```
  107. will be normalized into the following form:
  108. ```json
  109. {
  110. "@timestamp": "2023-10-01T12:00:00Z",
  111. "resource": {
  112. "attributes": {
  113. "service.name": "my-service",
  114. "service.version": "1.0.0",
  115. "service.environment": "production"
  116. }
  117. },
  118. "attributes": {
  119. "service.language.name": "python",
  120. "service.language.version": "3.8",
  121. "http.method": "GET",
  122. "http.url.path": "/api/v1/resource",
  123. "http.headers": [
  124. {
  125. "name": "Authorization",
  126. "value": "Bearer token"
  127. },
  128. {
  129. "name": "User-Agent",
  130. "value": "my-client/1.0"
  131. }
  132. ]
  133. },
  134. "body": {
  135. "text": "Hello, world!"
  136. },
  137. "span_id": "1234567890abcdef",
  138. "trace_id": "abcdef1234567890abcdef1234567890"
  139. }
  140. ```