Skip to content

Commit

Permalink
Followups from lint/comment changes
Browse files Browse the repository at this point in the history
This is a followup branch from #2023:
- delete `proxy/client.go`, move code to `destination-client`
- move `RenderTapEvent` and `GetPercentTLS` from `util` to `cmd`

Signed-off-by: Andrew Seigner <siggy@buoyant.io>
  • Loading branch information
siggy committed Jan 2, 2019
1 parent 1c30218 commit e3aaa1f
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 217 deletions.
12 changes: 11 additions & 1 deletion cli/cmd/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
statTables[resourceKey][key].rowStats = &rowStats{
requestRate: util.GetRequestRate(r.Stats, r.TimeWindow),
successRate: util.GetSuccessRate(r.Stats),
tlsPercent: util.GetPercentTLS(r.Stats),
tlsPercent: getPercentTLS(r.Stats),
latencyP50: r.Stats.LatencyMsP50,
latencyP95: r.Stats.LatencyMsP95,
latencyP99: r.Stats.LatencyMsP99,
Expand All @@ -287,6 +287,16 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
}
}

// getPercentTLS calculates the percent of traffic that is TLS, from Public API
// BasicStats.
func getPercentTLS(stats *pb.BasicStats) float64 {
reqTotal := stats.SuccessCount + stats.FailureCount
if reqTotal == 0 {
return 0.0
}
return float64(stats.TlsRequestCount) / float64(reqTotal)
}

func printStatTables(statTables map[string]map[string]*row, w *tabwriter.Writer, maxNameLength int, maxNamespaceLength int, options *statOptions) {
usePrefix := false
if len(statTables) > 1 {
Expand Down
181 changes: 180 additions & 1 deletion cli/cmd/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import (

"github.com/linkerd/linkerd2/controller/api/util"
pb "github.com/linkerd/linkerd2/controller/gen/public"
"github.com/linkerd/linkerd2/pkg/addr"
"github.com/linkerd/linkerd2/pkg/k8s"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
)

type tapOptions struct {
Expand Down Expand Up @@ -165,11 +168,187 @@ func writeTapEventsToBuffer(tapClient pb.Api_TapByResourceClient, w *tabwriter.W
fmt.Fprintln(os.Stderr, err)
break
}
_, err = fmt.Fprintln(w, util.RenderTapEvent(event, resource))
_, err = fmt.Fprintln(w, renderTapEvent(event, resource))
if err != nil {
return err
}
}

return nil
}

// renderTapEvent renders a Public API TapEvent to a string.
func renderTapEvent(event *pb.TapEvent, resource string) string {
dst := dst(event)
src := src(event)

proxy := "???"
tls := ""
switch event.GetProxyDirection() {
case pb.TapEvent_INBOUND:
proxy = "in " // A space is added so it aligns with `out`.
tls = src.tlsStatus()
case pb.TapEvent_OUTBOUND:
proxy = "out"
tls = dst.tlsStatus()
default:
// Too old for TLS.
}

flow := fmt.Sprintf("proxy=%s %s %s tls=%s",
proxy,
src.formatAddr(),
dst.formatAddr(),
tls,
)

// If `resource` is non-empty, then
resources := ""
if resource != "" {
resources = fmt.Sprintf(
"%s%s%s",
src.formatResource(resource),
dst.formatResource(resource),
routeLabels(event),
)
}

switch ev := event.GetHttp().GetEvent().(type) {
case *pb.TapEvent_Http_RequestInit_:
return fmt.Sprintf("req id=%d:%d %s :method=%s :authority=%s :path=%s%s",
ev.RequestInit.GetId().GetBase(),
ev.RequestInit.GetId().GetStream(),
flow,
ev.RequestInit.GetMethod().GetRegistered().String(),
ev.RequestInit.GetAuthority(),
ev.RequestInit.GetPath(),
resources,
)

case *pb.TapEvent_Http_ResponseInit_:
return fmt.Sprintf("rsp id=%d:%d %s :status=%d latency=%dµs%s",
ev.ResponseInit.GetId().GetBase(),
ev.ResponseInit.GetId().GetStream(),
flow,
ev.ResponseInit.GetHttpStatus(),
ev.ResponseInit.GetSinceRequestInit().GetNanos()/1000,
resources,
)

case *pb.TapEvent_Http_ResponseEnd_:
switch eos := ev.ResponseEnd.GetEos().GetEnd().(type) {
case *pb.Eos_GrpcStatusCode:
return fmt.Sprintf(
"end id=%d:%d %s grpc-status=%s duration=%dµs response-length=%dB%s",
ev.ResponseEnd.GetId().GetBase(),
ev.ResponseEnd.GetId().GetStream(),
flow,
codes.Code(eos.GrpcStatusCode),
ev.ResponseEnd.GetSinceResponseInit().GetNanos()/1000,
ev.ResponseEnd.GetResponseBytes(),
resources,
)

case *pb.Eos_ResetErrorCode:
return fmt.Sprintf(
"end id=%d:%d %s reset-error=%+v duration=%dµs response-length=%dB%s",
ev.ResponseEnd.GetId().GetBase(),
ev.ResponseEnd.GetId().GetStream(),
flow,
eos.ResetErrorCode,
ev.ResponseEnd.GetSinceResponseInit().GetNanos()/1000,
ev.ResponseEnd.GetResponseBytes(),
resources,
)

default:
return fmt.Sprintf("end id=%d:%d %s duration=%dµs response-length=%dB%s",
ev.ResponseEnd.GetId().GetBase(),
ev.ResponseEnd.GetId().GetStream(),
flow,
ev.ResponseEnd.GetSinceResponseInit().GetNanos()/1000,
ev.ResponseEnd.GetResponseBytes(),
resources,
)
}

default:
return fmt.Sprintf("unknown %s", flow)
}
}

// src returns the source peer of a `TapEvent`.
func src(event *pb.TapEvent) peer {
return peer{
address: event.GetSource(),
labels: event.GetSourceMeta().GetLabels(),
direction: "src",
}
}

// dst returns the destination peer of a `TapEvent`.
func dst(event *pb.TapEvent) peer {
return peer{
address: event.GetDestination(),
labels: event.GetDestinationMeta().GetLabels(),
direction: "dst",
}
}

type peer struct {
address *pb.TcpAddress
labels map[string]string
direction string
}

// formatAddr formats the peer's TCP address for the `src` or `dst` element in
// the tap output corresponding to this peer.
func (p *peer) formatAddr() string {
return fmt.Sprintf(
"%s=%s",
p.direction,
addr.PublicAddressToString(p.address),
)
}

// formatResource returns a label describing what Kubernetes resources the peer
// belongs to. If the peer belongs to a resource of kind `resourceKind`, it will
// return a label for that resource; otherwise, it will fall back to the peer's
// pod name. Additionally, if the resource is not of type `namespace`, it will
// also add a label describing the peer's resource.
func (p *peer) formatResource(resourceKind string) string {
var s string
if resourceName, exists := p.labels[resourceKind]; exists {
kind := resourceKind
if short := k8s.ShortNameFromCanonicalResourceName(resourceKind); short != "" {
kind = short
}
s = fmt.Sprintf(
" %s_res=%s/%s",
p.direction,
kind,
resourceName,
)
} else if pod, hasPod := p.labels[k8s.Pod]; hasPod {
s = fmt.Sprintf(" %s_pod=%s", p.direction, pod)
}
if resourceKind != k8s.Namespace {
if ns, hasNs := p.labels[k8s.Namespace]; hasNs {
s += fmt.Sprintf(" %s_ns=%s", p.direction, ns)
}
}
return s
}

func (p *peer) tlsStatus() string {
return p.labels["tls"]
}

func routeLabels(event *pb.TapEvent) string {
out := ""
for key, val := range event.GetRouteMeta().GetLabels() {
out = fmt.Sprintf("%s rt_%s=%s", out, key, val)
}

return out
}
14 changes: 7 additions & 7 deletions cli/cmd/tap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "req id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= :method=POST :authority=hello.default:7777 :path=/hello.v1.HelloService/Hello"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -245,7 +245,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "rsp id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= :status=200 latency=999µs"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -266,7 +266,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "end id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= grpc-status=OK duration=888µs response-length=111B"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -287,7 +287,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "end id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= reset-error=123 duration=888µs response-length=111B"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -306,7 +306,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "end id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= duration=888µs response-length=111B"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -324,7 +324,7 @@ func TestEventToString(t *testing.T) {
})

expectedOutput := "end id=7:8 proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls= duration=888µs response-length=111B"
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand All @@ -334,7 +334,7 @@ func TestEventToString(t *testing.T) {
event := toTapEvent(&pb.TapEvent_Http{})

expectedOutput := "unknown proxy=out src=1.2.3.4:5555 dst=2.3.4.5:6666 tls="
output := util.RenderTapEvent(event, "")
output := renderTapEvent(event, "")
if output != expectedOutput {
t.Fatalf("Expecting command output to be [%s], got [%s]", expectedOutput, output)
}
Expand Down
17 changes: 0 additions & 17 deletions controller/api/proxy/client.go

This file was deleted.

Loading

0 comments on commit e3aaa1f

Please sign in to comment.