otel: capture whether process was invoked from a terminal
This commit adds a "terminal" attribute to `BaseMetricAttributes` that allows us to discern whether an invocation was from an interactive terminal or not. Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
@ -1,9 +1,16 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/spf13/cobra"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@ -92,3 +99,91 @@ func TestGetCommandName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStdioAttributes(t *testing.T) {
|
||||
outBuffer := new(bytes.Buffer)
|
||||
errBuffer := new(bytes.Buffer)
|
||||
t.Parallel()
|
||||
for _, tc := range []struct {
|
||||
test string
|
||||
stdinTty bool
|
||||
stdoutTty bool
|
||||
// TODO(laurazard): test stderr
|
||||
expected []attribute.KeyValue
|
||||
}{
|
||||
{
|
||||
test: "",
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.Bool("command.stdin.isatty", false),
|
||||
attribute.Bool("command.stdout.isatty", false),
|
||||
attribute.Bool("command.stderr.isatty", false),
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "",
|
||||
stdinTty: true,
|
||||
stdoutTty: true,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.Bool("command.stdin.isatty", true),
|
||||
attribute.Bool("command.stdout.isatty", true),
|
||||
attribute.Bool("command.stderr.isatty", false),
|
||||
},
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.test, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli := &DockerCli{
|
||||
in: streams.NewIn(io.NopCloser(strings.NewReader(""))),
|
||||
out: streams.NewOut(outBuffer),
|
||||
err: errBuffer,
|
||||
}
|
||||
cli.In().SetIsTerminal(tc.stdinTty)
|
||||
cli.Out().SetIsTerminal(tc.stdoutTty)
|
||||
actual := stdioAttributes(cli)
|
||||
|
||||
assert.Check(t, reflect.DeepEqual(actual, tc.expected))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttributesFromError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
testName string
|
||||
err error
|
||||
expected []attribute.KeyValue
|
||||
}{
|
||||
{
|
||||
testName: "no error",
|
||||
err: nil,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("command.status.code", "0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "non-0 exit code",
|
||||
err: statusError{StatusCode: 127},
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("command.error.type", "generic"),
|
||||
attribute.String("command.status.code", "127"),
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "canceled",
|
||||
err: context.Canceled,
|
||||
expected: []attribute.KeyValue{
|
||||
attribute.String("command.error.type", "canceled"),
|
||||
attribute.String("command.status.code", "1"),
|
||||
},
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
actual := attributesFromError(tc.err)
|
||||
assert.Check(t, reflect.DeepEqual(actual, tc.expected))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user