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

Structured output proof of concept #35

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Conversation

euclidianAce
Copy link
Member

This introduces an 'event' api where events can be 'emitted' by
commands, which goes through the following pipeline:

  • a set of callbacks are registered with each command (similar to
    script hooks) by name
  • when an event is emitted, one of these names must be provided
  • the data is fed to the registered callback, which returns a Report
    which describes how to log and serialize the data
  • this report is taken by the event api and depending on whether the
    structured output flag is set will either
    • serialize the data to json (with a very basic hand rolled encoder)
      and write it to stdout
    • log it with the given Logger

The basic structure is as such:

command.new {
   name = "my-cool-command",
   description = ":D",
   exec = function(): integer
      event.emit("cool_event", { adjective = "cool" })
      event.emit("cool_event", { adjective = "neat" })
      return 0
   end,
   events = {
      cool_event = function(params: {string:any}): event.Report
         return {
            log_format = "This is from a %(adjective) event happening",
            parameters = { adjective = params.adjective },
         },
      end,
   },
}

Which with unstructured output will produce

$ cyan my-cool-command
     Info This is from a cool event happening
     Info This is from a neat event happening

But with structured output will produce

$ cyan --structured-output my-cool-command
{"event":"cool_event","data":{"adjective":"cool"}}
{"event":"cool_event","data":{"adjective":"neat"}}

This commit adds a little bit of this as a proof of concept to the
current build command, but not for everything that build can log.
But running

$ cyan build --update-all --structured-output --no-script

will produce nicely structured output, and some data massaging with jq
is easy enough. The following will produce an array of files that were
written by build

$ cyan build --update-all --structured-output --no-script | jq -n '[inputs | select(.event == "wrote_file") | .data.file]'

This introduces an 'event' api where events can be 'emitted' by
commands, which goes through the following pipeline:
 - a set of callbacks are registered with each command (similar to
   script hooks) by name
 - when an event is emitted, one of these names must be provided
 - the data is fed to the registered callback, which returns a `Report`
   which describes how to log and serialize the data
 - this report is taken by the event api and depending on whether the
   structured output flag is set will either
    - serialize the data to json (with a very basic hand rolled encoder)
      and write it to stdout
    - log it with the given `Logger`

The basic structure is as such:

	command.new {
	   name = "my-cool-command",
	   description = ":D",
	   exec = function(): integer
	      event.emit("cool_event", { adjective = "cool" })
	      event.emit("cool_event", { adjective = "neat" })
	      return 0
	   end,
	   events = {
	      cool_event = function(params: {string:any}): event.Report
	         return {
	            log_format = "This is from a %(adjective) event happening",
	            parameters = { adjective = params.adjective },
	         },
	      end,
	   },
	}

Which with unstructured output will produce

	$ cyan my-cool-command
	     Info This is from a cool event happening
	     Info This is from a neat event happening

But with structured output will produce

	$ cyan --structured-output my-cool-command
	{"event":"cool_event","data":{"adjective":"cool"}}
	{"event":"cool_event","data":{"adjective":"neat"}}

This commit adds a little bit of this as a proof of concept to the
current build command, but not for everything that `build` can log.
But running

	$ cyan build --update-all --structured-output --no-script

will produce nicely structured output, and some data massaging with jq
is easy enough. The following will produce an array of files that were
written by build

	$ cyan build --update-all --structured-output --no-script | jq -n '[inputs | select(.event == "wrote_file") | .data.file]'
@euclidianAce
Copy link
Member Author

Relevant issue #21

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.

1 participant