From 80dbd3443c544b63629567231c573746b733bd1d Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 31 May 2018 11:31:36 +0000 Subject: [PATCH] probe: Add -probe.publish.stdout option for debugging This option gives a crude way to view the raw probe data as json in the container logs, so that you can check exactly what it would have sent. We stub out the PipeClient interface with a dummy implementation in this mode. --- probe/controls/pipes.go | 9 +++++ prog/main.go | 2 ++ prog/probe.go | 74 +++++++++++++++++++++++++---------------- report/marshal.go | 10 ++++++ 4 files changed, 66 insertions(+), 29 deletions(-) diff --git a/probe/controls/pipes.go b/probe/controls/pipes.go index ec4198eed..0f2779fab 100644 --- a/probe/controls/pipes.go +++ b/probe/controls/pipes.go @@ -54,3 +54,12 @@ func (p *pipe) Close() error { } return err2 } + +// DummyPipeClient implements PipeClient when running the probe in debugging mode +type DummyPipeClient struct{} + +// PipeConnection implements controls.PipeClient +func (DummyPipeClient) PipeConnection(appID, pipeID string, pipe xfer.Pipe) error { return nil } + +// PipeClose implements controls.PipeClient +func (DummyPipeClient) PipeClose(appID, pipeID string) error { return nil } diff --git a/prog/main.go b/prog/main.go index 390171f1e..f0776b65f 100644 --- a/prog/main.go +++ b/prog/main.go @@ -93,6 +93,7 @@ type flags struct { } type probeFlags struct { + printOnStdout bool token string httpListen string publishInterval time.Duration @@ -274,6 +275,7 @@ func setupFlags(flags *flags) { flag.Bool("app-only", false, "Only run the app.") // Probe flags + flag.BoolVar(&flags.probe.printOnStdout, "probe.publish.stdout", false, "Print reports on stdout instead of sending to app, for debugging") flag.StringVar(&flags.probe.token, serviceTokenFlag, "", "Token to authenticate with cloud.weave.works") flag.StringVar(&flags.probe.token, probeTokenFlag, "", "Token to authenticate with cloud.weave.works") flag.StringVar(&flags.probe.httpListen, "probe.http.listen", "", "listen address for HTTP profiling and instrumentation server") diff --git a/prog/probe.go b/prog/probe.go index e4275aa7d..15418b711 100644 --- a/prog/probe.go +++ b/prog/probe.go @@ -130,46 +130,62 @@ func probeMain(flags probeFlags, targets []appclient.Target) { xfer.ControlHandlerFunc(handlerRegistry.HandleControlRequest), ) } - clients := appclient.NewMultiAppClient(clientFactory, flags.noControls) - defer clients.Stop() - dnsLookupFn := net.LookupIP - if flags.resolver != "" { - dnsLookupFn = appclient.LookupUsing(flags.resolver) + var clients interface { + probe.ReportPublisher + controls.PipeClient } - resolver, err := appclient.NewResolver(appclient.ResolverConfig{ - Targets: targets, - Lookup: dnsLookupFn, - Set: clients.Set, - }) - if err != nil { - log.Fatalf("Failed to create resolver: %v", err) - return - } - defer resolver.Stop() + if flags.printOnStdout { + if len(targets) > 0 { + log.Warnf("Dumping to stdout only: targets %v will be ignored", targets) + } + clients = new(struct { + report.StdoutPublisher + controls.DummyPipeClient + }) + } else { + multiClients := appclient.NewMultiAppClient(clientFactory, flags.noControls) + defer multiClients.Stop() - if flags.weaveEnabled && flags.weaveHostname != "" { - dockerBridgeIP, err := network.GetFirstAddressOf(flags.dockerBridge) + dnsLookupFn := net.LookupIP + if flags.resolver != "" { + dnsLookupFn = appclient.LookupUsing(flags.resolver) + } + resolver, err := appclient.NewResolver(appclient.ResolverConfig{ + Targets: targets, + Lookup: dnsLookupFn, + Set: multiClients.Set, + }) if err != nil { - log.Errorf("Error getting docker bridge ip: %v", err) - } else { - weaveDNSLookup := appclient.LookupUsing(dockerBridgeIP + ":53") - weaveTargets, err := appclient.ParseTargets([]string{flags.weaveHostname}) + log.Fatalf("Failed to create resolver: %v", err) + return + } + defer resolver.Stop() + + if flags.weaveEnabled && flags.weaveHostname != "" { + dockerBridgeIP, err := network.GetFirstAddressOf(flags.dockerBridge) if err != nil { - log.Errorf("Failed to parse weave targets: %v", err) + log.Errorf("Error getting docker bridge ip: %v", err) } else { - weaveResolver, err := appclient.NewResolver(appclient.ResolverConfig{ - Targets: weaveTargets, - Lookup: weaveDNSLookup, - Set: clients.Set, - }) + weaveDNSLookup := appclient.LookupUsing(dockerBridgeIP + ":53") + weaveTargets, err := appclient.ParseTargets([]string{flags.weaveHostname}) if err != nil { - log.Errorf("Failed to create weave resolver: %v", err) + log.Errorf("Failed to parse weave targets: %v", err) } else { - defer weaveResolver.Stop() + weaveResolver, err := appclient.NewResolver(appclient.ResolverConfig{ + Targets: weaveTargets, + Lookup: weaveDNSLookup, + Set: multiClients.Set, + }) + if err != nil { + log.Errorf("Failed to create weave resolver: %v", err) + } else { + defer weaveResolver.Stop() + } } } } + clients = multiClients } p := probe.New(flags.spyInterval, flags.publishInterval, clients, flags.noControls) diff --git a/report/marshal.go b/report/marshal.go index 255f5a6fd..65921e3c5 100644 --- a/report/marshal.go +++ b/report/marshal.go @@ -26,6 +26,16 @@ func (s *dummySelfer) CodecEncodeSelf(encoder *codec.Encoder) { panic("This shouldn't happen: perhaps something has gone wrong in code generation?") } +// StdoutPublisher is useful when debugging +type StdoutPublisher struct{} + +// Publish implements probe.ReportPublisher +func (StdoutPublisher) Publish(rep Report) error { + handle := &codec.JsonHandle{Indent: 2} + handle.Canonical = true + return codec.NewEncoder(os.Stdout, handle).Encode(rep) +} + // WriteBinary writes a Report as a gzipped msgpack into a bytes.Buffer func (rep Report) WriteBinary() (*bytes.Buffer, error) { w := &bytes.Buffer{}