Пример #1
0
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)
	}
}
Пример #2
0
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))
	}
}
Пример #3
0
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))
	}
}
Пример #4
0
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))
	}
}
Пример #5
0
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
}
Пример #6
0
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
}
Пример #7
0
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))
	}
}
Пример #8
0
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)
}
Пример #9
0
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)
	}
}
Пример #10
0
// 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
}
Пример #11
0
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
}
Пример #12
0
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))
	}
}
Пример #13
0
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)
	}
}
Пример #14
0
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))
	}
}
Пример #15
0
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
}
Пример #16
0
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))
	}
}
Пример #17
0
	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
Пример #18
0
		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))
Пример #19
0
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)
		}
	}
}
Пример #20
0
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"})
	}
}
Пример #21
0
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))
			}
		}
	}

}
Пример #22
0
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))
		}
	}
}
Пример #23
0
// 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))
	}
Пример #24
0
	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))
Пример #25
0
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)
		}
	}
}