From 7c0838de89f72653e6ff53a1763075796640cb62 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Thu, 19 Nov 2020 17:14:15 +0000 Subject: [PATCH] Add beeline-style propagation of the cmd context to called commands When using something like https://github.com/puppetlabs/rspec_honeycomb_formatter , it would be nice to connect the individual spans to the bigger picture of the buildevent steps and commands. This change uses the beeline's `PropagationContext` marshaling to pass on the current event to the called command. In the style of the rest of the HONEYCOMB_* environment variables and the similarily named `X-Honeycomb-Trace` HTTP header, this establishes `HONEYCOMB_TRACE` to pass the propagation context to other processes. --- README.md | 30 ++++++++++++++++++++++++++++++ cmd_cmd.go | 23 ++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4bf0c94..444fa8b 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,36 @@ jobs: - run: $GOPATH/bin/buildevents cmd $TRAVIS_BUILD_ID $STEP_SPAN_ID go-test -- go test -timeout 2m -mod vendor ./... ``` +## Attaching more traces from your build and test process + +Every command running through `buildevents cmd` will receive a `HONEYCOMB_TRACE` environment variable that contains a marshalled trace propagation context. This can be used to connect more spans to this trace. + +Ruby Beeline example: +```ruby +# at the very start of the command +# establish a command-level span, linking to the buildevent +process_span = Honeycomb.start_span(name: File.basename($PROGRAM_NAME), serialized_trace: ENV['HONEYCOMB_TRACE']) +Honeycomb.add_field_to_trace('process.full_name', $PROGRAM_NAME) + +# if you're not passing sensitive information through CLI args, enable this for more insights. +#Honeycomb.add_field_to_trace('process.args', ARGV) + +# override the HONEYCOMB_TRACE for sub-processes +ENV['HONEYCOMB_TRACE'] = process_span.to_trace_header + +# ensure that the process_span is sent before the process terminates +at_exit do + if $ERROR_INFO&.is_a?(SystemExit) + process_span.add_field('process.exit_code', $ERROR_INFO.status) + elsif $ERROR_INFO + process_span.add_field('process.exit_code', $ERROR_INFO.class.name) + else + process_span.add_field('process.exit_code', 'unknown') + end + process_span.send +end +``` + # Putting it all together We've covered each of the three modes in which `buildevents` is invoked and shown abbreviated examples for each one. Now it's time to look at an entire config to see how they interact: installation, running a build, and finally reporting the whole thing. diff --git a/cmd_cmd.go b/cmd_cmd.go index 41afb5d..1d19a5b 100644 --- a/cmd_cmd.go +++ b/cmd_cmd.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" libhoney "github.com/honeycombio/libhoney-go" + propagation "github.com/honeycombio/beeline-go/propagation" ) func commandCmd(cfg *libhoney.Config, filename *string, ciProvider *string) *cobra.Command { @@ -59,7 +60,19 @@ will be launched via "bash -c" using "exec".`, rand.Read(spanBytes) start := time.Now() - err := runCommand(subcmd) + + // copy out the current set of fields to avoid later modification + localFields := map[string]interface{}{} + for k, v := range ev.Fields() { + localFields[k] = v + } + var spanID = fmt.Sprintf("%x", spanBytes) + prop := &propagation.PropagationContext{ + TraceID: traceID, + ParentID: spanID, + TraceContext: localFields, + } + err := runCommand(subcmd, prop) dur := time.Since(start) // Annotate with arbitrary fields after the command runs @@ -68,7 +81,7 @@ will be launched via "bash -c" using "exec".`, ev.Add(map[string]interface{}{ "trace.parent_id": stepID, - "trace.span_id": fmt.Sprintf("%x", spanBytes), + "trace.span_id": spanID, "service_name": "cmd", "name": name, "duration_ms": dur / time.Millisecond, @@ -91,10 +104,14 @@ will be launched via "bash -c" using "exec".`, return execCmd } -func runCommand(subcmd string) error { +func runCommand(subcmd string, prop *propagation.PropagationContext) error { fmt.Println("running /bin/bash -c", subcmd) cmd := exec.Command("/bin/bash", "-c", subcmd) + cmd.Env = append(os.Environ(), + "HONEYCOMB_TRACE=" + propagation.MarshalHoneycombTraceContext(prop), + ) + cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr