Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

output: flush complex nested values, not just map[string]string. #68

Closed
wants to merge 3 commits into from

Conversation

pwhelan
Copy link
Contributor

@pwhelan pwhelan commented Apr 5, 2024

send the full nested complex values when flushing to output plugins in Message.Record as a map[string]interface{} instead of as a simple map[string]string. This will allow receiving float64 and other simple types as well as nested records with key/value pairs and arrays.

tests have also been added for this new functionality.

send the full nested complex values when flushing to output plugins
in `Message.Record` as a `map[string]interface{}` instead of as a
simple `map[string]string`. This will allow receiving float64 and
other simple types as well as nested records with key/value pairs
and arrays.

tests have also been added for this new functionality.

Signed-off-by: Phillip Whelan <[email protected]>
cshared.go Outdated
func decodeEntry(tag string, entry []any) (*Message, error) {
var t time.Time

slice := reflect.ValueOf(entry)
Copy link
Contributor

Choose a reason for hiding this comment

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

I know you just moved the code around and changed downbelow the record type, but is there a need to use reflection here? I don't think so...

if len(entry) != 2 { ... }

var t time.Time
switch t := entry[0].(type) { ... }

data, ok := entry[1](map[string]any])
...

Copy link
Contributor

Choose a reason for hiding this comment

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

This was needed to create slice and obtain the types of the first element to distinguish types of the time.
Fluent Bit sometimes uses only BigEndianTime but sometimes a bit of different situations.
When using timestamp with metadata, we need to detect those usages.

Copy link
Contributor

Choose a reason for hiding this comment

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

But the msgpack decoder will already handle the time and use bigEndianTime type. I think we can just go with type assertion instead of reflection.

Copy link
Contributor

@cosmo0920 cosmo0920 Apr 9, 2024

Choose a reason for hiding this comment

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

Ah, it was not effective when I tested. Because once decoded for metadata part which includes timestamp additional metadata, it's just represented with wrapped up as an untyped object not array.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I modified the code in decodeEntry to forego the use of reflect.

cshared_test.go Outdated
if count <= 0 {
return fmt.Errorf("no records flushed")
}
fmt.Print(printout.String())
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't you be doing some assertions here instead of just printing the result?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will add assertions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added assertions, one of them is pretty weird though:

			foo, ok := record["foo"]
			if !ok {
				t.Errorf("unable to access value for foo")
				return nil
			}

			// this is a little bit disconcerting. does the msgpack
			// decoder default to using []uint8 for strings?
			if foostr, okfoo := foo.([]uint8); !okfoo {
				t.Errorf("unable to get value for foo")
				return nil
			} else if string(foostr) != "bar" {
				t.Errorf("invalid value for foo")
				return nil
			}

Apparently the decoder is favouring []uint8 over string (which is technically mostly accurate for C strings... but....).

Copy link
Contributor

@nicolasparada nicolasparada left a comment

Choose a reason for hiding this comment

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

Left some comments. Would be nice to use actual assertion on the tests instead of just printing the results...

cshared.go Outdated
func decodeEntry(tag string, entry []any) (*Message, error) {
var t time.Time

slice := reflect.ValueOf(entry)
Copy link
Contributor

Choose a reason for hiding this comment

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

This was needed to create slice and obtain the types of the first element to distinguish types of the time.
Fluent Bit sometimes uses only BigEndianTime but sometimes a bit of different situations.
When using timestamp with metadata, we need to detect those usages.

cshared_test.go Show resolved Hide resolved
@cosmo0920
Copy link
Contributor

@nicolasparada Any insights? It's OK for you?

nicolasparada added a commit that referenced this pull request May 27, 2024
nicolasparada added a commit that referenced this pull request Jun 6, 2024
* replace msgpack library

* todo: fix time printing

* remove time test

* ci: enable cgo

* ci: C deps

* sudo

* ci: install cmetrics

* include tests from pr #68

* fix test

* test utl
@nicolasparada nicolasparada deleted the pwhelan-output-nested-values branch June 6, 2024 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants