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.
This commit is contained in:
Bryan Boreham
2018-06-19 22:59:01 +00:00
parent 31490e4dcb
commit 80dbd3443c
4 changed files with 66 additions and 29 deletions
+9
View File
@@ -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 }
+2
View File
@@ -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")
+45 -29
View File
@@ -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)
+10
View File
@@ -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{}