Skip to content

Commit

Permalink
Add beeline-style propagation of the cmd context to called commands
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
DavidS committed Dec 9, 2020
1 parent a29a075 commit 7c0838d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
23 changes: 20 additions & 3 deletions cmd_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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

Expand Down

0 comments on commit 7c0838d

Please sign in to comment.