From 7632e0b3c5f4e06321228b235efdea72dcd6ec81 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Fri, 4 Mar 2016 17:40:48 +0000 Subject: [PATCH] Adding support for plugins, with basic example of iowait, and ebpf Squash of: * Include plugins in the report * show plugin list in the UI * moving metric and metadata templates into the probe reports * update js for prime -> priority * added retry to plugin handshake * added iowait plugin * review feedback * plugin documentation --- app/api_topology.go | 4 +- app/router.go | 21 +- client/app/scripts/actions/app-actions.js | 3 +- client/app/scripts/components/app.js | 3 + .../node-details/node-details-info.js | 2 +- client/app/scripts/components/plugins.js | 22 ++ client/app/scripts/stores/app-store.js | 7 + common/xfer/constants.go | 7 +- common/xfer/plugin_spec.go | 223 ++++++++++++++ common/xfer/plugin_spec_internal_test.go | 225 ++++++++++++++ examples/plugins/README.md | 57 ++++ examples/plugins/iowait/.gitignore | 1 + examples/plugins/iowait/Dockerfile | 6 + examples/plugins/iowait/Makefile | 19 ++ examples/plugins/iowait/main.go | 138 +++++++++ experimental/graphviz/render.go | 2 +- probe/docker/reporter.go | 31 +- probe/host/reporter.go | 20 ++ probe/kubernetes/reporter.go | 24 +- probe/overlay/weave.go | 4 + probe/plugins/registry.go | 265 ++++++++++++++++ probe/plugins/registry_internal_test.go | 285 ++++++++++++++++++ probe/plugins/reporter.go | 25 ++ probe/plugins/unix_round_tripper.go | 27 ++ probe/probe.go | 13 + probe/process/reporter.go | 20 +- prog/main.go | 5 +- prog/probe.go | 19 ++ render/detailed/connections.go | 18 +- render/detailed/docker_labels.go | 6 +- render/detailed/docker_labels_test.go | 4 +- render/detailed/metadata.go | 179 +---------- render/detailed/metadata_test.go | 20 +- render/detailed/metrics.go | 167 +--------- render/detailed/metrics_test.go | 115 ++++--- render/detailed/node.go | 15 +- render/detailed/node_test.go | 92 +++--- render/detailed/summary.go | 38 +-- render/detailed/summary_test.go | 39 ++- render/mapping.go | 10 +- report/counters.go | 4 +- report/metadata_template.go | 162 ++++++++++ report/metric_row.go | 130 ++++++++ report/metric_template.go | 86 ++++++ report/metrics.go | 6 + report/report.go | 10 + report/topology.go | 40 ++- scope | 1 + test/fixture/report_fixture.go | 8 + test/fs/fs.go | 77 ++++- 50 files changed, 2168 insertions(+), 537 deletions(-) create mode 100644 client/app/scripts/components/plugins.js create mode 100644 common/xfer/plugin_spec.go create mode 100644 common/xfer/plugin_spec_internal_test.go create mode 100644 examples/plugins/README.md create mode 100644 examples/plugins/iowait/.gitignore create mode 100644 examples/plugins/iowait/Dockerfile create mode 100644 examples/plugins/iowait/Makefile create mode 100644 examples/plugins/iowait/main.go create mode 100644 probe/plugins/registry.go create mode 100644 probe/plugins/registry_internal_test.go create mode 100644 probe/plugins/reporter.go create mode 100644 probe/plugins/unix_round_tripper.go create mode 100644 report/metadata_template.go create mode 100644 report/metric_row.go create mode 100644 report/metric_template.go diff --git a/app/api_topology.go b/app/api_topology.go index e05b385b2..57796d90f 100644 --- a/app/api_topology.go +++ b/app/api_topology.go @@ -35,7 +35,7 @@ func handleTopology(ctx context.Context, rep Reporter, renderer render.Renderer, return } respondWith(w, http.StatusOK, APITopology{ - Nodes: detailed.Summaries(renderer.Render(report)), + Nodes: detailed.Summaries(report, renderer.Render(report)), }) } @@ -119,7 +119,7 @@ func handleWebsocket( log.Errorf("Error generating report: %v", err) return } - newTopo := detailed.Summaries(renderer.Render(report)) + newTopo := detailed.Summaries(report, renderer.Render(report)) diff := detailed.TopoDiff(previousTopo, newTopo) previousTopo = newTopo diff --git a/app/router.go b/app/router.go index 0f9f19780..260a08a55 100644 --- a/app/router.go +++ b/app/router.go @@ -84,7 +84,7 @@ func gzipHandler(h http.HandlerFunc) http.HandlerFunc { func RegisterTopologyRoutes(router *mux.Router, r Reporter) { get := router.Methods("GET").Subrouter() get.HandleFunc("/api", - gzipHandler(requestContextDecorator(apiHandler))) + gzipHandler(requestContextDecorator(apiHandler(r)))) get.HandleFunc("/api/topology", gzipHandler(requestContextDecorator(topologyRegistry.makeTopologyList(r)))) get.HandleFunc("/api/topology/{topology}", @@ -130,10 +130,17 @@ func RegisterReportPostHandler(a Adder, router *mux.Router) { })) } -func apiHandler(_ context.Context, w http.ResponseWriter, r *http.Request) { - respondWith(w, http.StatusOK, xfer.Details{ - ID: UniqueID, - Version: Version, - Hostname: hostname.Get(), - }) +func apiHandler(rep Reporter) CtxHandlerFunc { + return func(ctx context.Context, w http.ResponseWriter, r *http.Request) { + report, err := rep.Report(ctx) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + respondWith(w, http.StatusOK, xfer.Details{ + ID: UniqueID, + Version: Version, + Hostname: hostname.Get(), + Plugins: report.Plugins, + }) + } } diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js index 61327d4bb..2094e257b 100644 --- a/client/app/scripts/actions/app-actions.js +++ b/client/app/scripts/actions/app-actions.js @@ -317,7 +317,8 @@ export function receiveApiDetails(apiDetails) { AppDispatcher.dispatch({ type: ActionTypes.RECEIVE_API_DETAILS, hostname: apiDetails.hostname, - version: apiDetails.version + version: apiDetails.version, + plugins: apiDetails.plugins }); } diff --git a/client/app/scripts/components/app.js b/client/app/scripts/components/app.js index ab9babe27..198d76441 100644 --- a/client/app/scripts/components/app.js +++ b/client/app/scripts/components/app.js @@ -11,6 +11,7 @@ import HelpPanel from './help-panel'; import Status from './status.js'; import Topologies from './topologies.js'; import TopologyOptions from './topology-options.js'; +import Plugins from './plugins.js'; import { getApiDetails, getTopologies } from '../utils/web-api-utils'; import { pinNextMetric, hitEsc, unpinMetric, selectMetric, toggleHelp } from '../actions/app-actions'; @@ -53,6 +54,7 @@ function getStateFromStores() { updatePaused: AppStore.isUpdatePaused(), updatePausedAt: AppStore.getUpdatePausedAt(), version: AppStore.getVersion(), + plugins: AppStore.getPlugins(), websocketClosed: AppStore.isWebsocketClosed() }; } @@ -178,6 +180,7 @@ export default class App extends React.Component { +