mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-31 00:16:47 +01:00
add simple metrics ui
This commit is contained in:
parent
633c9e252a
commit
9441c64f5f
@ -2,5 +2,8 @@
|
|||||||
"extends": [
|
"extends": [
|
||||||
"finn",
|
"finn",
|
||||||
"finn/node"
|
"finn/node"
|
||||||
]
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-shadow": 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list';
|
||||||
|
import Chip from 'react-toolbox/lib/chip';
|
||||||
|
|
||||||
|
class Metrics extends Component {
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.props.fetchMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { globalCount, apps, clientList } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
<ListSubHeader caption={<span>Total of {globalCount} toggles checked from {apps.length} apps ({apps.join(', ')})</span>} />
|
||||||
|
<ListDivider />
|
||||||
|
{clientList.map(({ name, count, ping, appName }, i) =>
|
||||||
|
<ListItem
|
||||||
|
leftActions={[<Chip>{count}</Chip>]}
|
||||||
|
key={name + i}
|
||||||
|
caption={appName}
|
||||||
|
legend={`${name} pinged ${ping}`} />
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default Metrics;
|
@ -0,0 +1,39 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import Metrics from './metrics-component';
|
||||||
|
import { fetchMetrics } from '../../store/metrics-actions';
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
const globalCount = state.metrics.get('globalCount');
|
||||||
|
const apps = state.metrics.get('apps').toArray();
|
||||||
|
const clients = state.metrics.get('clients').toJS();
|
||||||
|
|
||||||
|
const clientList = Object
|
||||||
|
.keys(clients)
|
||||||
|
.map((k) => {
|
||||||
|
const client = clients[k];
|
||||||
|
return {
|
||||||
|
name: k,
|
||||||
|
appName: client.appName,
|
||||||
|
count: client.count,
|
||||||
|
ping: new Date(client.ping),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => (a.ping > b.ping ? -1 : 1));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Possible stuff to ask/answer:
|
||||||
|
* toggles in use but not in unleash-server
|
||||||
|
* nr of toggles using fallbackValue
|
||||||
|
* strategies implemented but not used
|
||||||
|
*/
|
||||||
|
return {
|
||||||
|
globalCount,
|
||||||
|
apps,
|
||||||
|
clientList,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const MetricsContainer = connect(mapStateToProps, { fetchMetrics })(Metrics);
|
||||||
|
|
||||||
|
export default MetricsContainer;
|
@ -14,10 +14,11 @@ export default class UnleashNav extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<List selectable ripple className={style.navigation}>
|
<List selectable ripple className={style.navigation}>
|
||||||
{createListItem('/features', 'Feature Toggles')}
|
{createListItem('/features', 'Feature toggles')}
|
||||||
{createListItem('/strategies', 'Strategies')}
|
{createListItem('/strategies', 'Strategies')}
|
||||||
{createListItem('/history', 'Event History')}
|
{createListItem('/history', 'Event history')}
|
||||||
{createListItem('/archive', 'Archived Toggles')}
|
{createListItem('/archive', 'Archived toggles')}
|
||||||
|
{createListItem('/metrics', 'Client metrics')}
|
||||||
|
|
||||||
<ListDivider />
|
<ListDivider />
|
||||||
|
|
||||||
|
20
packages/unleash-frontend-next/src/data/metrics-api.js
Normal file
20
packages/unleash-frontend-next/src/data/metrics-api.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const URI = '/metrics';
|
||||||
|
|
||||||
|
function throwIfNotSuccess (response) {
|
||||||
|
if (!response.ok) {
|
||||||
|
let error = new Error('API call failed');
|
||||||
|
error.status = response.status;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchAll () {
|
||||||
|
return fetch(URI)
|
||||||
|
.then(throwIfNotSuccess)
|
||||||
|
.then(response => response.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchAll,
|
||||||
|
};
|
@ -15,6 +15,7 @@ import Strategies from './page/strategies';
|
|||||||
import CreateStrategies from './page/strategies/create';
|
import CreateStrategies from './page/strategies/create';
|
||||||
import HistoryPage from './page/history';
|
import HistoryPage from './page/history';
|
||||||
import Archive from './page/archive';
|
import Archive from './page/archive';
|
||||||
|
import Metrics from './page/metrics';
|
||||||
|
|
||||||
const unleashStore = createStore(
|
const unleashStore = createStore(
|
||||||
store,
|
store,
|
||||||
@ -35,6 +36,7 @@ ReactDOM.render(
|
|||||||
<Route path="/strategies/create" component={CreateStrategies} />
|
<Route path="/strategies/create" component={CreateStrategies} />
|
||||||
<Route path="/history" component={HistoryPage} />
|
<Route path="/history" component={HistoryPage} />
|
||||||
<Route path="/archive" component={Archive} />
|
<Route path="/archive" component={Archive} />
|
||||||
|
<Route path="/metrics" component={Metrics} />
|
||||||
</Route>
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>, document.getElementById('app'));
|
</Provider>, document.getElementById('app'));
|
||||||
|
6
packages/unleash-frontend-next/src/page/metrics/index.js
Normal file
6
packages/unleash-frontend-next/src/page/metrics/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Metrics from '../../component/metrics/metrics-container';
|
||||||
|
|
||||||
|
const render = () => <Metrics />;
|
||||||
|
|
||||||
|
export default render;
|
@ -5,6 +5,7 @@ import input from './input-store';
|
|||||||
import history from './history-store'; // eslint-disable-line
|
import history from './history-store'; // eslint-disable-line
|
||||||
import archive from './archive-store';
|
import archive from './archive-store';
|
||||||
import error from './error-store';
|
import error from './error-store';
|
||||||
|
import metrics from './metrics-store';
|
||||||
|
|
||||||
const unleashStore = combineReducers({
|
const unleashStore = combineReducers({
|
||||||
features,
|
features,
|
||||||
@ -13,6 +14,7 @@ const unleashStore = combineReducers({
|
|||||||
history,
|
history,
|
||||||
archive,
|
archive,
|
||||||
error,
|
error,
|
||||||
|
metrics,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default unleashStore;
|
export default unleashStore;
|
||||||
|
20
packages/unleash-frontend-next/src/store/metrics-actions.js
Normal file
20
packages/unleash-frontend-next/src/store/metrics-actions.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import api from '../data/metrics-api';
|
||||||
|
|
||||||
|
export const RECEIVE_METRICS = 'RECEIVE_METRICS';
|
||||||
|
export const ERROR_RECEIVE_METRICS = 'ERROR_RECEIVE_METRICS';
|
||||||
|
|
||||||
|
const receiveMetrics = (json) => ({
|
||||||
|
type: RECEIVE_METRICS,
|
||||||
|
value: json,
|
||||||
|
});
|
||||||
|
|
||||||
|
const errorReceiveMetrics = (statusCode) => ({
|
||||||
|
type: ERROR_RECEIVE_METRICS,
|
||||||
|
statusCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function fetchMetrics () {
|
||||||
|
return dispatch => api.fetchAll()
|
||||||
|
.then(json => dispatch(receiveMetrics(json)))
|
||||||
|
.catch(error => dispatch(errorReceiveMetrics(error)));
|
||||||
|
}
|
21
packages/unleash-frontend-next/src/store/metrics-store.js
Normal file
21
packages/unleash-frontend-next/src/store/metrics-store.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { fromJS } from 'immutable';
|
||||||
|
import { RECEIVE_METRICS } from './metrics-actions';
|
||||||
|
|
||||||
|
function getInitState () {
|
||||||
|
return fromJS({
|
||||||
|
totalCount: 0,
|
||||||
|
apps: [],
|
||||||
|
clients: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const historyStore = (state = getInitState(), action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case RECEIVE_METRICS:
|
||||||
|
return fromJS(action.value);
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default historyStore;
|
@ -73,6 +73,10 @@ module.exports = {
|
|||||||
target: 'http://localhost:4242',
|
target: 'http://localhost:4242',
|
||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
|
'/metrics': {
|
||||||
|
target: 'http://localhost:4242',
|
||||||
|
secure: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user