diff --git a/src/runtime/pkg/katautils/create.go b/src/runtime/pkg/katautils/create.go index 143b2e3367..98079c53aa 100644 --- a/src/runtime/pkg/katautils/create.go +++ b/src/runtime/pkg/katautils/create.go @@ -112,7 +112,7 @@ func SetEphemeralStorageType(ociSpec specs.Spec) specs.Spec { func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec specs.Spec, runtimeConfig oci.RuntimeConfig, rootFs vc.RootFs, containerID, bundlePath, console string, disableOutput, systemdCgroup bool) (_ vc.VCSandbox, _ vc.Process, err error) { span, ctx := katatrace.Trace(ctx, nil, "CreateSandbox", createTracingTags) - katatrace.AddTag(span, "container_id", containerID) + katatrace.AddTags(span, "container_id", containerID) defer span.End() sandboxConfig, err := oci.SandboxConfig(ociSpec, runtimeConfig, bundlePath, containerID, console, disableOutput, systemdCgroup) @@ -167,7 +167,7 @@ func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec specs.Spec, runtimeCo sid := sandbox.ID() kataUtilsLogger = kataUtilsLogger.WithField("sandbox", sid) - katatrace.AddTag(span, "sandbox_id", sid) + katatrace.AddTags(span, "sandbox_id", sid) containers := sandbox.GetAllContainers() if len(containers) != 1 { @@ -211,7 +211,7 @@ func CreateContainer(ctx context.Context, sandbox vc.VCSandbox, ociSpec specs.Sp var c vc.VCContainer span, ctx := katatrace.Trace(ctx, nil, "CreateContainer", createTracingTags) - katatrace.AddTag(span, "container_id", containerID) + katatrace.AddTags(span, "container_id", containerID) defer span.End() ociSpec = SetEphemeralStorageType(ociSpec) @@ -237,7 +237,7 @@ func CreateContainer(ctx context.Context, sandbox vc.VCSandbox, ociSpec specs.Sp return vc.Process{}, err } - katatrace.AddTag(span, "sandbox_id", sandboxID) + katatrace.AddTags(span, "sandbox_id", sandboxID) c, err = sandbox.CreateContainer(ctx, contConfig) if err != nil { diff --git a/src/runtime/pkg/katautils/hook.go b/src/runtime/pkg/katautils/hook.go index 7933a182e1..62eb81169c 100644 --- a/src/runtime/pkg/katautils/hook.go +++ b/src/runtime/pkg/katautils/hook.go @@ -35,8 +35,7 @@ func hookLogger() *logrus.Entry { func runHook(ctx context.Context, hook specs.Hook, cid, bundlePath string) error { span, _ := katatrace.Trace(ctx, hookLogger(), "runHook", hookTracingTags) defer span.End() - katatrace.AddTag(span, "path", hook.Path) - katatrace.AddTag(span, "args", hook.Args) + katatrace.AddTags(span, "path", hook.Path, "args", hook.Args) state := specs.State{ Pid: syscall.Gettid(), @@ -93,7 +92,7 @@ func runHook(ctx context.Context, hook specs.Hook, cid, bundlePath string) error func runHooks(ctx context.Context, hooks []specs.Hook, cid, bundlePath, hookType string) error { span, ctx := katatrace.Trace(ctx, hookLogger(), "runHooks", hookTracingTags) - katatrace.AddTag(span, "type", hookType) + katatrace.AddTags(span, "type", hookType) defer span.End() for _, hook := range hooks { diff --git a/src/runtime/pkg/katautils/katatrace/tracing.go b/src/runtime/pkg/katautils/katatrace/tracing.go index f7f5f40c30..2c8b3945c2 100644 --- a/src/runtime/pkg/katautils/katatrace/tracing.go +++ b/src/runtime/pkg/katautils/katatrace/tracing.go @@ -7,6 +7,7 @@ package katatrace import ( "context" + "encoding/json" "github.com/sirupsen/logrus" "go.opentelemetry.io/otel" @@ -163,8 +164,77 @@ func Trace(parent context.Context, logger *logrus.Entry, name string, tags ...ma return span, ctx } -// AddTag adds an additional key-value pair to a tracing span. This can be used to -// provide dynamic tags that are determined at runtime. -func AddTag(span otelTrace.Span, key string, value interface{}) { - span.SetAttributes(label.Any(key, value)) +func addTag(span otelTrace.Span, key string, value interface{}) { + // do not append tags if tracing is disabled + if !tracing { + return + } + if value == nil { + span.SetAttributes(label.String(key, "nil")) + return + } + + switch value := value.(type) { + case string: + span.SetAttributes(label.String(key, value)) + case bool: + span.SetAttributes(label.Bool(key, value)) + case int: + span.SetAttributes(label.Int(key, value)) + case int8: + span.SetAttributes(label.Int(key, int(value))) + case int16: + span.SetAttributes(label.Int(key, int(value))) + case int32: + span.SetAttributes(label.Int32(key, value)) + case int64: + span.SetAttributes(label.Int64(key, value)) + case uint: + span.SetAttributes(label.Uint(key, value)) + case uint8: + span.SetAttributes(label.Uint(key, uint(value))) + case uint16: + span.SetAttributes(label.Uint(key, uint(value))) + case uint32: + span.SetAttributes(label.Uint32(key, value)) + case uint64: + span.SetAttributes(label.Uint64(key, value)) + case float32: + span.SetAttributes(label.Float32(key, value)) + case float64: + span.SetAttributes(label.Float64(key, value)) + default: + content, err := json.Marshal(value) + if content == nil && err == nil { + span.SetAttributes(label.String(key, "nil")) + } else if content != nil && err == nil { + span.SetAttributes(label.String(key, string(content))) + } else { + kataTraceLogger.WithField("type", "bug").Error("span attribute value error") + } + } +} + +// AddTag adds additional key-value pairs to a tracing span. This can be used to provide +// dynamic tags that are determined at runtime and tags with a non-string value. +// Must have an even number of keyValues with keys being strings. +func AddTags(span otelTrace.Span, keyValues ...interface{}) { + if !tracing { + return + } + if len(keyValues) < 2 { + kataTraceLogger.WithField("type", "bug").Error("not enough inputs for attributes") + return + } else if len(keyValues)%2 != 0 { + kataTraceLogger.WithField("type", "bug").Error("number of attribute keyValues is not even") + return + } + for i := 0; i < len(keyValues); i++ { + if key, ok := keyValues[i].(string); ok { + addTag(span, key, keyValues[i+1]) + } else { + kataTraceLogger.WithField("type", "bug").Error("key in attributes is not a string") + } + i++ + } } diff --git a/src/runtime/virtcontainers/kata_agent.go b/src/runtime/virtcontainers/kata_agent.go index b553159fba..cd0336ee8d 100644 --- a/src/runtime/virtcontainers/kata_agent.go +++ b/src/runtime/virtcontainers/kata_agent.go @@ -344,7 +344,7 @@ func (k *kataAgent) internalConfigure(ctx context.Context, h Hypervisor, id stri } k.keepConn = config.LongLiveConn - katatrace.AddTag(span, "socket", k.vmSocket) + katatrace.AddTags(span, "socket", k.vmSocket) return nil } diff --git a/src/runtime/virtcontainers/network.go b/src/runtime/virtcontainers/network.go index c682418f3b..bf2b09a3ae 100644 --- a/src/runtime/virtcontainers/network.go +++ b/src/runtime/virtcontainers/network.go @@ -1304,10 +1304,10 @@ func getNetworkTrace(networkType EndpointType) func(ctx context.Context, name st return func(ctx context.Context, name string, endpoint interface{}) (otelTrace.Span, context.Context) { span, ctx := katatrace.Trace(ctx, networkLogger(), name, networkTracingTags) if networkType != "" { - katatrace.AddTag(span, "type", string(networkType)) + katatrace.AddTags(span, "type", string(networkType)) } if endpoint != nil { - katatrace.AddTag(span, "endpoint", endpoint) + katatrace.AddTags(span, "endpoint", endpoint) } return span, ctx } @@ -1315,7 +1315,7 @@ func getNetworkTrace(networkType EndpointType) func(ctx context.Context, name st func closeSpan(span otelTrace.Span, err error) { if err != nil { - katatrace.AddTag(span, "error", err) + katatrace.AddTags(span, "error", err.Error()) } span.End() } @@ -1333,15 +1333,14 @@ func (n *Network) Run(ctx context.Context, networkNSPath string, cb func() error // Add adds all needed interfaces inside the network namespace. func (n *Network) Add(ctx context.Context, config *NetworkConfig, s *Sandbox, hotplug bool) ([]Endpoint, error) { span, ctx := n.trace(ctx, "Add") - katatrace.AddTag(span, "type", config.InterworkingModel.GetModel()) + katatrace.AddTags(span, "type", config.InterworkingModel.GetModel()) defer span.End() endpoints, err := createEndpointsFromScan(config.NetNSPath, config) if err != nil { return endpoints, err } - katatrace.AddTag(span, "endpoints", endpoints) - katatrace.AddTag(span, "hotplug", hotplug) + katatrace.AddTags(span, "endpoints", endpoints, "hotplug", hotplug) err = doNetNS(config.NetNSPath, func(_ ns.NetNS) error { for _, endpoint := range endpoints { diff --git a/src/runtime/virtcontainers/qemu.go b/src/runtime/virtcontainers/qemu.go index 25c9b093f2..e3e6ade866 100644 --- a/src/runtime/virtcontainers/qemu.go +++ b/src/runtime/virtcontainers/qemu.go @@ -1726,8 +1726,8 @@ func (q *qemu) hotplugDevice(ctx context.Context, devInfo interface{}, devType D } func (q *qemu) HotplugAddDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error) { - span, ctx := katatrace.Trace(ctx, q.Logger(), "HotplugAddDevice", qemuTracingTags, map[string]string{"sandbox_id": q.id}) - katatrace.AddTag(span, "device", devInfo) + span, ctx := katatrace.Trace(ctx, q.Logger(), "HotplugAddDevice", qemuTracingTags) + katatrace.AddTags(span, "sandbox_id", q.id, "device", devInfo) defer span.End() data, err := q.hotplugDevice(ctx, devInfo, devType, AddDevice) @@ -1739,8 +1739,8 @@ func (q *qemu) HotplugAddDevice(ctx context.Context, devInfo interface{}, devTyp } func (q *qemu) HotplugRemoveDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error) { - span, ctx := katatrace.Trace(ctx, q.Logger(), "HotplugRemoveDevice", qemuTracingTags, map[string]string{"sandbox_id": q.id}) - katatrace.AddTag(span, "device", devInfo) + span, ctx := katatrace.Trace(ctx, q.Logger(), "HotplugRemoveDevice", qemuTracingTags) + katatrace.AddTags(span, "sandbox_id", q.id, "device", devInfo) defer span.End() data, err := q.hotplugDevice(ctx, devInfo, devType, RemoveDevice) @@ -1968,8 +1968,8 @@ func (q *qemu) ResumeVM(ctx context.Context) error { // addDevice will add extra devices to Qemu command line. func (q *qemu) AddDevice(ctx context.Context, devInfo interface{}, devType DeviceType) error { var err error - span, _ := katatrace.Trace(ctx, q.Logger(), "AddDevice", qemuTracingTags, map[string]string{"sandbox_id": q.id}) - katatrace.AddTag(span, "device", devInfo) + span, _ := katatrace.Trace(ctx, q.Logger(), "AddDevice", qemuTracingTags) + katatrace.AddTags(span, "sandbox_id", q.id, "device", devInfo) defer span.End() switch v := devInfo.(type) { diff --git a/src/runtime/virtcontainers/sandbox.go b/src/runtime/virtcontainers/sandbox.go index 66f1a367ba..6b34d597c6 100644 --- a/src/runtime/virtcontainers/sandbox.go +++ b/src/runtime/virtcontainers/sandbox.go @@ -822,8 +822,7 @@ func (s *Sandbox) createNetwork(ctx context.Context) error { NetNsCreated: s.config.NetworkConfig.NetNsCreated, } - katatrace.AddTag(span, "networkNS", s.networkNS) - katatrace.AddTag(span, "NetworkConfig", s.config.NetworkConfig) + katatrace.AddTags(span, "networkNS", s.networkNS, "NetworkConfig", s.config.NetworkConfig) // In case there is a factory, network interfaces are hotplugged // after vm is started.