Skip to content

Commit

Permalink
allow setting status code and description at the end of background sp…
Browse files Browse the repository at this point in the history
…ans #197 (#201)

* break status code params out to their own helper

they'll also be used by span_end.go

* add support for StatusCode and StatusDescription

* add support for status code and desc on span background end

Adds support to set --status-code and --status-description when calling
otel-cli span end, along with tests.
  • Loading branch information
tobert authored May 12, 2023
1 parent f47323e commit 0f61b87
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 13 deletions.
19 changes: 18 additions & 1 deletion data_for_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,17 @@ var suites = []FixtureSuite{
SpanCount: 1,
EventCount: 1,
},
// this validates options sent to otel-cli span end
CheckFuncs: []CheckFunc{
func(t *testing.T, f Fixture, r Results) {
if r.Span.StatusCode != 2 {
t.Errorf("expected 2 for span status code, but got %d", r.Span.StatusCode)
}
if r.Span.StatusDescription != "I can't do that Dave." {
t.Errorf("got wrong string for status description: %q", r.Span.StatusDescription)
}
},
},
},
{
Name: "otel-cli span event",
Expand All @@ -597,7 +608,13 @@ var suites = []FixtureSuite{
{
Name: "otel-cli span end",
Config: FixtureConfig{
CliArgs: []string{"span", "end", "--sockdir", "."},
CliArgs: []string{
"span", "end",
"--sockdir", ".",
// these are validated by checkfuncs defined above ^^
"--status-code", "error",
"--status-description", "I can't do that Dave.",
},
},
Expect: Results{Config: otelcli.DefaultConfig()},
},
Expand Down
16 changes: 11 additions & 5 deletions otelcli/protobuf_span.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,21 @@ func NewProtobufSpanWithConfig(c Config) tracepb.Span {
span.SpanId = emptySpanId
}

// Only set status description when an error status.
// https://github.com/open-telemetry/opentelemetry-specification/blob/480a19d702470563d32a870932be5ddae798079c/specification/trace/api.md#set-status
SetSpanStatus(&span, c)

return span
}

// SetSpanStatus checks for status code error in the config and sets the
// span's 2 values as appropriate.
// Only set status description when an error status.
// https://github.com/open-telemetry/opentelemetry-specification/blob/480a19d702470563d32a870932be5ddae798079c/specification/trace/api.md#set-status
func SetSpanStatus(span *tracepb.Span, c Config) {
statusCode := SpanStatusStringToInt(c.StatusCode)
if statusCode == tracepb.Status_STATUS_CODE_ERROR {
if statusCode != tracepb.Status_STATUS_CODE_UNSET {
span.Status.Code = statusCode
span.Status.Message = c.StatusDescription
}

return span
}

// generateTraceId generates a random 16 byte trace id
Expand Down
7 changes: 7 additions & 0 deletions otelcli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ func addSpanParams(cmd *cobra.Command) {
cmd.Flags().StringVarP(&config.ServiceName, "service", "s", defaults.ServiceName, "set the name of the application sent on the traces")
// --kind / -k
cmd.Flags().StringVarP(&config.Kind, "kind", "k", defaults.Kind, "set the trace kind, e.g. internal, server, client, producer, consumer")

addSpanStatusParams(cmd)
}

func addSpanStatusParams(cmd *cobra.Command) {
defaults := DefaultConfig()

// --status-code / -sc
cmd.Flags().StringVar(&config.StatusCode, "status-code", defaults.StatusCode, "set the span status code, e.g. unset|ok|error")
// --status-description / -sd
Expand Down
2 changes: 1 addition & 1 deletion otelcli/span_background.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func doSpanBackground(cmd *cobra.Command, args []string) {
// propagation before the server starts, instead of after
propagateTraceparent(span, os.Stdout)

bgs := createBgServer(spanBgSockfile(), span)
bgs := createBgServer(spanBgSockfile(), &span)

// set up signal handlers to cleanly exit on SIGINT/SIGTERM etc
signals := make(chan os.Signal)
Expand Down
15 changes: 10 additions & 5 deletions otelcli/span_background_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ type BgSpanEvent struct {
}

// BgEnd is an empty struct that can be sent to call End().
type BgEnd struct{}
type BgEnd struct {
StatusCode string `json:"status_code"`
StatusDesc string `json:"status_description"`
}

// AddEvent takes a BgSpanEvent from the client and attaches an event to the span.
func (bs BgSpan) AddEvent(bse *BgSpanEvent, reply *BgSpan) error {
Expand Down Expand Up @@ -63,8 +66,10 @@ func (bs BgSpan) Wait(in, reply *struct{}) error {
// End takes a BgEnd (empty) struct, replies with the usual trace info, then
// ends the span end exits the background process.
func (bs BgSpan) End(in *BgEnd, reply *BgSpan) error {
// TODO: maybe accept an end timestamp?
//endSpan(bs.span)
// handle --status-code and --status-description args to span end
c := config.WithStatusCode(in.StatusCode).WithStatusDescription(in.StatusDesc)
SetSpanStatus(bs.span, c)

// running the shutdown as a goroutine prevents the client from getting an
// error here when the server gets closed. defer didn't do the trick.
go bs.shutdown()
Expand All @@ -81,7 +86,7 @@ type bgServer struct {

// createBgServer opens a new span background server on a unix socket and
// returns with the server ready to go. Not expected to block.
func createBgServer(sockfile string, span tracepb.Span) *bgServer {
func createBgServer(sockfile string, span *tracepb.Span) *bgServer {
var err error

bgs := bgServer{
Expand All @@ -97,7 +102,7 @@ func createBgServer(sockfile string, span tracepb.Span) *bgServer {
bgspan := BgSpan{
TraceID: hex.EncodeToString(span.TraceId),
SpanID: hex.EncodeToString(span.SpanId),
span: &span,
span: span,
shutdown: func() { bgs.Shutdown() },
}
// makes methods on BgSpan available over RPC
Expand Down
10 changes: 9 additions & 1 deletion otelcli/span_end.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ func init() {
//spanEndCmd.Flags().StringVar(&config.Timeout, "timeout", defaults.Timeout, "timeout for otel-cli operations, all timeouts in otel-cli use this value")
spanEndCmd.Flags().StringVar(&config.BackgroundSockdir, "sockdir", defaults.BackgroundSockdir, "a directory where a socket can be placed safely")
spanEndCmd.MarkFlagRequired("sockdir")

spanEndCmd.Flags().StringVar(&config.SpanEndTime, "end", defaults.SpanEndTime, "an Unix epoch or RFC3339 timestamp for the end of the span")

addSpanStatusParams(spanEndCmd)
}

func doSpanEnd(cmd *cobra.Command, args []string) {
client, shutdown := createBgClient()

rpcArgs := BgEnd{}
rpcArgs := BgEnd{
StatusCode: config.StatusCode,
StatusDesc: config.StatusDescription,
}

res := BgSpan{}
err := client.Call("BgSpan.End", rpcArgs, &res)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions otlpserver/clievent.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type CliEvent struct {
ElapsedMs int64 `json:"elapsed_ms"`
Attributes map[string]string `json:"attributes"`
ServiceAttributes map[string]string `json:"service_attributes"`
StatusCode int32
StatusDescription string
// for a span this is the start nanos, for an event it's just the timestamp
// mostly here for sorting CliEventList but could be any uint64
Nanos uint64 `json:"nanos"`
Expand Down Expand Up @@ -62,6 +64,8 @@ func (ce CliEvent) ToStringMap() map[string]string {
"end": etime,
"attributes": mapToKVString(ce.Attributes),
"service_attributes": mapToKVString(ce.ServiceAttributes),
"status_code": strconv.FormatInt(int64(ce.StatusCode), 10),
"status_description": ce.StatusDescription,
"is_populated": strconv.FormatBool(ce.IsPopulated),
"server_meta": mapToKVString(ce.ServerMeta),
}
Expand All @@ -88,6 +92,8 @@ func NewCliEventFromSpan(span *v1.Span, scopeSpans *v1.ScopeSpans, rss *v1.Resou
Attributes: make(map[string]string),
ServiceAttributes: make(map[string]string),
Nanos: span.GetStartTimeUnixNano(),
StatusCode: int32(span.GetStatus().Code),
StatusDescription: span.GetStatus().Message,
IsPopulated: true,
ServerMeta: make(map[string]string),
}
Expand Down

0 comments on commit 0f61b87

Please sign in to comment.