mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
Merge pull request #262 from tomwilkie/more-detials
Expose some more information on containers.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
|
||||
@@ -20,8 +21,12 @@ import (
|
||||
)
|
||||
|
||||
// These constants are keys used in node metadata
|
||||
// TODO: use these constants in report/{mapping.go, detailed_node.go} - pending some circular references
|
||||
const (
|
||||
ContainerName = "docker_container_name"
|
||||
ContainerCommand = "docker_container_command"
|
||||
ContainerPorts = "docker_container_ports"
|
||||
ContainerCreated = "docker_container_created"
|
||||
|
||||
NetworkRxDropped = "network_rx_dropped"
|
||||
NetworkRxBytes = "network_rx_bytes"
|
||||
NetworkRxErrors = "network_rx_errors"
|
||||
@@ -59,7 +64,7 @@ type ClientConn interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Container represents a docker container
|
||||
// Container represents a Docker container
|
||||
type Container interface {
|
||||
ID() string
|
||||
Image() string
|
||||
@@ -163,7 +168,6 @@ func (c *container) StartGatheringStats() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// called whilst holding t.Lock()
|
||||
func (c *container) StopGatheringStats() {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
@@ -178,15 +182,36 @@ func (c *container) StopGatheringStats() {
|
||||
return
|
||||
}
|
||||
|
||||
// called whilst holding t.RLock()
|
||||
func (c *container) ports() string {
|
||||
if c.container.NetworkSettings == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
ports := []string{}
|
||||
for port, bindings := range c.container.NetworkSettings.Ports {
|
||||
if len(bindings) == 0 {
|
||||
ports = append(ports, fmt.Sprintf("%s", port))
|
||||
continue
|
||||
}
|
||||
for _, b := range bindings {
|
||||
ports = append(ports, fmt.Sprintf("%s:%s->%s", b.HostIP, b.HostPort, port))
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(ports, ", ")
|
||||
}
|
||||
|
||||
func (c *container) GetNodeMetadata() report.NodeMetadata {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
result := report.NodeMetadata{
|
||||
ContainerID: c.ID(),
|
||||
ContainerName: strings.TrimPrefix(c.container.Name, "/"),
|
||||
ImageID: c.container.Image,
|
||||
ContainerID: c.ID(),
|
||||
ContainerName: strings.TrimPrefix(c.container.Name, "/"),
|
||||
ContainerPorts: c.ports(),
|
||||
ContainerCreated: c.container.Created.Format(time.RFC822),
|
||||
ContainerCommand: c.container.Path + " " + strings.Join(c.container.Args, " "),
|
||||
ImageID: c.container.Image,
|
||||
}
|
||||
|
||||
if c.latestStats == nil {
|
||||
|
||||
@@ -8,9 +8,8 @@ import (
|
||||
|
||||
// Keys for use in NodeMetadata
|
||||
const (
|
||||
ContainerName = "docker_container_name"
|
||||
ImageID = "docker_image_id"
|
||||
ImageName = "docker_image_name"
|
||||
ImageID = "docker_image_id"
|
||||
ImageName = "docker_image_name"
|
||||
)
|
||||
|
||||
// Reporter generate Reports containing Container and ContainerImage topologies
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
const (
|
||||
mb = 1 << 20
|
||||
)
|
||||
|
||||
// DetailedNode is the data type that's yielded to the JavaScript layer when
|
||||
// we want deep information about an individual node.
|
||||
type DetailedNode struct {
|
||||
@@ -152,14 +158,26 @@ func processOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
func containerOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
rows := []Row{}
|
||||
for _, tuple := range []struct{ key, human string }{
|
||||
{"docker_container_id", "Container ID"},
|
||||
{"docker_container_name", "Container name"},
|
||||
{"docker_image_id", "Container image ID"},
|
||||
{docker.ContainerID, "ID"},
|
||||
{docker.ContainerName, "Name"},
|
||||
{docker.ImageID, "Image ID"},
|
||||
{docker.ContainerPorts, "Ports"},
|
||||
{docker.ContainerCreated, "Created"},
|
||||
{docker.ContainerCommand, "Command"},
|
||||
} {
|
||||
if val, ok := nmd[tuple.key]; ok {
|
||||
rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""})
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := nmd[docker.MemoryUsage]; ok {
|
||||
memory, err := strconv.ParseFloat(val, 64)
|
||||
if err == nil {
|
||||
memoryStr := fmt.Sprintf("%0.2f", memory/float64(mb))
|
||||
rows = append(rows, Row{Key: "Memory Usage (MB):", ValueMajor: memoryStr, ValueMinor: ""})
|
||||
}
|
||||
}
|
||||
|
||||
return Table{
|
||||
Title: "Origin Container",
|
||||
Numeric: false,
|
||||
@@ -170,8 +188,8 @@ func containerOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
func containerImageOriginTable(nmd report.NodeMetadata) (Table, bool) {
|
||||
rows := []Row{}
|
||||
for _, tuple := range []struct{ key, human string }{
|
||||
{"docker_image_id", "Container image ID"},
|
||||
{"docker_image_name", "Container image name"},
|
||||
{docker.ImageID, "Image ID"},
|
||||
{docker.ImageName, "Image name"},
|
||||
} {
|
||||
if val, ok := nmd[tuple.key]; ok {
|
||||
rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""})
|
||||
|
||||
@@ -94,9 +94,9 @@ func TestMakeDetailedNode(t *testing.T) {
|
||||
Title: "Origin Container",
|
||||
Numeric: false,
|
||||
Rows: []render.Row{
|
||||
{"Container ID", "5e4d3c2b1a", ""},
|
||||
{"Container name", "server", ""},
|
||||
{"Container image ID", "imageid456", ""},
|
||||
{"ID", "5e4d3c2b1a", ""},
|
||||
{"Name", "server", ""},
|
||||
{"Image ID", "imageid456", ""},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
@@ -80,10 +81,10 @@ func MapProcessIdentity(m report.NodeMetadata) (RenderableNode, bool) {
|
||||
// nodes, we can safely assume the presences of certain keys.
|
||||
func MapContainerIdentity(m report.NodeMetadata) (RenderableNode, bool) {
|
||||
var (
|
||||
id = m["docker_container_id"]
|
||||
major = m["docker_container_name"]
|
||||
id = m[docker.ContainerID]
|
||||
major = m[docker.ContainerName]
|
||||
minor = report.ExtractHostID(m)
|
||||
rank = m["docker_image_id"]
|
||||
rank = m[docker.ImageID]
|
||||
)
|
||||
|
||||
return NewRenderableNode(id, major, minor, rank, m), true
|
||||
@@ -94,9 +95,9 @@ func MapContainerIdentity(m report.NodeMetadata) (RenderableNode, bool) {
|
||||
// topology nodes, we can safely assume the presences of certain keys.
|
||||
func MapContainerImageIdentity(m report.NodeMetadata) (RenderableNode, bool) {
|
||||
var (
|
||||
id = m["docker_image_id"]
|
||||
major = m["docker_image_name"]
|
||||
rank = m["docker_image_id"]
|
||||
id = m[docker.ImageID]
|
||||
major = m[docker.ImageName]
|
||||
rank = m[docker.ImageID]
|
||||
)
|
||||
|
||||
return NewRenderableNode(id, major, "", rank, m), true
|
||||
@@ -181,7 +182,7 @@ func MapProcess2Container(n RenderableNode) (RenderableNode, bool) {
|
||||
|
||||
// Otherwise, if the process is not in a container, group it
|
||||
// into an "Uncontained" node
|
||||
id, ok := n.NodeMetadata["docker_container_id"]
|
||||
id, ok := n.NodeMetadata[docker.ContainerID]
|
||||
if !ok || n.Pseudo {
|
||||
return newDerivedPseudoNode(UncontainedID, UncontainedMajor, n), true
|
||||
}
|
||||
@@ -231,7 +232,7 @@ func MapContainer2ContainerImage(n RenderableNode) (RenderableNode, bool) {
|
||||
|
||||
// Otherwise, if the process is not in a container, group it
|
||||
// into an "Uncontained" node
|
||||
id, ok := n.NodeMetadata["docker_image_id"]
|
||||
id, ok := n.NodeMetadata[docker.ImageID]
|
||||
if !ok || n.Pseudo {
|
||||
return newDerivedPseudoNode(UncontainedID, UncontainedMajor, n), true
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/render"
|
||||
"github.com/weaveworks/scope/report"
|
||||
"github.com/weaveworks/scope/test"
|
||||
@@ -160,16 +161,16 @@ var (
|
||||
Adjacency: report.Adjacency{},
|
||||
NodeMetadatas: report.NodeMetadatas{
|
||||
clientProcessNodeID: report.NodeMetadata{
|
||||
"pid": clientPID,
|
||||
"comm": "curl",
|
||||
"docker_container_id": clientContainerID,
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
"pid": clientPID,
|
||||
"comm": "curl",
|
||||
docker.ContainerID: clientContainerID,
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
},
|
||||
serverProcessNodeID: report.NodeMetadata{
|
||||
"pid": serverPID,
|
||||
"comm": "apache",
|
||||
"docker_container_id": serverContainerID,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
"pid": serverPID,
|
||||
"comm": "apache",
|
||||
docker.ContainerID: serverContainerID,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
},
|
||||
nonContainerProcessNodeID: report.NodeMetadata{
|
||||
"pid": nonContainerPID,
|
||||
@@ -182,30 +183,30 @@ var (
|
||||
Container: report.Topology{
|
||||
NodeMetadatas: report.NodeMetadatas{
|
||||
clientContainerNodeID: report.NodeMetadata{
|
||||
"docker_container_id": clientContainerID,
|
||||
"docker_container_name": "client",
|
||||
"docker_image_id": clientContainerImageID,
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
docker.ContainerID: clientContainerID,
|
||||
docker.ContainerName: "client",
|
||||
docker.ImageID: clientContainerImageID,
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
},
|
||||
serverContainerNodeID: report.NodeMetadata{
|
||||
"docker_container_id": serverContainerID,
|
||||
"docker_container_name": "server",
|
||||
"docker_image_id": serverContainerImageID,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
docker.ContainerID: serverContainerID,
|
||||
docker.ContainerName: "server",
|
||||
docker.ImageID: serverContainerImageID,
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
},
|
||||
},
|
||||
},
|
||||
ContainerImage: report.Topology{
|
||||
NodeMetadatas: report.NodeMetadatas{
|
||||
clientContainerImageNodeID: report.NodeMetadata{
|
||||
"docker_image_id": clientContainerImageID,
|
||||
"docker_image_name": "client_image",
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
docker.ImageID: clientContainerImageID,
|
||||
docker.ImageName: "client_image",
|
||||
report.HostNodeID: clientHostNodeID,
|
||||
},
|
||||
serverContainerImageNodeID: report.NodeMetadata{
|
||||
"docker_image_id": serverContainerImageID,
|
||||
"docker_image_name": "server_image",
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
docker.ImageID: serverContainerImageID,
|
||||
docker.ImageName: "server_image",
|
||||
report.HostNodeID: serverHostNodeID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user