mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-04 18:51:17 +00:00
Save locked metric in the url.
- introduces "metric type" so we can flick across topos and keep the "type" of metric selected. Cheating and using label as the type atm.
This commit is contained in:
@@ -28,21 +28,26 @@ export function lockNextMetric(delta) {
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
type: ActionTypes.LOCK_METRIC,
|
||||
metricId: nextMetric
|
||||
metricId: nextMetric,
|
||||
metricType: AppStore.getAvailableCanvasMetricsTypes()[nextMetric]
|
||||
});
|
||||
updateRoute();
|
||||
}
|
||||
|
||||
export function lockMetric(metricId) {
|
||||
AppDispatcher.dispatch({
|
||||
type: ActionTypes.LOCK_METRIC,
|
||||
metricId
|
||||
metricId,
|
||||
metricType: AppStore.getAvailableCanvasMetricsTypes()[metricId]
|
||||
});
|
||||
updateRoute();
|
||||
}
|
||||
|
||||
export function unlockMetric() {
|
||||
AppDispatcher.dispatch({
|
||||
type: ActionTypes.UNLOCK_METRIC,
|
||||
});
|
||||
updateRoute();
|
||||
}
|
||||
|
||||
export function changeTopologyOption(option, value, topologyId) {
|
||||
|
||||
@@ -139,11 +139,11 @@ export default class App extends React.Component {
|
||||
topologyId={this.state.currentTopologyId} />
|
||||
|
||||
<Sidebar>
|
||||
<MetricSelector
|
||||
{this.state.availableCanvasMetrics.length > 0 && <MetricSelector
|
||||
availableCanvasMetrics={this.state.availableCanvasMetrics}
|
||||
lockedMetric={this.state.lockedMetric}
|
||||
selectedMetric={this.state.selectedMetric}
|
||||
/>
|
||||
/>}
|
||||
<Status errorUrl={this.state.errorUrl} topology={this.state.currentTopology}
|
||||
topologiesLoaded={this.state.topologiesLoaded}
|
||||
websocketClosed={this.state.websocketClosed} />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { selectMetric, lockMetric, unlockMetric } from '../actions/app-actions';
|
||||
import { label } from '../utils/data-utils';
|
||||
|
||||
|
||||
export class MetricSelectorItem extends React.Component {
|
||||
@@ -45,7 +44,7 @@ export class MetricSelectorItem extends React.Component {
|
||||
className={className}
|
||||
onMouseOver={this.onMouseOver}
|
||||
onClick={this.onMouseClick}>
|
||||
{label(metric)}
|
||||
{metric.label}
|
||||
{isLocked && <span className="sidebar-item-actions">
|
||||
<span className="sidebar-item-action fa fa-thumb-tack"></span>
|
||||
</span>}
|
||||
|
||||
@@ -62,6 +62,7 @@ let websocketClosed = true;
|
||||
|
||||
let selectedMetric = null;
|
||||
let lockedMetric = selectedMetric;
|
||||
let lockedMetricType = null;
|
||||
let availableCanvasMetrics = [];
|
||||
|
||||
|
||||
@@ -144,6 +145,7 @@ export class AppStore extends Store {
|
||||
controlPipe: this.getControlPipe(),
|
||||
nodeDetails: this.getNodeDetailsState(),
|
||||
selectedNodeId,
|
||||
lockedMetricType,
|
||||
topologyId: currentTopologyId,
|
||||
topologyOptions: topologyOptions.toJS() // all options
|
||||
};
|
||||
@@ -182,6 +184,10 @@ export class AppStore extends Store {
|
||||
return availableCanvasMetrics;
|
||||
}
|
||||
|
||||
getAvailableCanvasMetricsTypes() {
|
||||
return _.fromPairs(this.getAvailableCanvasMetrics().map(m => [m.id, m.label]));
|
||||
}
|
||||
|
||||
getControlStatus() {
|
||||
return controlStatus.toJS();
|
||||
}
|
||||
@@ -428,12 +434,14 @@ export class AppStore extends Store {
|
||||
}
|
||||
case ActionTypes.LOCK_METRIC: {
|
||||
lockedMetric = payload.metricId;
|
||||
lockedMetricType = payload.metricType;
|
||||
selectedMetric = payload.metricId;
|
||||
this.__emitChange();
|
||||
break;
|
||||
}
|
||||
case ActionTypes.UNLOCK_METRIC: {
|
||||
lockedMetric = null;
|
||||
lockedMetricType = null;
|
||||
this.__emitChange();
|
||||
break;
|
||||
}
|
||||
@@ -607,7 +615,13 @@ export class AppStore extends Store {
|
||||
.toSet()
|
||||
.sortBy(n => METRIC_LABELS[n])
|
||||
.toJS()
|
||||
.map(v => ({id: v, label: v}));
|
||||
.map(v => ({id: v, label: METRIC_LABELS[v]}));
|
||||
|
||||
const similarTypeMetric = availableCanvasMetrics.find(m => m.label === lockedMetricType);
|
||||
lockedMetric = similarTypeMetric && similarTypeMetric.id;
|
||||
if (!availableCanvasMetrics.map(m => m.id).includes(selectedMetric)) {
|
||||
selectedMetric = lockedMetric;
|
||||
}
|
||||
|
||||
if (emitChange) {
|
||||
this.__emitChange();
|
||||
@@ -654,6 +668,7 @@ export class AppStore extends Store {
|
||||
setTopology(payload.state.topologyId);
|
||||
setDefaultTopologyOptions(topologies);
|
||||
selectedNodeId = payload.state.selectedNodeId;
|
||||
lockedMetricType = payload.state.lockedMetricType;
|
||||
if (payload.state.controlPipe) {
|
||||
controlPipes = makeOrderedMap({
|
||||
[payload.state.controlPipe.id]:
|
||||
|
||||
@@ -42,16 +42,16 @@ function getNextValue(keyValues, maxValue) {
|
||||
}
|
||||
|
||||
export const METRIC_LABELS = {
|
||||
docker_cpu_total_usage: 'Container CPU',
|
||||
docker_memory_usage: 'Container Memory',
|
||||
host_cpu_usage_percent: 'Host CPU',
|
||||
host_mem_usage_bytes: 'Host Memory',
|
||||
load1: 'Host Load 1',
|
||||
load15: 'Host Load 15',
|
||||
load5: 'Host Load 5',
|
||||
open_files_count: 'Process Open files',
|
||||
process_cpu_usage_percent: 'Process CPU',
|
||||
process_memory_usage_bytes: 'Process Memory'
|
||||
docker_cpu_total_usage: 'CPU',
|
||||
docker_memory_usage: 'Memory',
|
||||
host_cpu_usage_percent: 'CPU',
|
||||
host_mem_usage_bytes: 'Memory',
|
||||
load1: 'Load 1',
|
||||
load15: 'Load 15',
|
||||
load5: 'Load 5',
|
||||
open_files_count: 'Open files',
|
||||
process_cpu_usage_percent: 'CPU',
|
||||
process_memory_usage_bytes: 'Memory'
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ const cpuMetric = (node, name, max = 100) => ({
|
||||
max
|
||||
});
|
||||
|
||||
const fileMetric = (node, name, max = 10000) => ({
|
||||
const fileMetric = (node, name, max = 1000) => ({
|
||||
samples: [{value: getNextValue([node.id, name], max)}],
|
||||
max
|
||||
});
|
||||
@@ -94,23 +94,36 @@ const loadMetric = (node, name, max = 10) => ({
|
||||
max
|
||||
});
|
||||
|
||||
const metrics = {
|
||||
// process
|
||||
square: {
|
||||
process_cpu_usage_percent: cpuMetric,
|
||||
process_memory_usage_bytes: memoryMetric,
|
||||
open_files_count: fileMetric
|
||||
},
|
||||
// container
|
||||
hexagon: {
|
||||
docker_cpu_total_usage: cpuMetric,
|
||||
docker_memory_usage: memoryMetric
|
||||
},
|
||||
// host
|
||||
circle: {
|
||||
load5: loadMetric,
|
||||
host_cpu_usage_percent: cpuMetric,
|
||||
host_mem_usage_bytes: memoryMetric
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function mergeMetrics(node) {
|
||||
if (node.pseudo) {
|
||||
if (node.pseudo || node.stack) {
|
||||
return node;
|
||||
}
|
||||
return Object.assign({}, node, {
|
||||
metrics: {
|
||||
process_cpu_usage_percent: cpuMetric(node, 'process_cpu_usage_percent'),
|
||||
process_memory_usage_bytes: memoryMetric(node, 'process_memory_usage_bytes'),
|
||||
open_files_count: fileMetric(node, 'open_files_count'),
|
||||
load1: loadMetric(node, 'load1'),
|
||||
load5: loadMetric(node, 'load5'),
|
||||
load15: loadMetric(node, 'load15'),
|
||||
docker_cpu_total_usage: cpuMetric(node, 'docker_cpu_total_usage'),
|
||||
docker_memory_usage: memoryMetric(node, 'docker_memory_usage'),
|
||||
host_cpu_usage_percent: cpuMetric(node, 'host_cpu_usage_percent'),
|
||||
host_mem_usage_bytes: memoryMetric(node, 'host_mem_usage_bytes')
|
||||
}
|
||||
metrics: _(metrics[node.shape])
|
||||
.map((fn, name) => [name, fn(node)])
|
||||
.fromPairs()
|
||||
.value()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user