diff --git a/.chloggen/add_jarray_parser_and_assign_keys_transformer.yaml b/.chloggen/add_jarray_parser_and_assign_keys_transformer.yaml
new file mode 100644
index 000000000000..f3349a1ea59b
--- /dev/null
+++ b/.chloggen/add_jarray_parser_and_assign_keys_transformer.yaml
@@ -0,0 +1,18 @@
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: enhancement
+
+# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
+component: pkg/stanza
+
+# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
+note: Add a json array parser operator and an assign keys transformer.
+
+# One or more tracking issues related to the change
+issues: [30321]
+
+# (Optional) One or more lines of additional information to render under the primary note.
+# These lines will be padded with 2 spaces and then inserted directly into the document.
+# Use pipe (|) for multiline entries.
+subtext: |
+ Json array parser opreator can be used to parse a json array string input into a list of objects. |
+ Assign keys transformer can be used to assigns keys from the configuration to an input list
diff --git a/cmd/configschema/go.mod b/cmd/configschema/go.mod
index 94d94ed80e89..ae35a5edd64e 100644
--- a/cmd/configschema/go.mod
+++ b/cmd/configschema/go.mod
@@ -602,6 +602,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vincent-petithory/dataurl v1.0.0 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
diff --git a/cmd/configschema/go.sum b/cmd/configschema/go.sum
index 0094dbe58745..5301ecacf423 100644
--- a/cmd/configschema/go.sum
+++ b/cmd/configschema/go.sum
@@ -1505,6 +1505,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
diff --git a/cmd/otelcontribcol/go.mod b/cmd/otelcontribcol/go.mod
index 49974134e74e..56956cfa6c9e 100644
--- a/cmd/otelcontribcol/go.mod
+++ b/cmd/otelcontribcol/go.mod
@@ -635,6 +635,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vincent-petithory/dataurl v1.0.0 // indirect
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 // indirect
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
diff --git a/cmd/otelcontribcol/go.sum b/cmd/otelcontribcol/go.sum
index ec88c6a77b84..a40339096ef6 100644
--- a/cmd/otelcontribcol/go.sum
+++ b/cmd/otelcontribcol/go.sum
@@ -1519,6 +1519,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=
diff --git a/cmd/oteltestbedcol/go.mod b/cmd/oteltestbedcol/go.mod
index 6590f1f74091..0e562f19e56c 100644
--- a/cmd/oteltestbedcol/go.mod
+++ b/cmd/oteltestbedcol/go.mod
@@ -211,6 +211,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.etcd.io/bbolt v1.3.8 // indirect
diff --git a/cmd/oteltestbedcol/go.sum b/cmd/oteltestbedcol/go.sum
index 764433d58f1a..b3d401f2089c 100644
--- a/cmd/oteltestbedcol/go.sum
+++ b/cmd/oteltestbedcol/go.sum
@@ -623,6 +623,8 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/exporter/datadogexporter/go.mod b/exporter/datadogexporter/go.mod
index 3836370b5e92..0901da0ff11f 100644
--- a/exporter/datadogexporter/go.mod
+++ b/exporter/datadogexporter/go.mod
@@ -223,6 +223,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/zorkian/go-datadog-api v2.30.0+incompatible // indirect
diff --git a/exporter/datadogexporter/go.sum b/exporter/datadogexporter/go.sum
index 08c2419cc42c..d81822c3ccf4 100644
--- a/exporter/datadogexporter/go.sum
+++ b/exporter/datadogexporter/go.sum
@@ -717,6 +717,8 @@ github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
diff --git a/exporter/datadogexporter/integrationtest/go.sum b/exporter/datadogexporter/integrationtest/go.sum
index 05e229fd7ba2..1ad629e4f7dc 100644
--- a/exporter/datadogexporter/integrationtest/go.sum
+++ b/exporter/datadogexporter/integrationtest/go.sum
@@ -570,6 +570,7 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
diff --git a/extension/healthcheckextension/go.mod b/extension/healthcheckextension/go.mod
index ef00e349be4c..951fc72c5953 100644
--- a/extension/healthcheckextension/go.mod
+++ b/extension/healthcheckextension/go.mod
@@ -91,6 +91,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configauth v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/extension/healthcheckextension/go.sum b/extension/healthcheckextension/go.sum
index 0f3c0f35c67f..19b2bafb73a6 100644
--- a/extension/healthcheckextension/go.sum
+++ b/extension/healthcheckextension/go.sum
@@ -341,6 +341,8 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/go.mod b/go.mod
index e2675d7ab99c..323a1772a7cf 100644
--- a/go.mod
+++ b/go.mod
@@ -605,6 +605,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vincent-petithory/dataurl v1.0.0 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
diff --git a/go.sum b/go.sum
index a6ae23af05e9..02a6f4d02dc2 100644
--- a/go.sum
+++ b/go.sum
@@ -1510,6 +1510,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
diff --git a/pkg/stanza/adapter/register.go b/pkg/stanza/adapter/register.go
index 0197e6d58943..8105ef17d587 100644
--- a/pkg/stanza/adapter/register.go
+++ b/pkg/stanza/adapter/register.go
@@ -8,6 +8,7 @@ import (
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/output/stdout"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/csv"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/json"
+ _ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/jsonarray"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/keyvalue"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/regex"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/scope"
@@ -17,6 +18,7 @@ import (
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/trace"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/uri"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/add"
+ _ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/assignkeys"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/copy"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/filter"
_ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/flatten"
diff --git a/pkg/stanza/docs/operators/README.md b/pkg/stanza/docs/operators/README.md
index 69b42906df53..3ee3744a6f72 100644
--- a/pkg/stanza/docs/operators/README.md
+++ b/pkg/stanza/docs/operators/README.md
@@ -18,6 +18,7 @@ Inputs:
Parsers:
- [csv_parser](./csv_parser.md)
- [json_parser](./json_parser.md)
+- [json_array_parser](./json_array_parser.md)
- [regex_parser](./regex_parser.md)
- [scope_name_parser](./scope_name_parser.md)
- [syslog_parser](./syslog_parser.md)
@@ -43,3 +44,4 @@ General purpose:
- [retain](./retain.md)
- [router](./router.md)
- [unquote](./unquote.md)
+- [assign_keys](./assign_keys.md)
diff --git a/pkg/stanza/docs/operators/assign_keys.md b/pkg/stanza/docs/operators/assign_keys.md
new file mode 100644
index 000000000000..57a90f3bfa0a
--- /dev/null
+++ b/pkg/stanza/docs/operators/assign_keys.md
@@ -0,0 +1,99 @@
+## `assign_keys` operator
+
+The `assign_keys` assigns keys from the configuration to an input list. the output is a map containing these key-value pairs
+
+### Configuration Fields
+
+| Field | Default | Description |
+| --- | --- | --- |
+| `id` | `assign_keys` | A unique identifier for the operator. |
+| `output` | Next in pipeline | The connected operator(s) that will receive all outbound entries. |
+| `field` | required | The [field](../types/field.md) to assign keys to. |
+| `keys` | required | The list of strings to be used as the keys to the input list's values. Its length is expected to be equal to the length of the values list from field. In case there is a mismatch, an error will result. |
+| `on_error` | `send` | The behavior of the operator if it encounters an error. See [on_error](../types/on_error.md). |
+| `if` | | An [expression](../types/expression.md) that, when set, will be evaluated to determine whether this operator should be used for the given entry. This allows you to do easy conditional parsing without branching logic with routers. |
+
+### Example Configurations:
+
+
+Assign keys to a list in body
+
+
+
+```yaml
+- type: assign_keys
+ field: body
+ keys: ["foo", "bar", "charlie", "foxtrot"]
+```
+
+
+ Input Entry | Output Entry |
+
+
+
+```json
+{
+ "body": [1, "debug", "Debug Message", true]
+}
+```
+
+ |
+
+
+```json
+ {
+ "body": {
+ "foo": 1,
+ "bar": "debug",
+ "charlie": "Debug Message",
+ "foxtrot": true,
+ }
+ }
+```
+
+ |
+
+
+
+Assign keys to a list in an attributes field
+
+
+
+```yaml
+- type: assign_keys
+ field: attributes.input
+ keys: ["foo", "bar"]
+```
+
+
+ Input Entry | Output Entry |
+
+
+
+```json
+{
+ "attributes": {
+ "input": [1, "debug"],
+ "field2": "unchanged",
+ }
+}
+```
+
+ |
+
+
+```json
+{
+ "attributes": {
+ "input": {
+ "foo": 1,
+ "bar": "debug",
+ },
+ "field2": "unchanged",
+ }
+}
+```
+
+ |
+
+
\ No newline at end of file
diff --git a/pkg/stanza/docs/operators/json_array_parser.md b/pkg/stanza/docs/operators/json_array_parser.md
new file mode 100644
index 000000000000..39c980ee33d3
--- /dev/null
+++ b/pkg/stanza/docs/operators/json_array_parser.md
@@ -0,0 +1,129 @@
+## `json_array_parser` operator
+
+The `json_array_parser` operator parses the string-type field selected by `parse_from` assumed to be of a json array format into a list.
+A JArray string (or a json array string) is a string that represents a JSON array. A JSON array is a type of data structure that is used to store data in a structured way. It consists of an ordered list of values that can be either strings, numbers, objects, or even other arrays.
+#### Examples:
+a simple json array string with strictly strings in it:
+```
+"[\"Foo\", \"Bar\", \"Charlie\"]"
+```
+
+json array after parsing:
+```json
+["Foo", "Bar", "Charlie"]
+```
+
+a more complex json array string with different types in it without nested objects:
+```
+"[\"Hello\", 42, true, null]"
+```
+
+json array after parsing:
+```json
+["Hello", 42, true, null]
+```
+
+a more complex json array string with different types in it with nested objects:
+```
+"[\"Hello\", 42, {\"name\": \"Alice\", \"age\": 25}, [1, 2, 3], true, null]"
+```
+
+json array after parsing:
+```json
+["Hello", 42, {"name": "Alice", "age": 25}, [1, 2, 3], true, null]
+```
+
+Notice that for this example, the current parser will parse every nested object as a string and so the result is actually this -
+```json
+["Hello", 42, "{\"name\": \"Alice\", \"age\": 25}", "[1, 2, 3]", true, null]
+```
+
+More information on json arrays can be found [here](https://json-schema.org/understanding-json-schema/reference/array)
+
+
+### Configuration Fields
+
+| Field | Default | Description |
+|--------------------|------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | `json_array_parser` | A unique identifier for the operator. |
+| `output` | Next in pipeline | The connected operator(s) that will receive all outbound entries. |
+| `parse_from` | `body` | The [field](../types/field.md) from which the value will be parsed. |
+| `parse_to` | required. can be one of `body` or a nested field inside `body`, `attributes` or `resource` (ie `attributes.parsed`) | The [field](../types/field.md) to which the value will be parsed. |
+| `on_error` | `send` | The behavior of the operator if it encounters an error. See [on_error](../types/on_error.md). |
+| `timestamp` | `nil` | An optional [timestamp](../types/timestamp.md) block which will parse a timestamp field before passing the entry to the output operator. |
+| `severity` | `nil` | An optional [severity](../types/severity.md) block which will parse a severity field before passing the entry to the output operator. |
+
+### Embedded Operations
+
+The `json_array_parser` can be configured to embed certain operations such as timestamp and severity parsing. For more information, see [complex parsers](../types/parsers.md#complex-parsers).
+
+### Example Configurations
+
+#### Parse the field `body` with a json array parser into an attributes field
+
+Configuration:
+
+```yaml
+- type: json_array_parser
+ parse_from: body
+ parse_to: attributes.output
+```
+
+
+ Input Entry | Output Entry |
+
+
+
+```json
+{
+ "body": "[1,\"debug\",\"Debug Message\", true]"
+}
+```
+
+ |
+
+
+```json
+{
+ "attributes": {
+ "output": [1, "debug", "Debug Message", true]
+ }
+}
+```
+
+ |
+
+
+
+#### Parse the field `body` with a json array parser
+
+Configuration:
+
+```yaml
+- type: json_array_parser
+ parse_to: body
+```
+
+
+ Input Entry | Output Entry |
+
+
+
+```json
+{
+ "body": "[1,\"debug\",\"Debug Message\", true]"
+}
+```
+
+ |
+
+
+```json
+{
+ "body": [1, "debug", "Debug Message", true]
+}
+```
+
+ |
+
+
\ No newline at end of file
diff --git a/pkg/stanza/go.mod b/pkg/stanza/go.mod
index f9d645396f9f..ff9ba46c410f 100644
--- a/pkg/stanza/go.mod
+++ b/pkg/stanza/go.mod
@@ -14,6 +14,7 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.92.0
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.92.0
github.com/stretchr/testify v1.8.4
+ github.com/valyala/fastjson v1.6.4
go.opentelemetry.io/collector/component v0.92.1-0.20240118172122-8131d31601b8
go.opentelemetry.io/collector/config/configtls v0.92.1-0.20240118172122-8131d31601b8
go.opentelemetry.io/collector/confmap v0.92.1-0.20240118172122-8131d31601b8
diff --git a/pkg/stanza/go.sum b/pkg/stanza/go.sum
index 320e611a71f6..b47251ba44b8 100644
--- a/pkg/stanza/go.sum
+++ b/pkg/stanza/go.sum
@@ -264,6 +264,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/pkg/stanza/operator/parser/jsonarray/config_test.go b/pkg/stanza/operator/parser/jsonarray/config_test.go
new file mode 100644
index 000000000000..8a9af6933d70
--- /dev/null
+++ b/pkg/stanza/operator/parser/jsonarray/config_test.go
@@ -0,0 +1,58 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package jsonarray
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/operatortest"
+)
+
+func TestConfig(t *testing.T) {
+ // Manually adding operator to the Registry as its behind a feature gate
+ operator.Register(operatorType, func() operator.Builder { return NewConfig() })
+
+ operatortest.ConfigUnmarshalTests{
+ DefaultConfig: NewConfig(),
+ TestsFile: filepath.Join(".", "testdata", "config.yaml"),
+ Tests: []operatortest.ConfigUnmarshalTest{
+ {
+ Name: "basic",
+ Expect: func() *Config {
+ p := NewConfig()
+ p.ParseFrom = entry.NewBodyField("message")
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField("messageParsed")}
+ return p
+ }(),
+ },
+ {
+ Name: "parse_to_attributes",
+ Expect: func() *Config {
+ p := NewConfig()
+ p.ParseFrom = entry.NewBodyField()
+ p.ParseTo = entry.RootableField{Field: entry.NewAttributeField("output")}
+ return p
+ }(),
+ },
+ {
+ Name: "parse_to_body",
+ Expect: func() *Config {
+ p := NewConfig()
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ return p
+ }(),
+ },
+ {
+ Name: "parse_to_resource",
+ Expect: func() *Config {
+ p := NewConfig()
+ p.ParseTo = entry.RootableField{Field: entry.NewResourceField("output")}
+ return p
+ }(),
+ },
+ },
+ }.Run(t)
+}
diff --git a/pkg/stanza/operator/parser/jsonarray/json_array_parser.go b/pkg/stanza/operator/parser/jsonarray/json_array_parser.go
new file mode 100644
index 000000000000..2e687eb5ff46
--- /dev/null
+++ b/pkg/stanza/operator/parser/jsonarray/json_array_parser.go
@@ -0,0 +1,126 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package jsonarray // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/jsonarray"
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "github.com/valyala/fastjson"
+ "go.opentelemetry.io/collector/featuregate"
+ "go.uber.org/zap"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/helper"
+)
+
+const operatorType = "json_array_parser"
+
+var jsonArrayParserFeatureGate = featuregate.GlobalRegistry().MustRegister(
+ "logs.jsonParserArray",
+ featuregate.StageAlpha,
+ featuregate.WithRegisterDescription("When enabled, allows usage of `json_array_parser`."),
+ featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30321"),
+)
+
+func init() {
+ if jsonArrayParserFeatureGate.IsEnabled() {
+ operator.Register(operatorType, func() operator.Builder { return NewConfig() })
+ }
+}
+
+// NewConfig creates a new json array parser config with default values
+func NewConfig() *Config {
+ return NewConfigWithID(operatorType)
+}
+
+// NewConfigWithID creates a new json array parser config with default values
+func NewConfigWithID(operatorID string) *Config {
+ return &Config{
+ ParserConfig: helper.NewParserConfig(operatorID, operatorType),
+ }
+}
+
+// Config is the configuration of a json array parser operator.
+type Config struct {
+ helper.ParserConfig `mapstructure:",squash"`
+}
+
+// Build will build a json array parser operator.
+func (c Config) Build(logger *zap.SugaredLogger) (operator.Operator, error) {
+ parserOperator, err := c.ParserConfig.Build(logger)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Parser{
+ ParserOperator: parserOperator,
+ pool: new(fastjson.ParserPool),
+ }, nil
+}
+
+// Parser is an operator that parses json array in an entry.
+type Parser struct {
+ helper.ParserOperator
+ pool *fastjson.ParserPool
+}
+
+// Process will parse an entry for json array.
+func (r *Parser) Process(ctx context.Context, e *entry.Entry) error {
+ return r.ParserOperator.ProcessWith(ctx, e, r.parse)
+}
+
+func (r *Parser) parse(value any) (any, error) {
+ jArrayLine, err := valueAsString(value)
+ if err != nil {
+ return nil, err
+ }
+
+ p := r.pool.Get()
+ v, err := p.Parse(jArrayLine)
+ r.pool.Put(p)
+ if err != nil {
+ return nil, errors.New("failed to parse entry")
+ }
+
+ jArray := v.GetArray() // a is a []*Value slice
+ parsedValues := make([]any, len(jArray))
+ for i := range jArray {
+ switch jArray[i].Type() {
+ case fastjson.TypeNumber:
+ parsedValues[i] = jArray[i].GetInt64()
+ case fastjson.TypeString:
+ parsedValues[i] = string(jArray[i].GetStringBytes())
+ case fastjson.TypeTrue:
+ parsedValues[i] = true
+ case fastjson.TypeFalse:
+ parsedValues[i] = false
+ case fastjson.TypeNull:
+ parsedValues[i] = nil
+ case fastjson.TypeObject:
+ // Nested objects handled as a string since this parser doesn't support nested headers
+ parsedValues[i] = jArray[i].String()
+ default:
+ return nil, errors.New("failed to parse entry: " + string(jArray[i].MarshalTo(nil)))
+ }
+ }
+
+ return parsedValues, nil
+}
+
+// valueAsString interprets the given value as a string.
+func valueAsString(value any) (string, error) {
+ var s string
+ switch t := value.(type) {
+ case string:
+ s += t
+ case []byte:
+ s += string(t)
+ default:
+ return s, fmt.Errorf("type '%T' cannot be parsed as json array", value)
+ }
+
+ return s, nil
+}
diff --git a/pkg/stanza/operator/parser/jsonarray/json_array_parser_test.go b/pkg/stanza/operator/parser/jsonarray/json_array_parser_test.go
new file mode 100644
index 000000000000..7536e2689a8d
--- /dev/null
+++ b/pkg/stanza/operator/parser/jsonarray/json_array_parser_test.go
@@ -0,0 +1,351 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package jsonarray
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/testutil"
+)
+
+func newTestParser(t *testing.T) *Parser {
+ cfg := NewConfigWithID("test")
+ op, err := cfg.Build(testutil.Logger(t))
+ require.NoError(t, err)
+ return op.(*Parser)
+}
+
+func TestParserBuildFailure(t *testing.T) {
+ cfg := NewConfigWithID("test")
+ cfg.OnError = "invalid_on_error"
+ _, err := cfg.Build(testutil.Logger(t))
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "invalid `on_error` field")
+}
+
+func TestParserInvalidType(t *testing.T) {
+ parser := newTestParser(t)
+ _, err := parser.parse([]int{})
+ require.Error(t, err)
+ require.Contains(t, err.Error(), "type '[]int' cannot be parsed as json array")
+}
+
+func TestParserJarray(t *testing.T) {
+ cases := []struct {
+ name string
+ configure func(*Config)
+ inputEntries []entry.Entry
+ expectedEntries []entry.Entry
+ expectBuildErr bool
+ expectProcessErr bool
+ }{
+ {
+ "basic",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: []any{"stanza", "INFO", "started agent", int64(42), true},
+ },
+ },
+ false,
+ false,
+ },
+ {
+ "basic-no-parse_to-fail",
+ func(p *Config) {
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: []any{"stanza", "INFO", "started agent", int64(42), true},
+ },
+ },
+ false,
+ true,
+ },
+ {
+ "parse-to-attributes",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewAttributeField("output")}
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ Attributes: map[string]any{
+ "output": []any{"stanza", "INFO", "started agent", int64(42), true},
+ },
+ },
+ },
+ false,
+ false,
+ },
+ {
+ "parse-to-and-from-attributes",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewAttributeField("output")}
+ p.ParseFrom = entry.NewAttributeField("input")
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ Attributes: map[string]any{
+ "input": "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ },
+ },
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ Attributes: map[string]any{
+ "input": "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ "output": []any{"stanza", "INFO", "started agent", int64(42), true},
+ },
+ },
+ },
+ false,
+ false,
+ },
+ {
+ "nested-object",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\", 42, {\"city\": \"New York\", \"zip\": 10001}]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: []any{"stanza", int64(42), "{\"city\":\"New York\",\"zip\":10001}"},
+ },
+ },
+ false,
+ false,
+ },
+ {
+ "basic-multiple-static-bodies",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 42, true]",
+ },
+ {
+ Body: "[\"stanza\",\"ERROR\",\"agent killed\", 9999999, false]",
+ },
+ {
+ Body: "[\"stanza\",\"INFO\",\"started agent\", 0, null]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: []any{"stanza", "INFO", "started agent", int64(42), true},
+ },
+ {
+ Body: []any{"stanza", "ERROR", "agent killed", int64(9999999), false},
+ },
+ {
+ Body: []any{"stanza", "INFO", "started agent", int64(0), nil},
+ },
+ },
+ false,
+ false,
+ },
+ {
+ "comma in quotes",
+ func(p *Config) {
+ p.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ },
+ []entry.Entry{
+ {
+ Body: "[\"stanza\",\"Evergreen,49508\",1,\"555-5555\",\"agent\"]",
+ },
+ },
+ []entry.Entry{
+ {
+ Body: []any{"stanza", "Evergreen,49508", int64(1), "555-5555", "agent"},
+ },
+ },
+ false,
+ false,
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.name, func(t *testing.T) {
+ cfg := NewConfigWithID("test")
+ cfg.OutputIDs = []string{"fake"}
+ tc.configure(cfg)
+
+ op, err := cfg.Build(testutil.Logger(t))
+ if tc.expectBuildErr {
+ require.Error(t, err)
+ return
+ }
+ require.NoError(t, err)
+
+ fake := testutil.NewFakeOutput(t)
+ require.NoError(t, op.SetOutputs([]operator.Operator{fake}))
+
+ ots := time.Now()
+ for i := range tc.inputEntries {
+ inputEntry := tc.inputEntries[i]
+ inputEntry.ObservedTimestamp = ots
+ err = op.Process(context.Background(), &inputEntry)
+ if tc.expectProcessErr {
+ require.Error(t, err)
+ return
+ }
+ require.NoError(t, err)
+
+ expectedEntry := tc.expectedEntries[i]
+ expectedEntry.ObservedTimestamp = ots
+ fake.ExpectEntry(t, &expectedEntry)
+ }
+ })
+ }
+}
+
+func TestParserJarrayMultiline(t *testing.T) {
+ cases := []struct {
+ name string
+ input string
+ expected []any
+ }{
+ {
+ "no_newlines",
+ "[\"aaaa\",\"bbbb\",12,true,\"eeee\"]",
+ []any{"aaaa", "bbbb", int64(12), true, "eeee"},
+ },
+ {
+ "first_field",
+ "[\"aa\naa\",\"bbbb\",12,true,\"eeee\"]",
+ []any{"aa\naa", "bbbb", int64(12), true, "eeee"},
+ },
+ {
+ "middle_field",
+ "[\"aaaa\",\"bb\nbb\",12,true,\"eeee\"]",
+ []any{"aaaa", "bb\nbb", int64(12), true, "eeee"},
+ },
+ {
+ "last_field",
+ "[\"aaaa\",\"bbbb\",12,true,\"e\neee\"]",
+ []any{"aaaa", "bbbb", int64(12), true, "e\neee"},
+ },
+ {
+ "multiple_fields",
+ "[\"aaaa\",\"bb\nbb\",12,true,\"e\neee\"]",
+ []any{"aaaa", "bb\nbb", int64(12), true, "e\neee"},
+ },
+ {
+ "multiple_first_field",
+ "[\"a\na\na\na\",\"bbbb\",\"cccc\",\"dddd\",\"eeee\"]",
+ []any{"a\na\na\na", "bbbb", "cccc", "dddd", "eeee"},
+ },
+ {
+ "multiple_middle_field",
+ "[\"aaaa\",\"bbbb\",\"c\nc\nc\nc\",\"dddd\",\"eeee\"]",
+ []any{"aaaa", "bbbb", "c\nc\nc\nc", "dddd", "eeee"},
+ },
+ {
+ "multiple_last_field",
+ "[\"aaaa\",\"bbbb\",\"cccc\",\"dddd\",\"e\ne\ne\ne\"]",
+ []any{"aaaa", "bbbb", "cccc", "dddd", "e\ne\ne\ne"},
+ },
+ {
+ "leading_newline",
+ "[\"\naaaa\",\"bbbb\",\"cccc\",\"dddd\",\"eeee\"]",
+ []any{"\naaaa", "bbbb", "cccc", "dddd", "eeee"},
+ },
+ {
+ "trailing_newline",
+ "[\"aaaa\",\"bbbb\",\"cccc\",\"dddd\",\"eeee\n\"]",
+ []any{"aaaa", "bbbb", "cccc", "dddd", "eeee\n"},
+ },
+ {
+ "leading_newline_field",
+ "[\"aaaa\",\"\nbbbb\",\"\ncccc\",\"\ndddd\",\"eeee\"]",
+ []any{"aaaa", "\nbbbb", "\ncccc", "\ndddd", "eeee"},
+ },
+ {
+ "trailing_newline_field",
+ "[\"aaaa\",\"bbbb\n\",\"cccc\n\",\"dddd\n\",\"eeee\"]",
+ []any{"aaaa", "bbbb\n", "cccc\n", "dddd\n", "eeee"},
+ },
+ {
+ "empty_lines_unquoted",
+ "[\"aa\naa\",\"bbbb\",\"c\nccc\",\"dddd\",\"eee\ne\"]",
+ []any{"aa\naa", "bbbb", "c\nccc", "dddd", "eee\ne"},
+ },
+ {
+ "literal_return",
+ `["aaaa","bb
+bb","cccc","dd
+dd","eeee"]`,
+ []any{"aaaa", "bb\nbb", "cccc", "dd\ndd", "eeee"},
+ },
+ {
+ "return_in_quotes",
+ "[\"aaaa\",\"bbbb\",\"cc\ncc\",\"dddd\",\"eeee\"]",
+ []any{"aaaa", "bbbb", "cc\ncc", "dddd", "eeee"},
+ },
+ }
+ for _, tc := range cases {
+ t.Run(tc.name, func(t *testing.T) {
+ cfg := NewConfigWithID("test")
+ cfg.ParseTo = entry.RootableField{Field: entry.NewBodyField()}
+ cfg.OutputIDs = []string{"fake"}
+
+ op, err := cfg.Build(testutil.Logger(t))
+ require.NoError(t, err)
+
+ fake := testutil.NewFakeOutput(t)
+ require.NoError(t, op.SetOutputs([]operator.Operator{fake}))
+
+ entry := entry.New()
+ entry.Body = tc.input
+ err = op.Process(context.Background(), entry)
+ require.NoError(t, err)
+ fake.ExpectBody(t, tc.expected)
+ fake.ExpectNoEntry(t, 100*time.Millisecond)
+ })
+ }
+}
+
+func TestBuildParserJarray(t *testing.T) {
+ newBasicParser := func() *Config {
+ cfg := NewConfigWithID("test")
+ cfg.OutputIDs = []string{"test"}
+ return cfg
+ }
+
+ t.Run("BasicConfig", func(t *testing.T) {
+ c := newBasicParser()
+ _, err := c.Build(testutil.Logger(t))
+ require.NoError(t, err)
+ })
+}
diff --git a/pkg/stanza/operator/parser/jsonarray/testdata/config.yaml b/pkg/stanza/operator/parser/jsonarray/testdata/config.yaml
new file mode 100644
index 000000000000..479a5a1fa436
--- /dev/null
+++ b/pkg/stanza/operator/parser/jsonarray/testdata/config.yaml
@@ -0,0 +1,14 @@
+basic:
+ type: json_array_parser
+ parse_from: body.message
+ parse_to: body.messageParsed
+parse_to_attributes:
+ type: json_array_parser
+ parse_from: body
+ parse_to: attributes.output
+parse_to_body:
+ type: json_array_parser
+ parse_to: body
+parse_to_resource:
+ type: json_array_parser
+ parse_to: resource.output
diff --git a/pkg/stanza/operator/transformer/assignkeys/assign_keys.go b/pkg/stanza/operator/transformer/assignkeys/assign_keys.go
new file mode 100644
index 000000000000..3e6b41f5accf
--- /dev/null
+++ b/pkg/stanza/operator/transformer/assignkeys/assign_keys.go
@@ -0,0 +1,133 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package assignkeys // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/transformer/assignkeys"
+
+import (
+ "context"
+ "fmt"
+
+ "go.opentelemetry.io/collector/featuregate"
+ "go.uber.org/zap"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/helper"
+)
+
+const operatorType = "assign_keys"
+
+var assignKeysTransformerFeatureGate = featuregate.GlobalRegistry().MustRegister(
+ "logs.assignKeys",
+ featuregate.StageAlpha,
+ featuregate.WithRegisterDescription("When enabled, allows usage of `assign_keys` transformer."),
+ featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30321"),
+)
+
+func init() {
+ if assignKeysTransformerFeatureGate.IsEnabled() {
+ operator.Register(operatorType, func() operator.Builder { return NewConfig() })
+ }
+}
+
+// NewConfig creates a new assign_keys operator config with default values
+func NewConfig() *Config {
+ return NewConfigWithID(operatorType)
+}
+
+// NewConfigWithID creates a new assign_keys operator config with default values
+func NewConfigWithID(operatorID string) *Config {
+ return &Config{
+ TransformerConfig: helper.NewTransformerConfig(operatorID, operatorType),
+ }
+}
+
+// Config is the configuration of a assign_keys operator
+type Config struct {
+ helper.TransformerConfig `mapstructure:",squash"`
+ Field entry.Field `mapstructure:"field"`
+ Keys []string `mapstructure:"keys"`
+}
+
+// Build will build an assign_keys operator from the supplied configuration
+func (c Config) Build(logger *zap.SugaredLogger) (operator.Operator, error) {
+ transformerOperator, err := c.TransformerConfig.Build(logger)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(c.Keys) == 0 {
+ return nil, fmt.Errorf("assign_keys missing required field keys")
+ }
+
+ if _, ok := c.Field.FieldInterface.(entry.BodyField); ok {
+ return &Transformer{
+ TransformerOperator: transformerOperator,
+ Field: c.Field,
+ Keys: c.Keys,
+ }, nil
+ }
+
+ if _, ok := c.Field.FieldInterface.(entry.ResourceField); ok {
+ return &Transformer{
+ TransformerOperator: transformerOperator,
+ Field: c.Field,
+ Keys: c.Keys,
+ }, nil
+ }
+
+ if _, ok := c.Field.FieldInterface.(entry.AttributeField); ok {
+ return &Transformer{
+ TransformerOperator: transformerOperator,
+ Field: c.Field,
+ Keys: c.Keys,
+ }, nil
+ }
+
+ return nil, fmt.Errorf("invalid field type: %T", c.Field.FieldInterface)
+}
+
+// Transformer transforms a list in the entry field into a map. Each value is assigned a key from configuration keys
+type Transformer struct {
+ helper.TransformerOperator
+ Field entry.Field
+ Keys []string
+}
+
+// Process will process an entry with AssignKeys transformation.
+func (p *Transformer) Process(ctx context.Context, entry *entry.Entry) error {
+ return p.ProcessWith(ctx, entry, p.Transform)
+}
+
+// Transform will apply AssignKeys to an entry
+func (p *Transformer) Transform(entry *entry.Entry) error {
+ inputListInterface, ok := entry.Get(p.Field)
+ if !ok {
+ // The field doesn't exist, so ignore it
+ return fmt.Errorf("apply assign_keys: field %s does not exist on entry", p.Field)
+ }
+
+ inputList, ok := inputListInterface.([]any)
+ if !ok {
+ return fmt.Errorf("apply assign_keys: couldn't convert field %s to []any", p.Field)
+ }
+ if len(inputList) != len(p.Keys) {
+ return fmt.Errorf("apply assign_keys: field %s contains %d values while expected keys are %s contain %d keys", p.Field, len(inputList), p.Keys, len(p.Keys))
+ }
+
+ assignedMap := p.AssignKeys(p.Keys, inputList)
+
+ err := entry.Set(p.Field, assignedMap)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (p *Transformer) AssignKeys(keys []string, values []any) map[string]any {
+ outputMap := make(map[string]any, len(keys))
+ for i, key := range keys {
+ outputMap[key] = values[i]
+ }
+
+ return outputMap
+}
diff --git a/pkg/stanza/operator/transformer/assignkeys/assign_keys_test.go b/pkg/stanza/operator/transformer/assignkeys/assign_keys_test.go
new file mode 100644
index 000000000000..36c5874bdcb0
--- /dev/null
+++ b/pkg/stanza/operator/transformer/assignkeys/assign_keys_test.go
@@ -0,0 +1,155 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package assignkeys
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/testutil"
+)
+
+type testCase struct {
+ name string
+ expectErr bool
+ op *Config
+ input func() *entry.Entry
+ output func() *entry.Entry
+}
+
+// test building and processing a given config.
+func TestBuildAndProcess(t *testing.T) {
+ keys := []string{"origin", "sev", "msg", "count", "isBool"}
+ now := time.Now()
+ newTestEntry := func() *entry.Entry {
+ e := entry.New()
+ e.ObservedTimestamp = now
+ e.Timestamp = time.Unix(1586632809, 0)
+ e.Body = []any{"body", "INFO", "started agent", int64(42), true}
+ e.Resource = map[string]any{
+ "input": []any{"resource", "INFO", "started agent", int64(42), true},
+ }
+ e.Attributes = map[string]any{
+ "input": []any{"attribute", "INFO", "started agent", int64(42), true},
+ }
+ return e
+ }
+ cases := []testCase{
+ {
+ "assign_keys_body",
+ false,
+ func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewBodyField()
+ cfg.Keys = keys
+ return cfg
+ }(),
+ newTestEntry,
+ func() *entry.Entry {
+ e := newTestEntry()
+ e.Body = map[string]any{
+ "origin": "body",
+ "sev": "INFO",
+ "msg": "started agent",
+ "count": int64(42),
+ "isBool": true,
+ }
+ return e
+ },
+ },
+ {
+ "assign_keys_attributes",
+ false,
+ func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewAttributeField("input")
+ cfg.Keys = keys
+ return cfg
+ }(),
+ newTestEntry,
+ func() *entry.Entry {
+ e := newTestEntry()
+ e.Attributes = map[string]any{
+ "input": map[string]any{
+ "origin": "attribute",
+ "sev": "INFO",
+ "msg": "started agent",
+ "count": int64(42),
+ "isBool": true,
+ },
+ }
+ return e
+ },
+ },
+ {
+ "assign_keys_resources",
+ false,
+ func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewResourceField("input")
+ cfg.Keys = keys
+ return cfg
+ }(),
+ newTestEntry,
+ func() *entry.Entry {
+ e := newTestEntry()
+ e.Resource = map[string]any{
+ "input": map[string]any{
+ "origin": "resource",
+ "sev": "INFO",
+ "msg": "started agent",
+ "count": int64(42),
+ "isBool": true,
+ },
+ }
+ return e
+ },
+ },
+ {
+ "assign_keys_missing_keys",
+ true,
+ func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewBodyField()
+ return cfg
+ }(),
+ newTestEntry,
+ nil,
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run("BuildandProcess/"+tc.name, func(t *testing.T) {
+ cfg := tc.op
+ cfg.OutputIDs = []string{"fake"}
+ cfg.OnError = "drop"
+
+ op, err := cfg.Build(testutil.Logger(t))
+ if tc.expectErr && err != nil {
+ require.Error(t, err)
+ t.SkipNow()
+ }
+ require.NoError(t, err)
+
+ assignKeys := op.(interface {
+ Process(ctx context.Context, entry *entry.Entry) error
+ })
+ fake := testutil.NewFakeOutput(t)
+ require.NoError(t, op.SetOutputs([]operator.Operator{fake}))
+ val := tc.input()
+ err = assignKeys.Process(context.Background(), val)
+
+ if tc.expectErr {
+ require.Error(t, err)
+ } else {
+ require.NoError(t, err)
+ fake.ExpectEntry(t, tc.output())
+ }
+ })
+ }
+}
diff --git a/pkg/stanza/operator/transformer/assignkeys/config_test.go b/pkg/stanza/operator/transformer/assignkeys/config_test.go
new file mode 100644
index 000000000000..228c2c933a6b
--- /dev/null
+++ b/pkg/stanza/operator/transformer/assignkeys/config_test.go
@@ -0,0 +1,55 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+package assignkeys
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator"
+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/operatortest"
+)
+
+// Test unmarshalling of values into config struct
+func TestUnmarshal(t *testing.T) {
+ // Manually adding operator to the Registry as its behind a feature gate
+ operator.Register(operatorType, func() operator.Builder { return NewConfig() })
+
+ operatortest.ConfigUnmarshalTests{
+ DefaultConfig: NewConfig(),
+ TestsFile: filepath.Join(".", "testdata", "config.yaml"),
+ Tests: []operatortest.ConfigUnmarshalTest{
+ {
+ Name: "assign_keys_body",
+ Expect: func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewBodyField()
+ cfg.Keys = []string{"foo", "bar"}
+ return cfg
+ }(),
+ ExpectErr: false,
+ },
+ {
+ Name: "assign_keys_body_nested",
+ Expect: func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewBodyField("nested")
+ cfg.Keys = []string{"foo", "bar"}
+ return cfg
+ }(),
+ ExpectErr: false,
+ },
+ {
+ Name: "assign_keys_attributes",
+ Expect: func() *Config {
+ cfg := NewConfig()
+ cfg.Field = entry.NewAttributeField("input")
+ cfg.Keys = []string{"foo", "bar"}
+ return cfg
+ }(),
+ ExpectErr: false,
+ },
+ },
+ }.Run(t)
+}
diff --git a/pkg/stanza/operator/transformer/assignkeys/package_test.go b/pkg/stanza/operator/transformer/assignkeys/package_test.go
new file mode 100644
index 000000000000..5f2effedf3b5
--- /dev/null
+++ b/pkg/stanza/operator/transformer/assignkeys/package_test.go
@@ -0,0 +1,14 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package assignkeys
+
+import (
+ "testing"
+
+ "go.uber.org/goleak"
+)
+
+func TestMain(m *testing.M) {
+ goleak.VerifyTestMain(m)
+}
diff --git a/pkg/stanza/operator/transformer/assignkeys/testdata/config.yaml b/pkg/stanza/operator/transformer/assignkeys/testdata/config.yaml
new file mode 100644
index 000000000000..9520f379ecc9
--- /dev/null
+++ b/pkg/stanza/operator/transformer/assignkeys/testdata/config.yaml
@@ -0,0 +1,12 @@
+assign_keys_body:
+ type: assign_keys
+ field: body
+ keys: ["foo", "bar"]
+assign_keys_body_nested:
+ type: assign_keys
+ field: body.nested
+ keys: ["foo", "bar"]
+assign_keys_attributes:
+ type: assign_keys
+ field: attributes.input
+ keys: ["foo", "bar"]
diff --git a/processor/logstransformprocessor/go.mod b/processor/logstransformprocessor/go.mod
index f10191211f8c..afdd754a29a2 100644
--- a/processor/logstransformprocessor/go.mod
+++ b/processor/logstransformprocessor/go.mod
@@ -51,6 +51,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/processor/logstransformprocessor/go.sum b/processor/logstransformprocessor/go.sum
index e87da336dd5f..1251933e7bcf 100644
--- a/processor/logstransformprocessor/go.sum
+++ b/processor/logstransformprocessor/go.sum
@@ -257,6 +257,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/azureeventhubreceiver/go.mod b/receiver/azureeventhubreceiver/go.mod
index 5da0195307ad..425caff77233 100644
--- a/receiver/azureeventhubreceiver/go.mod
+++ b/receiver/azureeventhubreceiver/go.mod
@@ -81,6 +81,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/azureeventhubreceiver/go.sum b/receiver/azureeventhubreceiver/go.sum
index e525fb3d0cce..2a8fd79cf60b 100644
--- a/receiver/azureeventhubreceiver/go.sum
+++ b/receiver/azureeventhubreceiver/go.sum
@@ -332,6 +332,8 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/filelogreceiver/go.mod b/receiver/filelogreceiver/go.mod
index b9d6608e16c4..86c476f0d2db 100644
--- a/receiver/filelogreceiver/go.mod
+++ b/receiver/filelogreceiver/go.mod
@@ -51,6 +51,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/filelogreceiver/go.sum b/receiver/filelogreceiver/go.sum
index 43af39a180f3..fe3dbd268fae 100644
--- a/receiver/filelogreceiver/go.sum
+++ b/receiver/filelogreceiver/go.sum
@@ -261,6 +261,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/journaldreceiver/go.mod b/receiver/journaldreceiver/go.mod
index 49dd77a80dff..ff37242aee53 100644
--- a/receiver/journaldreceiver/go.mod
+++ b/receiver/journaldreceiver/go.mod
@@ -46,6 +46,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/journaldreceiver/go.sum b/receiver/journaldreceiver/go.sum
index 9d8b86399668..fa5f83c45020 100644
--- a/receiver/journaldreceiver/go.sum
+++ b/receiver/journaldreceiver/go.sum
@@ -257,6 +257,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/mongodbatlasreceiver/go.mod b/receiver/mongodbatlasreceiver/go.mod
index 1f92e0c05c31..1492ce9a3513 100644
--- a/receiver/mongodbatlasreceiver/go.mod
+++ b/receiver/mongodbatlasreceiver/go.mod
@@ -63,6 +63,7 @@ require (
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
github.com/stretchr/objx v0.5.0 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/mongodbatlasreceiver/go.sum b/receiver/mongodbatlasreceiver/go.sum
index 0d8070b6b4c4..cbdd9205edd0 100644
--- a/receiver/mongodbatlasreceiver/go.sum
+++ b/receiver/mongodbatlasreceiver/go.sum
@@ -266,6 +266,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/namedpipereceiver/go.mod b/receiver/namedpipereceiver/go.mod
index 7023c4b5e9fc..5e68e0565a14 100644
--- a/receiver/namedpipereceiver/go.mod
+++ b/receiver/namedpipereceiver/go.mod
@@ -48,6 +48,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/namedpipereceiver/go.sum b/receiver/namedpipereceiver/go.sum
index 67a1bf8a69cd..dc7e1ddc4d77 100644
--- a/receiver/namedpipereceiver/go.sum
+++ b/receiver/namedpipereceiver/go.sum
@@ -259,6 +259,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/otlpjsonfilereceiver/go.mod b/receiver/otlpjsonfilereceiver/go.mod
index 6a095a8faabf..59a7d3ca4a47 100644
--- a/receiver/otlpjsonfilereceiver/go.mod
+++ b/receiver/otlpjsonfilereceiver/go.mod
@@ -48,6 +48,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/otlpjsonfilereceiver/go.sum b/receiver/otlpjsonfilereceiver/go.sum
index 4fff10d5dd4e..9143de1b4a04 100644
--- a/receiver/otlpjsonfilereceiver/go.sum
+++ b/receiver/otlpjsonfilereceiver/go.sum
@@ -260,6 +260,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/sqlqueryreceiver/go.mod b/receiver/sqlqueryreceiver/go.mod
index a4a03acfc2fc..54c9412baa73 100644
--- a/receiver/sqlqueryreceiver/go.mod
+++ b/receiver/sqlqueryreceiver/go.mod
@@ -133,6 +133,7 @@ require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
go.opencensus.io v0.24.0 // indirect
diff --git a/receiver/sqlqueryreceiver/go.sum b/receiver/sqlqueryreceiver/go.sum
index e63a426128f3..556aeb07432f 100644
--- a/receiver/sqlqueryreceiver/go.sum
+++ b/receiver/sqlqueryreceiver/go.sum
@@ -477,6 +477,8 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/syslogreceiver/go.mod b/receiver/syslogreceiver/go.mod
index 93f609928955..3a42c1247c1b 100644
--- a/receiver/syslogreceiver/go.mod
+++ b/receiver/syslogreceiver/go.mod
@@ -49,6 +49,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configopaque v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/syslogreceiver/go.sum b/receiver/syslogreceiver/go.sum
index 4c78ddbf95e3..b704c043115d 100644
--- a/receiver/syslogreceiver/go.sum
+++ b/receiver/syslogreceiver/go.sum
@@ -260,6 +260,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/tcplogreceiver/go.mod b/receiver/tcplogreceiver/go.mod
index 5f8cafb6d077..affb69b5eeaa 100644
--- a/receiver/tcplogreceiver/go.mod
+++ b/receiver/tcplogreceiver/go.mod
@@ -48,6 +48,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configopaque v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/tcplogreceiver/go.sum b/receiver/tcplogreceiver/go.sum
index 4c78ddbf95e3..b704c043115d 100644
--- a/receiver/tcplogreceiver/go.sum
+++ b/receiver/tcplogreceiver/go.sum
@@ -260,6 +260,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/udplogreceiver/go.mod b/receiver/udplogreceiver/go.mod
index 2db7adbb0b7a..291869df10c5 100644
--- a/receiver/udplogreceiver/go.mod
+++ b/receiver/udplogreceiver/go.mod
@@ -46,6 +46,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/udplogreceiver/go.sum b/receiver/udplogreceiver/go.sum
index 9d8b86399668..fa5f83c45020 100644
--- a/receiver/udplogreceiver/go.sum
+++ b/receiver/udplogreceiver/go.sum
@@ -257,6 +257,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/receiver/windowseventlogreceiver/go.mod b/receiver/windowseventlogreceiver/go.mod
index 9ee0c8c67590..8a489e5406a5 100644
--- a/receiver/windowseventlogreceiver/go.mod
+++ b/receiver/windowseventlogreceiver/go.mod
@@ -47,6 +47,7 @@ require (
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector v0.92.1-0.20240118172122-8131d31601b8 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.92.1-0.20240118172122-8131d31601b8 // indirect
diff --git a/receiver/windowseventlogreceiver/go.sum b/receiver/windowseventlogreceiver/go.sum
index 9d8b86399668..fa5f83c45020 100644
--- a/receiver/windowseventlogreceiver/go.sum
+++ b/receiver/windowseventlogreceiver/go.sum
@@ -257,6 +257,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/testbed/go.mod b/testbed/go.mod
index 5a3cccb98761..8c05703b54ef 100644
--- a/testbed/go.mod
+++ b/testbed/go.mod
@@ -210,6 +210,7 @@ require (
github.com/tinylib/msgp v1.1.9 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
diff --git a/testbed/go.sum b/testbed/go.sum
index 150a6e34ea27..ebd479e3f7d6 100644
--- a/testbed/go.sum
+++ b/testbed/go.sum
@@ -610,6 +610,8 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/msgpack/v4 v4.3.13 h1:A2wsiTbvp63ilDaWmsk2wjx6xZdxQOvpiNlKBGKKXKI=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=