
Using Go for Scalable Operating System Analytics - marpaia
https://blog.kolide.com/using-go-for-scalable-operating-system-analytics-cb170d85b1c5
======
tetraodonpuffer
Interesting article but I am not sure about the recommendation of writing your
own command parsing instead of using something like mow.cli[1] which seems
fairly lightweight and self-contained.

In terms of logging I am also wondering if something like zerolog[2] might be
a better choice than go-kit's logger given its higher performance

[1] [https://github.com/jawher/mow.cli](https://github.com/jawher/mow.cli) [2]
[https://github.com/rs/zerolog](https://github.com/rs/zerolog)

~~~
marpaia
I use cobra sometimes, it's not that cobra or mow is too heavy, but I think
that the oklog-style command parsing pattern is no more code or boiler-plate
than using a library (for many use-cases) and it reduces developer overhead
because most people are already familiar with how `flag` works. The whole
pattern is really just the normal `flag` library and a switch statement, but
it works really nicely because `flag` is really great and has a lot of
features.

~~~
justinsaccount
Yeah.. I like cobra, but it seems to somewhat force you into using a lot of
globals to accomplish things.

The only downside to the oklog-style seems to be that you can't introspect the
full cli tool at runtime, which rules out things like outputting documentation
or shell completion files.

~~~
zalmoxes
We did use cobra in fleet, and worked hard not to use globals
[https://github.com/kolide/fleet/blob/f909f4808b17ffd5616c6c8...](https://github.com/kolide/fleet/blob/f909f4808b17ffd5616c6c837cb86206c61dbe20/cmd/fleet/serve.go#L45)

It's doable, but it was hard and while cobra is a nice library, it's probably
overkill unless you're a project like kubernetes.

Most projects in Go are very small in terms of configuration surface, and
something like
[https://github.com/kolide/launcher/blob/9dcf149957b9e9757a24...](https://github.com/kolide/launcher/blob/9dcf149957b9e9757a24c300a019b3b8b95a0b3c/cmd/package-
builder/package-builder.go#L153-L174) is much cleaner IMO.

~~~
justinsaccount
Yeah, I think I will try the simpler approach. I generally just have stuff
like

    
    
      tool [-debug] [-store sqlite] cmd [-opt] [arg]
    

So, main needs to bootstraps logger and store and then delegate to downstream
commands that almost always will consume the store and logger.

I'm currently using PersistentPreRunE to bootstrap the logging and store.. but
I'm not really happy with the end result and some things are awkward. Maybe it
would be less awkward if cobra had a 'Context' I could stick things in. The
last issue was I added a version subcommand, which kept creating the store. I
ended up having to do

    
    
      PersistentPreRunE:  func(cmd *cobra.Command, args []string) error { return nil },
      PersistentPostRunE: func(cmd *cobra.Command, args []string) error { return nil },
    

Which would have been a lot simpler if I was doing things manually.

------
carterschonwald
There’s at least a few factual issues in the article. The big one I noticed is
that it attributed the update framework to Docker. Which isn’t true at least
historically.

~~~
zalmoxes
Yes that's true. But Docker did popularize it, at least that's how I initially
read about it.

It's exciting to see that TUF is now a CNCF project.

