Skip to content

Commit

Permalink
expose use_number only
Browse files Browse the repository at this point in the history
  • Loading branch information
newly12 committed Jun 25, 2024
1 parent 06b8e50 commit e3b3b43
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .chloggen/json_parser_number_data_type.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ change_type: enhancement
component: pkg/stanza

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: expose json iterator config in json parser
note: Add `use_number` config in json parser to support decode into int or float properly

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33696]
Expand Down
43 changes: 11 additions & 32 deletions pkg/stanza/docs/operators/json_parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,22 @@ The `json_parser` operator parses the string-type field selected by `parse_from`

### Configuration Fields

| Field | Default | Description |
| --- | --- | --- |
| `id` | `json_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` | `attributes` | 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). |
| `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. |
| `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. |
| `jsontier_config` | `nil` | An optional jsontier config block. See below for details. |
| Field | Default | Description |
| --- | --- | --- |
| `id` | `json_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` | `attributes` | 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). |
| `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. |
| `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. |
| `use_number` | `false` | Numbers like `int` and `float` are parsed as `float64` by default, when `use_number` is enabled, numbers are parsed as `json.Number` and then converted to `int64` or `float64` based on the value. |

### Embedded Operations

The `json_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).

### `jsoniter_config` Configuration

The `json_parser` operator uses the [json-iterator](https://github.com/json-iterator/go) as the underlying json parser, the default config is [ConfigFastest](https://pkg.go.dev/github.com/json-iterator/go#pkg-variables).

In additional, this `jsoniter_config` block allows you to configure the json parser with a custom configuration. Here are available fields that map to the corresponding fields in [json-iterator Config](https://pkg.go.dev/github.com/json-iterator/go#Config):

| Field | Default | Description |
|--------------------------------------|---------|----------------------------------------------------|
| `indention_step` | 0 | json-iterator.Config.IndentionStep |
| `marshal_float_with_6_digits` | `false` | json-iterator.Config.MarshalFloatWith6Digits |
| `escape_html` | `false` | json-iterator.Config.EscapeHTML |
| `sort_map_keys` | `false` | json-iterator.Config.SortMapKeys |
| `use_number` | `false` | json-iterator.Config.UseNumber |
| `disallow_unknown_fields` | `false` | json-iterator.Config.DisallowUnknownFields |
| `tag_key` | `` | json-iterator.Config.TagKey |
| `only_tagged_field` | `false` | json-iterator.Config.OnlyTaggedField |
| `validate_json_raw_message` | `false` | json-iterator.Config.ValidateJsonRawMessage |
| `object_field_must_be_simple_string` | `false` | json-iterator.Config.ObjectFieldMustBeSimpleString |
| `case_sensitive` | `false` | json-iterator.Config.CaseSensitive |

numbers like `int` and `float` are parsed as `float64` by default, when `use_number` is enabled, numbers are parsed as `json.Number` and then coverted to `int64` or `float64` based on the value.

### Example Configurations

Expand Down
51 changes: 11 additions & 40 deletions pkg/stanza/operator/parser/json/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,7 @@ func NewConfigWithID(operatorID string) *Config {
type Config struct {
helper.ParserConfig `mapstructure:",squash"`

*JsoniterConfig `mapstructure:"jsoniter_config,omitempty"`
}

type JsoniterConfig struct {
IndentionStep int `mapstructure:"indention_step"`
MarshalFloatWith6Digits bool `mapstructure:"marshal_float_with_6_digits"`
EscapeHTML bool `mapstructure:"escape_html"`
SortMapKeys bool `mapstructure:"sort_map_keys"`
UseNumber bool `mapstructure:"use_number"`
DisallowUnknownFields bool `mapstructure:"disallow_unknown_fields"`
TagKey string `mapstructure:"tag_key"`
OnlyTaggedField bool `mapstructure:"only_tagged_field"`
ValidateJsonRawMessage bool `mapstructure:"validate_json_raw_message"`
ObjectFieldMustBeSimpleString bool `mapstructure:"object_field_must_be_simple_string"`
CaseSensitive bool `mapstructure:"case_sensitive"`
}

func (jc JsoniterConfig) toJsoniterAPI() jsoniter.API {
return jsoniter.Config{
IndentionStep: jc.IndentionStep,
MarshalFloatWith6Digits: jc.MarshalFloatWith6Digits,
EscapeHTML: jc.EscapeHTML,
SortMapKeys: jc.SortMapKeys,
UseNumber: jc.UseNumber,
DisallowUnknownFields: jc.DisallowUnknownFields,
TagKey: jc.TagKey,
OnlyTaggedField: jc.OnlyTaggedField,
ValidateJsonRawMessage: jc.ValidateJsonRawMessage,
ObjectFieldMustBeSimpleString: jc.ObjectFieldMustBeSimpleString,
CaseSensitive: jc.CaseSensitive,
}.Froze()
UseNumber bool `mapstructure:"use_number"`
}

// Build will build a JSON parser operator.
Expand All @@ -73,18 +43,19 @@ func (c Config) Build(set component.TelemetrySettings) (operator.Operator, error
return nil, err
}

var json jsoniter.API
var convertNumber bool
if c.JsoniterConfig != nil {
json = c.JsoniterConfig.toJsoniterAPI()
convertNumber = c.JsoniterConfig.UseNumber
} else {
json = jsoniter.ConfigFastest
// jsonConfig defaults to jsoniter.ConfigFastest for backward compatibility
var jsonConfig = jsoniter.Config{
EscapeHTML: false,
MarshalFloatWith6Digits: true,
ObjectFieldMustBeSimpleString: true,
}

// override the default values with the values from the config
jsonConfig.UseNumber = c.UseNumber

return &Parser{
ParserOperator: parserOperator,
json: json,
useNumber: convertNumber,
json: jsonConfig.Froze(),
useNumber: c.UseNumber,
}, nil
}
4 changes: 1 addition & 3 deletions pkg/stanza/operator/parser/json/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ func TestConfig(t *testing.T) {
Name: "use_number",
Expect: func() *Config {
p := NewConfig()
p.JsoniterConfig = &JsoniterConfig{
UseNumber: true,
}
p.UseNumber = true
return p
}(),
},
Expand Down
10 changes: 5 additions & 5 deletions pkg/stanza/operator/parser/json/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestParser(t *testing.T) {
{
"use_number_simple",
func(p *Config) {
p.JsoniterConfig = &JsoniterConfig{UseNumber: true}
p.UseNumber = true
},
&entry.Entry{
Body: `{"int":1,"float":1.0}`,
Expand All @@ -158,7 +158,7 @@ func TestParser(t *testing.T) {
{
"use_number_nested",
func(p *Config) {
p.JsoniterConfig = &JsoniterConfig{UseNumber: true}
p.UseNumber = true
},
&entry.Entry{
Body: `{"int":1,"float":1.0,"nested":{"int":2,"float":2.0}}`,
Expand All @@ -178,7 +178,7 @@ func TestParser(t *testing.T) {
{
"use_number_arrays",
func(p *Config) {
p.JsoniterConfig = &JsoniterConfig{UseNumber: true}
p.UseNumber = true
},
&entry.Entry{
Body: `{"int":1,"float":1.0,"nested":{"int":2,"float":2.0},"array":[1,2]}`,
Expand All @@ -199,7 +199,7 @@ func TestParser(t *testing.T) {
{
"use_number_mixed_arrays",
func(p *Config) {
p.JsoniterConfig = &JsoniterConfig{UseNumber: true}
p.UseNumber = true
},
&entry.Entry{
Body: `{"int":1,"float":1.0,"mixed_array":[1,1.5,2]}`,
Expand All @@ -216,7 +216,7 @@ func TestParser(t *testing.T) {
{
"use_number_nested_arrays",
func(p *Config) {
p.JsoniterConfig = &JsoniterConfig{UseNumber: true}
p.UseNumber = true
},
&entry.Entry{
Body: `{"int":1,"float":1.0,"nested":{"int":2,"float":2.0,"array":[1,2]},"array":[3,4]}`,
Expand Down
3 changes: 1 addition & 2 deletions pkg/stanza/operator/parser/json/testdata/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@ timestamp:
layout: '%Y-%m-%d'
use_number:
type: json_parser
jsoniter_config:
use_number: true
use_number: true

0 comments on commit e3b3b43

Please sign in to comment.