internal/telemetry: render trace tags using typed keys

Type switch on the key and use it to get the value and decide how
to render it.
Use the same render for all debug tag printing.

Change-Id: Ia305fded7dcf05b57c5805f48bb5c22fa7def71f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/225380
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/lsp/debug/trace.go b/internal/lsp/debug/trace.go
index 52a6986..53b4994 100644
--- a/internal/lsp/debug/trace.go
+++ b/internal/lsp/debug/trace.go
@@ -172,8 +172,7 @@
 func renderTags(tags event.TagIterator) string {
 	buf := &bytes.Buffer{}
 	for ; tags.Valid(); tags.Advance() {
-		tag := tags.Tag()
-		fmt.Fprintf(buf, "%s=%q ", tag.Key.Name(), tag.Value)
+		fmt.Fprintf(buf, "%v ", tags.Tag())
 	}
 	return buf.String()
 }
diff --git a/internal/telemetry/event/event.go b/internal/telemetry/event/event.go
index 0303229..3f222c4 100644
--- a/internal/telemetry/event/event.go
+++ b/internal/telemetry/event/event.go
@@ -51,7 +51,7 @@
 	}
 	for it := ev.Tags(); it.Valid(); it.Advance() {
 		tag := it.Tag()
-		fmt.Fprintf(f, "\n\t%s = %v", tag.Key.Name(), tag.Value)
+		fmt.Fprintf(f, "\n\t%v", tag)
 	}
 }
 
diff --git a/internal/telemetry/event/tag.go b/internal/telemetry/event/tag.go
index 7aa6ebb..5f1e09e 100644
--- a/internal/telemetry/event/tag.go
+++ b/internal/telemetry/event/tag.go
@@ -67,7 +67,7 @@
 	maps []TagMap
 }
 
-// Key returns the key for this Tag.
+// Valid returns true if the Tag is a valid one (it has a key).
 func (t Tag) Valid() bool { return t.Key != nil }
 
 // Format is used for debug printing of tags.
@@ -76,7 +76,42 @@
 		fmt.Fprintf(f, `nil`)
 		return
 	}
-	fmt.Fprintf(f, `%v="%v"`, t.Key.Name(), t.Value)
+	switch key := t.Key.(type) {
+	case *IntKey:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *Int8Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *Int16Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *Int32Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *Int64Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *UIntKey:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *UInt8Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *UInt16Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *UInt32Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *UInt64Key:
+		fmt.Fprintf(f, "%s=%d", key.Name(), key.From(t))
+	case *Float32Key:
+		fmt.Fprintf(f, "%s=%g", key.Name(), key.From(t))
+	case *Float64Key:
+		fmt.Fprintf(f, "%s=%g", key.Name(), key.From(t))
+	case *BooleanKey:
+		fmt.Fprintf(f, "%s=%t", key.Name(), key.From(t))
+	case *StringKey:
+		fmt.Fprintf(f, "%s=%q", key.Name(), key.From(t))
+	case *ErrorKey:
+		fmt.Fprintf(f, "%s=%q", key.Name(), key.From(t))
+	case *ValueKey:
+		fmt.Fprintf(f, "%s=%q", key.Name(), key.From(t))
+	default:
+		fmt.Fprintf(f, `%s="invalid type %T"`, key.Name(), key)
+	}
 }
 
 func (i *TagIterator) Valid() bool {