func TestReporter(t *testing.T) { walker := &mockWalker{ processes: []process.Process{ {PID: 1, PPID: 0, Name: "init"}, {PID: 2, PPID: 1, Name: "bash"}, {PID: 3, PPID: 1, Name: "apache", Threads: 2}, {PID: 4, PPID: 2, Name: "ping", Cmdline: "ping foo.bar.local"}, {PID: 5, PPID: 1, Cmdline: "tail -f /var/log/syslog"}, }, } getDeltaTotalJiffies := func() (uint64, float64, error) { return 0, 0., nil } now := time.Now() mtime.NowForce(now) defer mtime.NowReset() reporter := process.NewReporter(walker, "", getDeltaTotalJiffies) want := report.MakeReport() want.Process = report.MakeTopology().AddNode( report.MakeProcessNodeID("", "1"), report.MakeNodeWith(map[string]string{ process.PID: "1", process.Name: "init", process.Threads: "0", }).WithMetric(process.MemoryUsage, report.MakeMetric().Add(now, 0.)), ).AddNode( report.MakeProcessNodeID("", "2"), report.MakeNodeWith(map[string]string{ process.PID: "2", process.Name: "bash", process.PPID: "1", process.Threads: "0", }).WithMetric(process.MemoryUsage, report.MakeMetric().Add(now, 0.)), ).AddNode( report.MakeProcessNodeID("", "3"), report.MakeNodeWith(map[string]string{ process.PID: "3", process.Name: "apache", process.PPID: "1", process.Threads: "2", }).WithMetric(process.MemoryUsage, report.MakeMetric().Add(now, 0.)), ).AddNode( report.MakeProcessNodeID("", "4"), report.MakeNodeWith(map[string]string{ process.PID: "4", process.Name: "ping", process.PPID: "2", process.Cmdline: "ping foo.bar.local", process.Threads: "0", }).WithMetric(process.MemoryUsage, report.MakeMetric().Add(now, 0.)), ).AddNode( report.MakeProcessNodeID("", "5"), report.MakeNodeWith(map[string]string{ process.PID: "5", process.PPID: "1", process.Cmdline: "tail -f /var/log/syslog", process.Threads: "0", }).WithMetric(process.MemoryUsage, report.MakeMetric().Add(now, 0.)), ) have, err := reporter.Report() if err != nil || !reflect.DeepEqual(want, have) { t.Errorf("%s (%v)", test.Diff(want, have), err) } }
func TestReporter(t *testing.T) { var ( release = "release" version = "version" network = "192.168.0.0/16" hostID = "hostid" hostname = "hostname" timestamp = time.Now() load = report.Metrics{ host.Load1: report.MakeMetric().Add(timestamp, 1.0), host.Load5: report.MakeMetric().Add(timestamp, 5.0), host.Load15: report.MakeMetric().Add(timestamp, 15.0), host.CPUUsage: report.MakeMetric().Add(timestamp, 30.0).WithMax(100.0), host.MemUsage: report.MakeMetric().Add(timestamp, 60.0).WithMax(100.0), } uptime = "278h55m43s" kernel = "release version" _, ipnet, _ = net.ParseCIDR(network) localNets = report.Networks([]*net.IPNet{ipnet}) ) mtime.NowForce(timestamp) defer mtime.NowReset() var ( oldGetKernelVersion = host.GetKernelVersion oldGetLoad = host.GetLoad oldGetUptime = host.GetUptime oldGetCPUUsagePercent = host.GetCPUUsagePercent oldGetMemoryUsageBytes = host.GetMemoryUsageBytes ) defer func() { host.GetKernelVersion = oldGetKernelVersion host.GetLoad = oldGetLoad host.GetUptime = oldGetUptime host.GetCPUUsagePercent = oldGetCPUUsagePercent host.GetMemoryUsageBytes = oldGetMemoryUsageBytes }() host.GetKernelVersion = func() (string, error) { return release + " " + version, nil } host.GetLoad = func(time.Time) report.Metrics { return load } host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) } host.GetCPUUsagePercent = func() (float64, float64) { return 30.0, 100.0 } host.GetMemoryUsageBytes = func() (float64, float64) { return 60.0, 100.0 } want := report.MakeReport() want.Host.AddNode(report.MakeHostNodeID(hostID), report.MakeNodeWith(map[string]string{ host.Timestamp: timestamp.UTC().Format(time.RFC3339Nano), host.HostName: hostname, host.OS: runtime.GOOS, host.Uptime: uptime, host.KernelVersion: kernel, }).WithSets(report.Sets{ host.LocalNetworks: report.MakeStringSet(network), }).WithMetrics(load)) have, _ := host.NewReporter(hostID, hostname, localNets).Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestReporter(t *testing.T) { var ( release = "release" version = "version" network = "192.168.0.0/16" hostID = "hostid" now = "now" hostname = "hostname" timestamp = time.Now() load = report.Metrics{ host.Load1: report.MakeMetric().Add(timestamp, 1.0), host.Load5: report.MakeMetric().Add(timestamp, 5.0), host.Load15: report.MakeMetric().Add(timestamp, 15.0), } uptime = "278h55m43s" kernel = "release version" _, ipnet, _ = net.ParseCIDR(network) localNets = report.Networks([]*net.IPNet{ipnet}) ) var ( oldGetKernelVersion = host.GetKernelVersion oldGetLoad = host.GetLoad oldGetUptime = host.GetUptime oldNow = host.Now ) defer func() { host.GetKernelVersion = oldGetKernelVersion host.GetLoad = oldGetLoad host.GetUptime = oldGetUptime host.Now = oldNow }() host.GetKernelVersion = func() (string, error) { return release + " " + version, nil } host.GetLoad = func() report.Metrics { return load } host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) } host.Now = func() string { return now } want := report.MakeReport() want.Host.AddNode(report.MakeHostNodeID(hostID), report.MakeNodeWith(map[string]string{ host.Timestamp: now, host.HostName: hostname, host.OS: runtime.GOOS, host.Uptime: uptime, host.KernelVersion: kernel, }).WithSets(report.Sets{ host.LocalNetworks: report.MakeStringSet(network), }).WithMetrics(load)) have, _ := host.NewReporter(hostID, hostname, localNets).Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestMetricCopy(t *testing.T) { want := report.MakeMetric() have := want.Copy() if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } want = report.MakeMetric().Add(time.Now(), 1) have = want.Copy() if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
func (c *container) memoryUsageMetric(stats []docker.Stats) report.Metric { result := report.MakeMetric() for _, s := range stats { result = result.Add(s.Read, float64(s.MemoryStats.Usage)).WithMax(float64(s.MemoryStats.Limit)) } return result }
func (c *container) memoryUsageMetric() report.Metric { result := report.MakeMetric() for _, s := range c.pendingStats { result = result.Add(s.Read, float64(s.MemoryStats.Usage)) } return result }
func TestMetricRowSummary(t *testing.T) { var ( now = time.Now() metric = report.MakeMetric().Add(now, 1.234) row = report.MetricRow{ ID: "id", Format: "format", Group: "group", Value: 1.234, Priority: 1, Metric: &metric, } summary = row.Summary() ) // summary should not have any samples if summary.Metric.Len() != 0 { t.Errorf("Expected summary to have no samples, but had %d", summary.Metric.Len()) } // original metric should still have its samples if metric.Len() != 1 { t.Errorf("Expected original metric to still have it's samples, but had %d", metric.Len()) } // summary should have all the same fields (minus the metric) summary.Metric = nil row.Metric = nil if !reflect.DeepEqual(summary, row) { t.Errorf("Expected summary to have same fields as original: %s", test.Diff(summary, row)) } }
func TestMetricDiv(t *testing.T) { t1 := time.Now() t2 := time.Now().Add(1 * time.Minute) want := report.MakeMetric(). Add(t1, -2). Add(t2, 2) beforeDiv := report.MakeMetric(). Add(t1, -2048). Add(t2, 2048) have := beforeDiv.Div(1024) if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } // Check the original was unmodified checkMetric(t, beforeDiv, t1, t2, -2048, 2048) }
func TestMetricMerge(t *testing.T) { t1 := time.Now() t2 := time.Now().Add(1 * time.Minute) t3 := time.Now().Add(2 * time.Minute) t4 := time.Now().Add(3 * time.Minute) metric1 := report.MakeMetric(). Add(t2, 0.2). Add(t3, 0.31) metric2 := report.MakeMetric(). Add(t1, -0.1). Add(t3, 0.3). Add(t4, 0.4) want := report.MakeMetric(). Add(t1, -0.1). Add(t2, 0.2). Add(t3, 0.31). Add(t4, 0.4) have := metric1.Merge(metric2) if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } // Check it didn't modify metric1 if !metric1.First.Equal(t2) { t.Errorf("Expected metric1.First == %q, but was: %q", t2, metric1.First) } if !metric1.Last.Equal(t3) { t.Errorf("Expected metric1.Last == %q, but was: %q", t3, metric1.Last) } if metric1.Min != 0.0 { t.Errorf("Expected metric1.Min == %f, but was: %f", 0.0, metric1.Min) } if metric1.Max != 0.31 { t.Errorf("Expected metric1.Max == %f, but was: %f", 0.31, metric1.Max) } // Check the result is not the same instance as metric1 if &metric1 == &have { t.Errorf("Expected different pointers for metric1 and have, but both were: %p", &have) } }
// Report implements Reporter. func (r *Reporter) Report() (report.Report, error) { var ( rep = report.MakeReport() localCIDRs []string ) localNets, err := GetLocalNetworks() if err != nil { return rep, nil } for _, localNet := range localNets { localCIDRs = append(localCIDRs, localNet.String()) } uptime, err := GetUptime() if err != nil { return rep, err } kernel, err := GetKernelVersion() if err != nil { return rep, err } now := mtime.Now() metrics := GetLoad(now) cpuUsage, max := GetCPUUsagePercent() metrics[CPUUsage] = report.MakeMetric().Add(now, cpuUsage).WithMax(max) memoryUsage, max := GetMemoryUsageBytes() metrics[MemoryUsage] = report.MakeMetric().Add(now, memoryUsage).WithMax(max) rep.Host.AddNode(report.MakeHostNodeID(r.hostID), report.MakeNodeWith(map[string]string{ Timestamp: mtime.Now().UTC().Format(time.RFC3339Nano), HostName: r.hostName, OS: runtime.GOOS, KernelVersion: kernel, Uptime: uptime.String(), }).WithSets(report.EmptySets. Add(LocalNetworks, report.MakeStringSet(localCIDRs...)), ).WithMetrics(metrics)) return rep, nil }
func (r *Reporter) processTopology() (report.Topology, error) { t := report.MakeTopology(). WithMetadataTemplates(MetadataTemplates). WithMetricTemplates(MetricTemplates) now := mtime.Now() deltaTotal, maxCPU, err := r.jiffies() if err != nil { return t, err } err = r.walker.Walk(func(p, prev Process) { pidstr := strconv.Itoa(p.PID) nodeID := report.MakeProcessNodeID(r.scope, pidstr) node := report.MakeNode(nodeID) for _, tuple := range []struct{ key, value string }{ {PID, pidstr}, {Name, p.Name}, {Cmdline, p.Cmdline}, {Threads, strconv.Itoa(p.Threads)}, } { if tuple.value != "" { node = node.WithLatests(map[string]string{tuple.key: tuple.value}) } } if p.PPID > 0 { node = node.WithLatests(map[string]string{PPID: strconv.Itoa(p.PPID)}) } if deltaTotal > 0 { cpuUsage := float64(p.Jiffies-prev.Jiffies) / float64(deltaTotal) * 100. node = node.WithMetric(CPUUsage, report.MakeMetric().Add(now, cpuUsage).WithMax(maxCPU)) } node = node.WithMetric(MemoryUsage, report.MakeMetric().Add(now, float64(p.RSSBytes)).WithMax(float64(p.RSSBytesLimit))) node = node.WithMetric(OpenFilesCount, report.MakeMetric().Add(now, float64(p.OpenFilesCount)).WithMax(float64(p.OpenFilesLimit))) t.AddNode(node) }) return t, err }
func TestMetricsCopy(t *testing.T) { t1 := time.Now() want := report.Metrics{ "metric1": report.MakeMetric().Add(t1, 0.1), } delete(want.Copy(), "metric1") // Modify a copy have := want.Copy() // Check the original wasn't affected if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
func TestMetricFirstLastMinMax(t *testing.T) { metric := report.MakeMetric() var zero time.Time t1 := time.Now() t2 := time.Now().Add(1 * time.Minute) t3 := time.Now().Add(2 * time.Minute) t4 := time.Now().Add(3 * time.Minute) other := report.MakeMetric() other.Max = 5 other.Min = -5 other.First = t1.Add(-1 * time.Minute) other.Last = t4.Add(1 * time.Minute) tests := []struct { f func(report.Metric) report.Metric first, last time.Time min, max float64 }{ {nil, zero, zero, 0, 0}, {func(m report.Metric) report.Metric { return m.Add(t2, 2) }, t2, t2, 0, 2}, {func(m report.Metric) report.Metric { return m.Add(t1, 1) }, t1, t2, 0, 2}, {func(m report.Metric) report.Metric { return m.Add(t3, -1) }, t1, t3, -1, 2}, {func(m report.Metric) report.Metric { return m.Add(t4, 3) }, t1, t4, -1, 3}, {func(m report.Metric) report.Metric { return m.Merge(other) }, t1.Add(-1 * time.Minute), t4.Add(1 * time.Minute), -5, 5}, } for _, test := range tests { oldFirst, oldLast, oldMin, oldMax := metric.First, metric.Last, metric.Min, metric.Max oldMetric := metric if test.f != nil { metric = test.f(metric) } // Check it didn't modify the old one checkMetric(t, oldMetric, oldFirst, oldLast, oldMin, oldMax) // Check the new one is as expected checkMetric(t, metric, test.first, test.last, test.min, test.max) } }
func TestMetricAdd(t *testing.T) { s := []report.Sample{ {time.Now(), 0.1}, {time.Now().Add(1 * time.Minute), 0.2}, {time.Now().Add(2 * time.Minute), 0.3}, } have := report.MakeMetric(). Add(s[0].Timestamp, s[0].Value). Add(s[2].Timestamp, s[2].Value). // Keeps sorted Add(s[1].Timestamp, s[1].Value). Add(s[2].Timestamp, 0.5) // Overwrites duplicate timestamps want := report.MakeMetric(). Add(s[0].Timestamp, s[0].Value). Add(s[1].Timestamp, s[1].Value). Add(s[2].Timestamp, 0.5) if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
func (c *container) cpuPercentMetric(stats []docker.Stats) report.Metric { result := report.MakeMetric() if len(stats) < 2 { return result } previous := stats[0] for _, s := range stats[1:] { // Copies from docker/api/client/stats.go#L205 cpuDelta := float64(s.CPUStats.CPUUsage.TotalUsage - previous.CPUStats.CPUUsage.TotalUsage) systemDelta := float64(s.CPUStats.SystemCPUUsage - previous.CPUStats.SystemCPUUsage) cpuPercent := 0.0 if systemDelta > 0.0 && cpuDelta > 0.0 { cpuPercent = (cpuDelta / systemDelta) * float64(len(s.CPUStats.CPUUsage.PercpuUsage)) * 100.0 } result = result.Add(s.Read, cpuPercent) available := float64(len(s.CPUStats.CPUUsage.PercpuUsage)) * 100.0 if available >= result.Max { result.Max = available } previous = s } return result }
func TestMetricsMerge(t *testing.T) { t1 := time.Now() t2 := time.Now().Add(1 * time.Minute) t3 := time.Now().Add(2 * time.Minute) t4 := time.Now().Add(3 * time.Minute) metrics1 := report.Metrics{ "metric1": report.MakeMetric().Add(t1, 0.1).Add(t2, 0.2), "metric2": report.MakeMetric().Add(t3, 0.3), } metrics2 := report.Metrics{ "metric2": report.MakeMetric().Add(t4, 0.4), "metric3": report.MakeMetric().Add(t1, 0.1).Add(t2, 0.2), } want := report.Metrics{ "metric1": report.MakeMetric().Add(t1, 0.1).Add(t2, 0.2), "metric2": report.MakeMetric().Add(t3, 0.3).Add(t4, 0.4), "metric3": report.MakeMetric().Add(t1, 0.1).Add(t2, 0.2), } have := metrics1.Merge(metrics2) if !reflect.DeepEqual(want, have) { t.Errorf("diff: %s", test.Diff(want, have)) } }
ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, ClientIP) ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, ServerIP) UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient1IP) UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient2IP) UnknownAddress3NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient3IP) RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, RandomClientIP) // this should become an internet node KubernetesNamespace = "ping" ClientPodID = "ping/pong-a" ServerPodID = "ping/pong-b" ClientPodNodeID = report.MakePodNodeID(KubernetesNamespace, "pong-a") ServerPodNodeID = report.MakePodNodeID(KubernetesNamespace, "pong-b") ServiceID = "ping/pongservice" ServiceNodeID = report.MakeServiceNodeID(KubernetesNamespace, "pongservice") LoadMetric = report.MakeMetric().Add(Now, 0.01).WithFirst(Now.Add(-15 * time.Second)) LoadMetrics = report.Metrics{ host.Load1: LoadMetric, host.Load5: LoadMetric, host.Load15: LoadMetric, } CPUMetric = report.MakeMetric().Add(Now, 0.01).WithFirst(Now.Add(-15 * time.Second)) MemoryMetric = report.MakeMetric().Add(Now, 0.01).WithFirst(Now.Add(-15 * time.Second)) Report = report.Report{ Endpoint: report.Topology{ Nodes: report.Nodes{ // Node is arbitrary. We're free to put only precisely what we // care to test into the fixture. Just be sure to include the bits
return nil } one, err := strconv.ParseFloat(toks[0], 64) if err != nil { return nil } five, err := strconv.ParseFloat(toks[1], 64) if err != nil { return nil } fifteen, err := strconv.ParseFloat(toks[2], 64) if err != nil { return nil } return report.Metrics{ Load1: report.MakeMetric().Add(now, one), Load5: report.MakeMetric().Add(now, five), Load15: report.MakeMetric().Add(now, fifteen), } } // GetUptime returns the uptime of the host. var GetUptime = func() (time.Duration, error) { buf, err := ioutil.ReadFile("/proc/uptime") if err != nil { return 0, err } fields := strings.Fields(string(buf)) if len(fields) != 2 { return 0, fmt.Errorf("invalid format: %s", string(buf))
func TestReporter(t *testing.T) { var ( release = "release" version = "version" network = "192.168.0.0/16" hostID = "hostid" hostname = "hostname" timestamp = time.Now() metrics = report.Metrics{ host.Load1: report.MakeMetric().Add(timestamp, 1.0), host.Load5: report.MakeMetric().Add(timestamp, 5.0), host.Load15: report.MakeMetric().Add(timestamp, 15.0), host.CPUUsage: report.MakeMetric().Add(timestamp, 30.0).WithMax(100.0), host.MemoryUsage: report.MakeMetric().Add(timestamp, 60.0).WithMax(100.0), } uptime = "278h55m43s" kernel = "release version" _, ipnet, _ = net.ParseCIDR(network) ) mtime.NowForce(timestamp) defer mtime.NowReset() var ( oldGetKernelVersion = host.GetKernelVersion oldGetLoad = host.GetLoad oldGetUptime = host.GetUptime oldGetCPUUsagePercent = host.GetCPUUsagePercent oldGetMemoryUsageBytes = host.GetMemoryUsageBytes oldGetLocalNetworks = host.GetLocalNetworks ) defer func() { host.GetKernelVersion = oldGetKernelVersion host.GetLoad = oldGetLoad host.GetUptime = oldGetUptime host.GetCPUUsagePercent = oldGetCPUUsagePercent host.GetMemoryUsageBytes = oldGetMemoryUsageBytes host.GetLocalNetworks = oldGetLocalNetworks }() host.GetKernelVersion = func() (string, error) { return release + " " + version, nil } host.GetLoad = func(time.Time) report.Metrics { return metrics } host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) } host.GetCPUUsagePercent = func() (float64, float64) { return 30.0, 100.0 } host.GetMemoryUsageBytes = func() (float64, float64) { return 60.0, 100.0 } host.GetLocalNetworks = func() ([]*net.IPNet, error) { return []*net.IPNet{ipnet}, nil } rpt, err := host.NewReporter(hostID, hostname).Report() if err != nil { t.Fatal(err) } nodeID := report.MakeHostNodeID(hostID) node, ok := rpt.Host.Nodes[nodeID] if !ok { t.Errorf("Expected host node %q, but not found", nodeID) } // Should have a bunch of expected latest keys for _, tuple := range []struct { key, want string }{ {host.Timestamp, timestamp.UTC().Format(time.RFC3339Nano)}, {host.HostName, hostname}, {host.OS, runtime.GOOS}, {host.Uptime, uptime}, {host.KernelVersion, kernel}, } { if have, ok := node.Latest.Lookup(tuple.key); !ok || have != tuple.want { t.Errorf("Expected %s %q, got %q", tuple.key, tuple.want, have) } } // Should have the local network if have, ok := node.Sets.Lookup(host.LocalNetworks); !ok || !have.Contains(network) { t.Errorf("Expected host.LocalNetworks to include %q, got %q", network, have) } // Should have metrics for key, want := range metrics { wantSample := want.LastSample() if metric, ok := node.Metrics[key]; !ok { t.Errorf("Expected %s metric, but not found", key) } else if sample := metric.LastSample(); sample == nil { t.Errorf("Expected %s metric to have a sample, but there were none", key) } else if sample.Value != wantSample.Value { t.Errorf("Expected %s metric sample %f, got %f", key, wantSample, sample.Value) } } }
func TestContainer(t *testing.T) { log.SetOutput(ioutil.Discard) oldDialStub, oldNewClientConnStub := docker.DialStub, docker.NewClientConnStub defer func() { docker.DialStub, docker.NewClientConnStub = oldDialStub, oldNewClientConnStub }() docker.DialStub = func(network, address string) (net.Conn, error) { return nil, nil } reader, writer := io.Pipe() connection := &mockConnection{reader} docker.NewClientConnStub = func(c net.Conn, r *bufio.Reader) docker.ClientConn { return connection } c := docker.NewContainer(container1) err := c.StartGatheringStats() if err != nil { t.Errorf("%v", err) } defer c.StopGatheringStats() now := time.Unix(12345, 67890).UTC() mtime.NowForce(now) defer mtime.NowReset() // Send some stats to the docker container stats := &client.Stats{} stats.Read = now stats.MemoryStats.Usage = 12345 if err = json.NewEncoder(writer).Encode(&stats); err != nil { t.Error(err) } // Now see if we go them uptime := (now.Sub(startTime) / time.Second) * time.Second want := report.MakeNode().WithLatests(map[string]string{ "docker_container_command": " ", "docker_container_created": "01 Jan 01 00:00 UTC", "docker_container_id": "ping", "docker_container_name": "pong", "docker_image_id": "baz", "docker_label_foo1": "bar1", "docker_label_foo2": "bar2", "docker_container_state": "running", "docker_container_uptime": uptime.String(), }).WithSets(report.EmptySets. Add("docker_container_ports", report.MakeStringSet("1.2.3.4:80->80/tcp", "81/tcp")). Add("docker_container_ips", report.MakeStringSet("1.2.3.4")). Add("docker_container_ips_with_scopes", report.MakeStringSet("scope;1.2.3.4")), ).WithControls( docker.RestartContainer, docker.StopContainer, docker.PauseContainer, docker.AttachContainer, docker.ExecContainer, ).WithMetrics(report.Metrics{ "docker_cpu_total_usage": report.MakeMetric(), "docker_memory_usage": report.MakeMetric().Add(now, 12345), }).WithParents(report.EmptySets. Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID("baz"))), ) test.Poll(t, 100*time.Millisecond, want, func() interface{} { node := c.GetNode("scope", []net.IP{}) node.Latest.ForEach(func(k, v string) { if v == "0" || v == "" { node.Latest = node.Latest.Delete(k) } }) return node }) if c.Image() != "baz" { t.Errorf("%s != baz", c.Image()) } if c.PID() != 2 { t.Errorf("%d != 2", c.PID()) } if have := docker.ExtractContainerIPs(c.GetNode("", []net.IP{})); !reflect.DeepEqual(have, []string{"1.2.3.4"}) { t.Errorf("%v != %v", have, []string{"1.2.3.4"}) } }
func TestMetricMarshalling(t *testing.T) { t1 := time.Now().UTC() t2 := time.Now().UTC().Add(1 * time.Minute) t3 := time.Now().UTC().Add(2 * time.Minute) t4 := time.Now().UTC().Add(3 * time.Minute) wantSamples := []report.Sample{ {Timestamp: t1, Value: 0.1}, {Timestamp: t2, Value: 0.2}, {Timestamp: t3, Value: 0.3}, {Timestamp: t4, Value: 0.4}, } want := report.MakeMetric() for _, sample := range wantSamples { want = want.Add(sample.Timestamp, sample.Value) } // gob { gobs, err := want.GobEncode() if err != nil { t.Fatal(err) } var have report.Metric have.GobDecode(gobs) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } // others { for _, h := range []codec.Handle{ codec.Handle(&codec.MsgpackHandle{}), codec.Handle(&codec.JsonHandle{}), } { buf := &bytes.Buffer{} encoder := codec.NewEncoder(buf, h) want.CodecEncodeSelf(encoder) bufCopy := bytes.NewBuffer(buf.Bytes()) decoder := codec.NewDecoder(buf, h) var have report.Metric have.CodecDecodeSelf(decoder) if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } // extra check for samples decoder = codec.NewDecoder(bufCopy, h) var wire struct { Samples []report.Sample `json:"samples"` } if err := decoder.Decode(&wire); err != nil { t.Error(err) } if !reflect.DeepEqual(wantSamples, wire.Samples) { t.Error(test.Diff(wantSamples, wire.Samples)) } } } }
func TestPropagateSingleMetrics(t *testing.T) { now := time.Now() for _, c := range []struct { name string input report.Node topology string output report.Nodes }{ { name: "empty", input: report.MakeNode("empty"), topology: "", output: report.Nodes{"empty": report.MakeNode("empty")}, }, { name: "one child", input: report.MakeNode("a").WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), ), ), topology: report.Container, output: report.Nodes{ "a": report.MakeNode("a").WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }).WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), ), ), }, }, { name: "ignores other topologies", input: report.MakeNode("a").WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithTopology("otherTopology"). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), topology: report.Container, output: report.Nodes{ "a": report.MakeNode("a").WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }).WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithTopology("otherTopology"). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), }, }, { name: "two children", input: report.MakeNode("a").WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), topology: report.Container, output: report.Nodes{ "a": report.MakeNode("a").WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), }, }, { name: "ignores k8s pause container", input: report.MakeNode("a").WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithLatest(report.DoesNotMakeConnections, now, ""). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), topology: report.Container, output: report.Nodes{ "a": report.MakeNode("a").WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }).WithChildren( report.MakeNodeSet( report.MakeNode("child1"). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric1": report.MakeMetric(), }), report.MakeNode("child2"). WithLatest(report.DoesNotMakeConnections, now, ""). WithTopology(report.Container). WithMetrics(report.Metrics{ "metric2": report.MakeMetric(), }), ), ), }, }, } { got := render.PropagateSingleMetrics(c.topology)(c.input, report.Networks{}) if !reflect.DeepEqual(got, c.output) { t.Errorf("[%s] Diff: %s", c.name, test.Diff(c.output, got)) } } }
// GetLoad returns the current load averages as metrics. var GetLoad = func(now time.Time) report.Metrics { buf, err := ioutil.ReadFile("/proc/loadavg") if err != nil { return nil } toks := strings.Fields(string(buf)) if len(toks) < 3 { return nil } one, err := strconv.ParseFloat(toks[0], 64) if err != nil { return nil } return report.Metrics{ Load1: report.MakeMetric().Add(now, one), } } // GetUptime returns the uptime of the host. var GetUptime = func() (time.Duration, error) { buf, err := ioutil.ReadFile("/proc/uptime") if err != nil { return 0, err } fields := strings.Fields(string(buf)) if len(fields) != 2 { return 0, fmt.Errorf("invalid format: %s", string(buf)) }
ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, ClientIP) ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, ServerIP) UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient1IP) UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient2IP) UnknownAddress3NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient3IP) RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, RandomClientIP) // this should become an internet node KubernetesNamespace = "ping" ClientPodID = "ping/pong-a" ServerPodID = "ping/pong-b" ClientPodNodeID = report.MakePodNodeID(KubernetesNamespace, "pong-a") ServerPodNodeID = report.MakePodNodeID(KubernetesNamespace, "pong-b") ServiceID = "ping/pongservice" ServiceNodeID = report.MakeServiceNodeID(KubernetesNamespace, "pongservice") ClientProcess1CPUMetric = report.MakeMetric().Add(Now, 0.01).WithFirst(Now.Add(-1 * time.Second)) ClientProcess1MemoryMetric = report.MakeMetric().Add(Now, 0.02).WithFirst(Now.Add(-2 * time.Second)) ClientContainerCPUMetric = report.MakeMetric().Add(Now, 0.03).WithFirst(Now.Add(-3 * time.Second)) ClientContainerMemoryMetric = report.MakeMetric().Add(Now, 0.04).WithFirst(Now.Add(-4 * time.Second)) ServerContainerCPUMetric = report.MakeMetric().Add(Now, 0.05).WithFirst(Now.Add(-5 * time.Second)) ServerContainerMemoryMetric = report.MakeMetric().Add(Now, 0.06).WithFirst(Now.Add(-6 * time.Second)) ClientHostCPUMetric = report.MakeMetric().Add(Now, 0.07).WithFirst(Now.Add(-7 * time.Second)) ClientHostMemoryMetric = report.MakeMetric().Add(Now, 0.08).WithFirst(Now.Add(-8 * time.Second)) ClientHostLoad1Metric = report.MakeMetric().Add(Now, 0.09).WithFirst(Now.Add(-9 * time.Second)) ClientHostLoad5Metric = report.MakeMetric().Add(Now, 0.10).WithFirst(Now.Add(-10 * time.Second)) ClientHostLoad15Metric = report.MakeMetric().Add(Now, 0.11).WithFirst(Now.Add(-11 * time.Second)) ServerHostCPUMetric = report.MakeMetric().Add(Now, 0.12).WithFirst(Now.Add(-12 * time.Second))
func TestMetricMarshalling(t *testing.T) { t1 := time.Now().UTC() t2 := time.Now().UTC().Add(1 * time.Minute) t3 := time.Now().UTC().Add(2 * time.Minute) t4 := time.Now().UTC().Add(3 * time.Minute) wantSamples := []report.Sample{ {Timestamp: t1, Value: 0.1}, {Timestamp: t2, Value: 0.2}, {Timestamp: t3, Value: 0.3}, {Timestamp: t4, Value: 0.4}, } want := report.MakeMetric() for _, sample := range wantSamples { want = want.Add(sample.Timestamp, sample.Value) } codecs := []codec{ { "json", json.Marshal, json.Unmarshal, func(t *testing.T, codec codec, b []byte) { var wire struct { Samples []report.Sample `json:"samples"` } if err := codec.decode(b, &wire); err != nil { t.Fatalf("[%s] %s", codec.name, err) } if !reflect.DeepEqual(wantSamples, wire.Samples) { t.Errorf("[%s] diff: %sencoded: %s", codec.name, test.Diff(wantSamples, wire.Samples), b) } }, }, { "gob", func(v interface{}) ([]byte, error) { buf := &bytes.Buffer{} err := gob.NewEncoder(buf).Encode(v) return buf.Bytes(), err }, func(b []byte, v interface{}) error { return gob.NewDecoder(bytes.NewReader(b)).Decode(v) }, nil, }, } for _, codec := range codecs { b, err := codec.encode(want) if err != nil { t.Fatalf("[%s] %s", codec.name, err) } var have report.Metric err = codec.decode(b, &have) if err != nil { t.Fatalf("[%s] %s", codec.name, err) } if !reflect.DeepEqual(want, have) { t.Errorf("[%s] diff: %sencoded: %s", codec.name, test.Diff(want, have), b) } if codec.extraChecks != nil { codec.extraChecks(t, codec, b) } } }