예제 #1
0
파일: merge_test.go 프로젝트: davkal/scope
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")
	}
}
예제 #2
0
파일: main.go 프로젝트: neviim/scope
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...")
}
예제 #3
0
파일: main.go 프로젝트: neviim/scope
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")
}
예제 #4
0
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)
	}
}
예제 #5
0
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)
	}
}
예제 #6
0
파일: main.go 프로젝트: neviim/scope
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)
	}
}
예제 #7
0
파일: main.go 프로젝트: neviim/scope
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())
}