func TestMerge(t *testing.T) { log.SetOutput(ioutil.Discard) var ( p1Addr = "localhost:7888" p2Addr = "localhost:7889" ) p1, err := xfer.NewTCPPublisher(p1Addr) if err != nil { t.Fatal(err) } defer p1.Close() p2, err := xfer.NewTCPPublisher(p2Addr) if err != nil { t.Fatal(err) } defer p2.Close() batchTime := 100 * time.Millisecond c := xfer.NewCollector(batchTime, "id") c.Add(p1Addr) c.Add(p2Addr) defer c.Stop() time.Sleep(batchTime / 10) // connect k1, k2 := report.MakeHostNodeID("p1"), report.MakeHostNodeID("p2") { r := report.MakeReport() r.Host.NodeMetadatas[k1] = report.NodeMetadata{"host_name": "test1"} p1.Publish(r) } { r := report.MakeReport() r.Host.NodeMetadatas[k2] = report.NodeMetadata{"host_name": "test2"} p2.Publish(r) } success := make(chan struct{}) go func() { defer close(success) for r := range c.Reports() { if r.Host.NodeMetadatas[k1]["host_name"] != "test1" { continue } if r.Host.NodeMetadatas[k2]["host_name"] != "test2" { continue } return } }() select { case <-success: case <-time.After(2 * batchTime): t.Errorf("collector didn't capture both reports") } }
func main() { var ( version = flag.Bool("version", false, "print version number and exit") publishInterval = flag.Duration("publish.interval", 1*time.Second, "publish (output) interval") listen = flag.String("listen", ":"+strconv.Itoa(xfer.ProbePort), "listen address") hostCount = flag.Int("hostcount", 10, "Number of demo hosts to generate") ) flag.Parse() if len(flag.Args()) != 0 { flag.Usage() os.Exit(1) } // -version flag: if *version { fmt.Printf("unstable\n") return } publisher, err := xfer.NewTCPPublisher(*listen) if err != nil { log.Fatal(err) } defer publisher.Close() go func() { for { publisher.Publish(DemoReport(*hostCount)) time.Sleep(*publishInterval) } }() log.Printf("%s", <-interrupt()) log.Printf("Shutting down...") }
func main() { var ( listen = flag.String("listen", ":"+strconv.Itoa(xfer.ProbePort), "listen address") probes = flag.String("probes", "", "list of all initial probes, comma separated") batch = flag.Duration("batch", 1*time.Second, "batch interval") version = flag.Bool("version", false, "print version number and exit") ) flag.Parse() if len(flag.Args()) != 0 { flag.Usage() os.Exit(1) } if *version { //fmt.Printf("%s\n", probe.Version) return } if *probes == "" { log.Fatal("no probes given via -probes") } log.Printf("starting") fixedAddresses := strings.Split(*probes, ",") // Collector deals with the probes, and generates a single merged report // every second. c := xfer.NewCollector(*batch, "id") for _, addr := range fixedAddresses { c.Add(addr) } defer c.Stop() publisher, err := xfer.NewTCPPublisher(*listen) if err != nil { log.Fatal(err) } defer publisher.Close() log.Printf("listening on %s\n", *listen) var fixedIPs []string for _, a := range fixedAddresses { if addr, _, err := net.SplitHostPort(a); err == nil { fixedIPs = append(fixedIPs, addr) } } go discover(c, publisher, fixedIPs) <-interrupt() log.Printf("shutting down") }
func TestPublisherClosesDuplicateConnections(t *testing.T) { log.SetOutput(ioutil.Discard) // Choose a port port, err := getFreePort() if err != nil { t.Fatal(err) } // Start a publisher p, err := xfer.NewTCPPublisher(port) if err != nil { t.Fatal(err) } defer p.Close() // Connect a listener conn, err := net.Dial("tcp4", "127.0.0.1"+port) if err != nil { t.Fatal(err) } defer conn.Close() if err := gob.NewEncoder(conn).Encode(xfer.HandshakeRequest{ID: "foo"}); err != nil { t.Fatal(err) } time.Sleep(time.Millisecond) // Try to connect the same listener dupconn, err := net.Dial("tcp4", "127.0.0.1"+port) if err != nil { t.Fatal(err) } // Send handshake if err := gob.NewEncoder(dupconn).Encode(xfer.HandshakeRequest{ID: "foo"}); err != nil { t.Fatal(err) } defer dupconn.Close() // Publish a message p.Publish(report.Report{}) // The first listener should receive it var r report.Report if err := gob.NewDecoder(conn).Decode(&r); err != nil { t.Fatal(err) } // The duplicate listener should have an error if err := gob.NewDecoder(dupconn).Decode(&r); err == nil { t.Errorf("expected error, got none") } else { t.Logf("dupconn got expected error: %v", err) } }
func TestTCPPublisher(t *testing.T) { log.SetOutput(ioutil.Discard) // Choose a port port, err := getFreePort() if err != nil { t.Fatal(err) } // Start a publisher p, err := xfer.NewTCPPublisher(port) if err != nil { t.Fatal(err) } defer p.Close() // Start a raw listener conn, err := net.Dial("tcp4", "127.0.0.1"+port) if err != nil { t.Fatal(err) } defer conn.Close() time.Sleep(time.Millisecond) // Send handshake if err := gob.NewEncoder(conn).Encode(xfer.HandshakeRequest{ID: "foo"}); err != nil { t.Fatal(err) } // Publish a message p.Publish(report.Report{}) // Check it was received var r report.Report if err := gob.NewDecoder(conn).Decode(&r); err != nil { t.Fatal(err) } }
func main() { var ( publishInterval = flag.Duration("publish.interval", 1*time.Second, "publish (output) interval") listenAddress = flag.String("listen", ":"+strconv.Itoa(xfer.ProbePort), "listen address") ) flag.Parse() if len(flag.Args()) != 1 { fmt.Printf("usage: fixprobe [--args] report.json\n") return } fixture := flag.Arg(0) f, err := os.Open(fixture) if err != nil { fmt.Printf("json error: %v\n", err) return } var fixedReport report.Report if err := json.NewDecoder(f).Decode(&fixedReport); err != nil { fmt.Printf("json error: %v\n", err) return } publisher, err := xfer.NewTCPPublisher(*listenAddress) if err != nil { log.Fatal(err) } defer publisher.Close() log.Printf("listening on %s", *listenAddress) for range time.Tick(*publishInterval) { publisher.Publish(fixedReport) } }
func main() { var ( httpListen = flag.String("http.listen", "", "listen address for HTTP profiling and instrumentation server") publishInterval = flag.Duration("publish.interval", 3*time.Second, "publish (output) interval") spyInterval = flag.Duration("spy.interval", time.Second, "spy (scan) interval") listen = flag.String("listen", ":"+strconv.Itoa(xfer.ProbePort), "listen address") prometheusEndpoint = flag.String("prometheus.endpoint", "/metrics", "Prometheus metrics exposition endpoint (requires -http.listen)") spyProcs = flag.Bool("processes", true, "report processes (needs root)") dockerEnabled = flag.Bool("docker", false, "collect Docker-related attributes for processes") dockerInterval = flag.Duration("docker.interval", 10*time.Second, "how often to update Docker attributes") dockerBridge = flag.String("docker.bridge", "docker0", "the docker bridge name") weaveRouterAddr = flag.String("weave.router.addr", "", "IP address or FQDN of the Weave router") procRoot = flag.String("proc.root", "/proc", "location of the proc filesystem") ) flag.Parse() if len(flag.Args()) != 0 { flag.Usage() os.Exit(1) } log.Printf("probe version %s", version) procspy.SetProcRoot(*procRoot) if *httpListen != "" { log.Printf("profiling data being exported to %s", *httpListen) log.Printf("go tool pprof http://%s/debug/pprof/{profile,heap,block}", *httpListen) if *prometheusEndpoint != "" { log.Printf("exposing Prometheus endpoint at %s%s", *httpListen, *prometheusEndpoint) http.Handle(*prometheusEndpoint, makePrometheusHandler()) } go func() { err := http.ListenAndServe(*httpListen, nil) log.Print(err) }() } if *spyProcs && os.Getegid() != 0 { log.Printf("warning: process reporting enabled, but that requires root to find everything") } publisher, err := xfer.NewTCPPublisher(*listen) if err != nil { log.Fatal(err) } defer publisher.Close() var ( hostName = hostname() hostID = hostName // TODO: we should sanitize the hostname taggers = []Tagger{newTopologyTagger(), host.NewTagger(hostID)} reporters = []Reporter{host.NewReporter(hostID, hostName), endpoint.NewReporter(hostID, hostName, *spyProcs)} processCache *process.CachingWalker ) processCache = process.NewCachingWalker(process.NewWalker(*procRoot)) reporters = append(reporters, process.NewReporter(processCache, hostID)) if *dockerEnabled { if err := report.AddLocalBridge(*dockerBridge); err != nil { log.Fatalf("failed to get docker bridge address: %v", err) } dockerRegistry, err := docker.NewRegistry(*dockerInterval) if err != nil { log.Fatalf("failed to start docker registry: %v", err) } defer dockerRegistry.Stop() taggers = append(taggers, docker.NewTagger(dockerRegistry, processCache)) reporters = append(reporters, docker.NewReporter(dockerRegistry, hostID)) } if *weaveRouterAddr != "" { weave, err := overlay.NewWeave(*weaveRouterAddr) if err != nil { log.Fatalf("failed to start Weave tagger: %v", err) } taggers = append(taggers, weave) reporters = append(reporters, weave) } log.Printf("listening on %s", *listen) quit := make(chan struct{}) defer close(quit) go func() { var ( pubTick = time.Tick(*publishInterval) spyTick = time.Tick(*spyInterval) r = report.MakeReport() ) for { select { case <-pubTick: publishTicks.WithLabelValues().Add(1) publisher.Publish(r) r = report.MakeReport() case <-spyTick: if err := processCache.Update(); err != nil { log.Printf("error reading processes: %v", err) } for _, reporter := range reporters { newReport, err := reporter.Report() if err != nil { log.Printf("error generating report: %v", err) } r.Merge(newReport) } r = Apply(r, taggers) case <-quit: return } } }() log.Printf("%s", <-interrupt()) }