Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions example/get-metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const { GlasnosticConsole } = require('../dist/glasnostic-api');
console.log(`logged in as ${username}`);
const environments = await api.getEnvironments();

// create a view that is capturing the traffic
const view = await api.createView(environments[0].key, 'My Channel', 'source', 'destination');
console.log('created view:', view);
// send metric data to the first network in the first environment
const networkId = environments[0].clusters[0].key;
const metric = [{
Expand All @@ -27,12 +30,12 @@ const { GlasnosticConsole } = require('../dist/glasnostic-api');
await api.sendMetric(networkId, new Date(), metric);
console.log('metric sent.');
// gets data from the last minute (=60000 milliseconds) in 10s samples (=10000 milliseconds)
const metrics = await api.getMetrics(environments[0].key, 10000, 60000);
const metrics = await api.getViewMetrics(environments[0].key, view.index,10000, 60000);
console.log('initial metrics:', metrics);
// send 2nd metric
await api.sendMetric(environments[0].clusters[0].key, new Date(), metric);
console.log('2nd metric sent.');
// get 20s of metrics after the last time getMetrics was called
const incrementalMetrics = await api.getMetrics(environments[0].key, 10000, 20000, metrics.window.start);
// get 30s of metrics after the last time getViewMetrics was called
const incrementalMetrics = await api.getViewMetrics(environments[0].key, view.index,10000, 30000, metrics.window.start);
console.log('metrics update:', incrementalMetrics);
})();
14 changes: 8 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"devDependencies": {
"@rollup/plugin-typescript": "^4.1.2",
"@types/lodash": "^4.14.155",
"@types/minimatch": "^3.0.3",
"@types/tough-cookie": "^4.0.0",
"prettier": "^2.0.5",
"rollup": "^2.15.0",
Expand All @@ -29,6 +30,7 @@
},
"dependencies": {
"got": "^11.2.0",
"minimatch": "^3.0.4",
"lodash": "^4.17.21",
"tough-cookie": "^4.0.0"
}
Expand Down
3 changes: 2 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export default {
external: [
'got',
'tough-cookie',
'lodash'
'lodash',
'minimatch'
],
plugins: [typescript({
declaration: true,
Expand Down
62 changes: 60 additions & 2 deletions src/glasnostic-api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { CookieJar } from 'tough-cookie';
import { default as got } from 'got';
import { isNil } from 'lodash';
import { makeRe } from 'minimatch';
import { PolicyHistory } from './policy-history';
import { Policies } from './policies';
import { View } from './view';
import { Environment } from './environment';
import { MetricsResponse } from './metrics';
import {RouteMetric} from "./metrics";
import { RouteMetric, MetricsResponse, MetricsNodeMap, MetricsRouteHistory, MetricsRouteSpec } from './metrics';

export * from './policies';
export * from './metric-types';
Expand Down Expand Up @@ -268,4 +268,62 @@ export class GlasnosticConsole {

return got.post(url, options).json<any>();
}

private filterMetricsByView(
nodes: MetricsNodeMap,
routes: MetricsRouteHistory[],
source: string,
destination: string
): MetricsRouteHistory[] {
interface Name {
src: string;
dst: string;
}
const parsePatterns = (patterns: string): RegExp[] => {
return patterns
.split(',')
.map((s) => makeRe(s.trim()))
.filter((p) => !!p);
};
const match = (patterns: RegExp[], subject: string): boolean => {
return patterns.some((p) => p.test(subject));
};
const lookupName = (spec: MetricsRouteSpec, nodes: MetricsNodeMap): Name => {
const routeNodes = spec.map((s) => nodes[s]);
const [src, dst] = routeNodes.map((n) =>
[n?.name, n?.instance].filter((s) => !!s).join(' ')
);
return { src, dst };
};

const srcPatterns = parsePatterns(source);
const dstPatterns = parsePatterns(destination);
return routes.filter((route) => {
const { src, dst } = lookupName(route.spec, nodes);
return match(srcPatterns, src) && match(dstPatterns, dst);
});
}

async getViewMetrics(
environmentKey: string,
viewIndex: string,
samplePeriod?: number,
duration?: number,
start?: number
): Promise<MetricsResponse> {
const getMetrics = this.getMetrics(environmentKey, samplePeriod, duration, start);
const getView = this.getView(environmentKey, viewIndex);
const [res, view] = await Promise.all([getMetrics, getView]);
if (!view) {
throw new Error('view not found');
}
if (!res.nodes || !res.routes) {
return res;
}
const routes = this.filterMetricsByView(res.nodes, res.routes, view.clients, view.services);
return {
...res,
routes,
};
}
}