Skip to content

Commit

Permalink
Merge pull request #6 from 128technology/develop
Browse files Browse the repository at this point in the history
Release v1.0
  • Loading branch information
thedillonb committed Nov 21, 2017
2 parents c0b32a0 + 5b025ad commit 98af498
Show file tree
Hide file tree
Showing 10 changed files with 4,506 additions and 214 deletions.
15 changes: 7 additions & 8 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
module.exports = {
"extends": "airbnb-base",
"plugins": [
"import"
],
"rules": {
"arrow-parens": 0
}
};
extends: ['airbnb-base', 'prettier'],
plugins: ['import', 'prettier'],
rules: {
'arrow-parens': 0,
'prettier/prettier': ['error', { singleQuote: true, trailingComma: 'none', printWidth: 120 }]
}
};
75 changes: 40 additions & 35 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,80 +8,85 @@ module.exports = function Grunt(grunt) {
grunt.loadNpmTasks('grunt-contrib-clean');

grunt.initConfig({

clean: ['dist'],

copy: {
src_to_dist: {
cwd: 'src',
expand: true,
src: ['**/*', '!**/*.js', '!**/*.scss'],
dest: 'dist',
dest: 'dist'
},
pluginDef: {
expand: false,
src: 'SUMMARY.md',
dest: 'dist/README.md',
},
dest: 'dist/README.md'
}
},

watch: {
rebuild_all: {
files: ['src/**/*'],
tasks: ['build'],
options: { spawn: false },
},
options: { spawn: false }
}
},

babel: {
options: {
sourceMap: true,
presets: ['es2015'],
presets: ['es2015']
},
dist: {
options: {
plugins: ['transform-es2015-modules-systemjs', 'transform-es2015-for-of'],
plugins: ['transform-es2015-modules-systemjs', 'transform-es2015-for-of']
},
files: [{
cwd: 'src',
expand: true,
src: ['**/*.js'],
dest: 'dist',
ext: '.js',
}],
files: [
{
cwd: 'src',
expand: true,
src: ['**/*.js'],
dest: 'dist',
ext: '.js'
}
]
},
distTestNoSystemJs: {
files: [{
cwd: 'src',
expand: true,
src: ['**/*.js'],
dest: 'dist/test',
ext: '.js',
}],
files: [
{
cwd: 'src',
expand: true,
src: ['**/*.js'],
dest: 'dist/test',
ext: '.js'
}
]
},
distTestsSpecsNoSystemJs: {
files: [{
expand: true,
cwd: 'tests',
src: ['**/*.js'],
dest: 'dist/test/tests',
ext: '.js',
}],
},
files: [
{
expand: true,
cwd: 'tests',
src: ['**/*.js'],
dest: 'dist/test/tests',
ext: '.js'
}
]
}
},

eslint: {
target: ['**/*.js', '!node_modules/**/*.js', '!dist/**/*.js'],
target: ['**/*.js', '!node_modules/**/*.js', '!dist/**/*.js']
},

mochaTest: {
test: {
options: {
reporter: 'spec',
reporter: 'spec'
},
src: ['dist/test/tests/test-main.js', 'dist/test/tests/*-test.js'],
},
},
src: ['dist/test/tests/test-main.js', 'dist/test/tests/*-test.js']
}
}
});

grunt.registerTask('default', ['clean', 'eslint', 'copy:src_to_dist', 'copy:pluginDef', 'babel', 'mochaTest']);
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"version": "1.0.0",
"description": "",
"main": "index.js",
"repository": {
"url": "https://github.com/128technology/grafana-datasource"
},
"scripts": {
"test": "grunt validate",
"build": "grunt",
Expand All @@ -19,7 +22,9 @@
"chai": "~3.5.0",
"eslint": "^3.16.1",
"eslint-config-airbnb-base": "^11.1.0",
"eslint-config-prettier": "^2.8.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-prettier": "^2.3.1",
"grunt": "^0.4.5",
"grunt-babel": "~6.0.0",
"grunt-cli": "^1.2.0",
Expand All @@ -33,6 +38,7 @@
"grunt-systemjs-builder": "^0.2.5",
"load-grunt-tasks": "~3.2.0",
"mocha": "^2.4.5",
"prettier": "^1.8.2",
"prunk": "~1.2.1",
"q": "~1.4.1"
},
Expand Down
158 changes: 57 additions & 101 deletions src/datasource.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
import _ from 'lodash';
import moment from 'moment';

function toIdentifiers(root) {
function select(data) {
if (_.isArray(data)) {
const obj = _.fromPairs(data.map(x => [x.id, x]));
return select(obj);
}
if (_.isObject(data)) {
return _.flatMap(_.keys(data), x => select(data[x]).map(y => [x, y]));
}
return [data];
}

return select(root)
.map(_.flattenDeep)
.map(x => {
const ptrn = _.initial(x).join('.');
const val = _.last(x);
return `${ptrn}:${val}`;
});
}

export default class GenericDatasource {
constructor(instanceSettings, $q, backendSrv, templateSrv) {
this.token = instanceSettings.jsonData.token;
Expand All @@ -40,115 +19,92 @@ export default class GenericDatasource {
data,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.token}`,
},
Authorization: `Bearer ${this.token}`
}
});
}

getVersion() {
return this.jsonRequest('/api/v1/system')
.then(x => x.softwareVersion);
getRouters() {
return this.jsonRequest('/api/v1/router').then(res => res.data);
}

query(options) {
const {
range = {},
intervalMs,
targets = [],
} = options;
getPermutations(metric, keys, router) {
const url = `/api/v1/router/${router}/stats/${metric}`;
const data = {
parameters: _.map(keys, name => ({ name, itemize: true }))
};

return this.jsonRequest(url, 'POST', data).then(res => {
const permutations = _.get(res, ['data', 0, 'permutations'], []);
const returnParams = _.flatMap(permutations, p => p.parameters);
const group = _.groupBy(returnParams, x => _.snakeCase(x.name));
return _.mapValues(group, x => _.uniq(_.map(x, 'value')));
});
}

const rangeTo = moment(range.to).utc().format('YYYY-MM-DDTHH-mm-ss');
const rangeFrom = moment(range.from).utc().format('YYYY-MM-DDTHH-mm-ss');
query(options) {
const { range = {}, intervalMs, targets = [] } = options;
const resolution = Math.max(intervalMs / 1000, 1);

const requests = targets.filter(t => !t.hide).map(targetObj => {
const target = this.templateSrv.replace(targetObj.target);
const parameters = target.split(',').map(x => x.trim()).map((x) => {
const args = x.split('=');
return { name: _.toLower(args[0]), value: args[1] };
});
const rangeTo = moment(range.to)
.utc()
.format('YYYY-MM-DDTHH-mm-ss');
const rangeFrom = moment(range.from)
.utc()
.format('YYYY-MM-DDTHH-mm-ss');

return this.jsonRequest('/api/v1/analytics/runningTransform', 'POST', {
metric: targetObj.metric,
const requests = targets.filter(t => !t.hide).map(targetObj =>
this.jsonRequest(`/api/v1/router/${targetObj.router}/metrics`, 'POST', {
id: `/stats/${targetObj.metric}`,
transform: targetObj.transform || 'sum',
order: 'ascending',
parameters,
filters: [targetObj.params],
resolution,
window: {
end: `${rangeTo}Z`,
start: `${rangeFrom}Z`,
},
})
.then(resp => ({
target: targetObj.alias || target,
datapoints: resp.data.map(p => [p.value, moment(p.date).unix() * 1000]),
}));
});
start: `${rangeFrom}Z`
}
}).then(resp => ({
target: targetObj.alias || targetObj.metric,
datapoints: resp.data.map(p => [p.value, moment(p.date).unix() * 1000])
}))
);

return this.q.all(requests).then(x => ({
data: x,
}));
return this.q.all(requests).then(data => ({ data }));
}

testDatasource() {
return this.jsonRequest('/api/v1/system')
.then((response) => {
if (response.status !== 200) {
return {
status: 'error',
message: `Target returned a ${response.status}`,
title: 'Error',
};
}

return this.jsonRequest('/api/v1/system').then(response => {
if (response.status !== 200) {
return {
status: 'success',
message: 'Data source is working',
title: 'Success',
status: 'error',
message: `Target returned a ${response.status}`,
title: 'Error'
};
});
}

return {
status: 'success',
message: 'Data source is working',
title: 'Success'
};
});
}

annotationQuery(options) {
return this.jsonRequest('/api/v1/alarm')
.then(result => result.data.map((alarm, idx) => ({
return this.jsonRequest('/api/v1/alarm').then(result =>
result.data.map((alarm, idx) => ({
annotation: {
name: `Alarm #${alarm.number}`,
datasource: options.annotation.datasource,
enable: options.annotation.enable,
showLine: true,
showLine: true
},
title: `Alarm #${alarm.number}`,
time: (moment(alarm.time).unix() * 1000) + idx,
time: moment(alarm.time).unix() * 1000 + idx,
text: alarm.message,
tags: alarm.severity,
})));
}

graphQuery(query, variables) {
return this.jsonRequest('/api/v1/graphql', 'POST', { query, variables });
}

metricFindQuery(query) {
const formattedQuery = query.replace('*', '([^.]+)');
const interpolated = this.templateSrv.replace(formattedQuery, null, 'regex');
const regexStr = `^${interpolated}:`;
const regex = new RegExp(regexStr);

return this.graphQuery(`query {
authority {
router {
id: name
node {
id: name
}
}
}
}`)
.then(x => x.data.data)
.then(x => toIdentifiers(x)
.filter(p => regex.test(p))
.map(p => _.last(p.split(':'))))
.then(x => x.map(val => ({ text: val })));
tags: alarm.severity
}))
);
}
}

0 comments on commit 98af498

Please sign in to comment.