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

fix: allow config bools to default to true #969

Merged
merged 7 commits into from
Jan 25, 2024

Conversation

robbkidd
Copy link
Member

@robbkidd robbkidd commented Jan 18, 2024

Which problem is this PR solving?

Short description of the changes

  • add a failing test to reproduce the problem
  • updated config struct fields that are bools defaulting to true to be bool pointers so that nil represents the unset state
  • updated getter functions to handle the pointers
  • add a GetSamplerEnabled() function to HoneycombLoggerConfig to handle pointer defreferencing

Maybe TODO

  • use something (reflect?) to do struct tag lookups to find default values in the getter functions instead of declaring defaults in multiple places
  • keep the default-true-bool-overridden-with-false test?
  • contribute documentation about bool pointer workaround to upstream defaults library?

@robbkidd robbkidd requested a review from a team as a code owner January 18, 2024 20:53
@kentquirk
Copy link
Contributor

Do you want to make this a draft PR until you have code for it?

@fchikwekwe fchikwekwe marked this pull request as draft January 18, 2024 21:22
@robbkidd
Copy link
Member Author

robbkidd commented Jan 18, 2024

Do you want to make this a draft PR until you have code for it?

Certainly! Drafted ... and there should be code for it shortly.

UPDATE: Code added. As is my wont, walking our commits might help understanding the whys and whats of the changes.

@robbkidd robbkidd force-pushed the fabb.bools-should-default-to-true-tho branch from 138ed07 to 4a6404a Compare January 18, 2024 21:49
robbkidd and others added 2 commits January 18, 2024 16:53
Because bool's zero value is false, defaults library cannot determine if a field has not been set. Use a pointer instead! Zero for an unset pointer is nil.

Co-authored-by: Faith Chikwekwe <[email protected]>
@robbkidd robbkidd force-pushed the fabb.bools-should-default-to-true-tho branch from 4a6404a to e2b420a Compare January 18, 2024 21:54
@robbkidd robbkidd force-pushed the fabb.bools-should-default-to-true-tho branch from e2b420a to c33b520 Compare January 18, 2024 21:56
return f.mainConfig.Specialized.CompressPeerCommunication
var compressPeerCommunication bool
if f.mainConfig.Specialized.CompressPeerCommunication == nil {
compressPeerCommunication = true
Copy link
Contributor

Choose a reason for hiding this comment

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

These true values are hardcoded, but we should try and lookup these values from the struct tag. That will require us to use the reflect package mimicking some behavior from the defaults package. Is this something that we want in the scope of this fix?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I'm happy with the hardcoded true values that are only present on struct values that are currently type bool and default true. It might be nice to write a helper function that we can add to add struct values to check is type is bool and default is true.

Copy link
Contributor

Choose a reason for hiding this comment

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

@robbkidd suggested that we either add some code to the validate function to check for struct tag type and value. Or perhaps there is a test that we can add later on to validate any changes to struct tags.

Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of reading the tags, we talked about something like:

type BoolDefaultTrue *bool

That would give us the hook to do some more useful linting or other work to make sure that we keep the contract for those types.

@@ -890,6 +890,31 @@ func TestHoneycombIdFieldsConfigDefault(t *testing.T) {
assert.Equal(t, []string{"trace.parent_id", "parentId"}, c.GetParentIdFieldNames())
}

func TestOverrideConfigDefaults(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Added in the first commit of this PR, demonstrate the 5 bools that default to true don't. Not sure if we keep this test long-term.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's just add a comment to this explaining why it exists.

@@ -59,7 +59,7 @@ func (h *HoneycombLogger) Start() error {
}
}

if loggerConfig.SamplerEnabled {
if *loggerConfig.SamplerEnabled {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should consider adding a getter function for HoneycombLogger.SamplerEnabled so that we do not have to dereference in every time Sampler Enabled is used.

Copy link
Member Author

@robbkidd robbkidd Jan 18, 2024

Choose a reason for hiding this comment

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

A loggerConfig.GetSamplerEnabled() function would also do away with the shenanigans used in test to get a pointer to a bool.

Copy link
Member Author

Choose a reason for hiding this comment

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

During a chat this morning, @kentquirk, @fchikwekwe, and I agreed we should make the SamplerEnabled bool-pointer private and add a getter function to smooth the bool interface. That'll be work on this PR with other ideas to reduce tech debt in a follow-up issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

And I learn that I cannot make the SamplerEnabled field private without breaking the YAML marshal/unmarshal. Still adding the function, though!

@robbkidd robbkidd requested a review from a team January 18, 2024 22:19
@robbkidd robbkidd added type: bug Something isn't working version: bump patch A PR with release-worthy changes and is backwards-compatible. labels Jan 18, 2024
@robbkidd robbkidd marked this pull request as ready for review January 18, 2024 22:20
@@ -119,10 +119,21 @@ type HoneycombLoggerConfig struct {
APIHost string `yaml:"APIHost" default:"https://api.honeycomb.io"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Not in scope for this PR, but accessor functions for all fields on HoneycomLoggerConfig would be nice.

Copy link
Contributor

Choose a reason for hiding this comment

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

I struggle with this; every accessor adds one form of tech debt to save another form of tech debt. In particular, when I broke up the config into subsections, I deliberately did not add accessors for everything.

I don't feel strongly against it, I just wish there was a better way (JS/java properties would be nice but Go doesn't give us those).

@@ -119,10 +119,21 @@ type HoneycombLoggerConfig struct {
APIHost string `yaml:"APIHost" default:"https://api.honeycomb.io"`
APIKey string `yaml:"APIKey" cmdenv:"HoneycombLoggerAPIKey,HoneycombAPIKey"`
Dataset string `yaml:"Dataset" default:"Refinery Logs"`
SamplerEnabled bool `yaml:"SamplerEnabled" default:"true"`
SamplerEnabled *bool `yaml:"SamplerEnabled" default:"true"` // Avoid pointer woe on access, use GetSamplerEnabled() instead.
Copy link
Member Author

@robbkidd robbkidd Jan 19, 2024

Choose a reason for hiding this comment

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

I tossed this comment on the field so that it would be shown by IDEs that do the hover box thing. Like a ⚠️ sign saying "Hey, maybe don't use this directly."

🤔 ... which I suppose is a comment that could be added to all the new *bool fields.

Copy link
Member Author

Choose a reason for hiding this comment

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

Add this comment to all the *bools in a separate commit (easily removed from this PR if that's too much commentary).

Copy link
Contributor

@kentquirk kentquirk left a comment

Choose a reason for hiding this comment

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

I think this is pretty good, and the only thing I'd like to see changed is to define that type for a bool that defaults to true, and use that appropriately; we don't have to get into modifying the defaults package or validating specially unless you see a really easy solution. I wouldn't spend a lot more time on it.

@@ -890,6 +890,31 @@ func TestHoneycombIdFieldsConfigDefault(t *testing.T) {
assert.Equal(t, []string{"trace.parent_id", "parentId"}, c.GetParentIdFieldNames())
}

func TestOverrideConfigDefaults(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's just add a comment to this explaining why it exists.

@@ -119,10 +119,21 @@ type HoneycombLoggerConfig struct {
APIHost string `yaml:"APIHost" default:"https://api.honeycomb.io"`
Copy link
Contributor

Choose a reason for hiding this comment

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

I struggle with this; every accessor adds one form of tech debt to save another form of tech debt. In particular, when I broke up the config into subsections, I deliberately did not add accessors for everything.

I don't feel strongly against it, I just wish there was a better way (JS/java properties would be nice but Go doesn't give us those).

return f.mainConfig.Specialized.CompressPeerCommunication
var compressPeerCommunication bool
if f.mainConfig.Specialized.CompressPeerCommunication == nil {
compressPeerCommunication = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of reading the tags, we talked about something like:

type BoolDefaultTrue *bool

That would give us the hook to do some more useful linting or other work to make sure that we keep the contract for those types.

@fchikwekwe
Copy link
Contributor

Yes, I played around with adding the boolean true type a little bit this week, but I'll bump the rest of this work to be completed in #970.

@fchikwekwe fchikwekwe merged commit 451d00e into main Jan 25, 2024
3 checks passed
@fchikwekwe fchikwekwe deleted the fabb.bools-should-default-to-true-tho branch January 25, 2024 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working version: bump patch A PR with release-worthy changes and is backwards-compatible.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants