Skip to content
This repository has been archived by the owner on Jan 23, 2025. It is now read-only.

Commit

Permalink
Merge pull request #52 from CorpGlory/kentik-custom-dimensions-suppor…
Browse files Browse the repository at this point in the history
…t-#46

Kentik custom dimensions support #46
  • Loading branch information
daniellee authored Oct 12, 2018
2 parents 6e09636 + 4305d47 commit 229e044
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 33 deletions.
62 changes: 51 additions & 11 deletions specs/datasource/datasource.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,60 @@
import { Datasource } from '../../src/datasource/module';
import {Datasource} from '../../src/datasource/module';
import {KentikAPI} from '../../src/datasource/kentikAPI';
import {KentikProxy} from '../../src/datasource/kentikProxy';

describe('KentikDatasource', () => {
let ctx: any = {};

beforeEach(function () {
ctx.kentikProxySrv = {};
ctx.templateSrv = {};

let instanceSettings = {};
ctx.ds = new Datasource(instanceSettings, {}, ctx.templateSrv);
});
const data = {
customDimensions: [
{
display_name: 'just-testing', name: 'c_test',
populators: [
{ value: 'value1' }, { value: 'value2' }
]
},
{
display_name: 'just-testing-2', name: 'c_test_2',
populators: [
{ value: 'value3' }, { value: 'value4' }
]
}
],
rows: [
{ src_geo_city: 'city' }
]
};
beforeEach(() => createDatasourceInstance(ctx, data));

describe('When querying Kentik data', () => {
it('pass', (done) => {
done();
it('Should return tag values for default dimensions', async () => {
const tagValues = await ctx.ds.getTagValues({ key: 'Source City' });
expect(tagValues).toHaveLength(1);
expect(tagValues[0]).toEqual({ text: 'city' });
});

it('Should return tag values for custom dimensions', async () => {
const tagValues = await ctx.ds.getTagValues({ key: 'Custom just-testing-2' });
expect(tagValues).toHaveLength(2);
expect(tagValues[0]).toEqual({ text: 'value3' });
expect(tagValues[1]).toEqual({ text: 'value4' });
});
});

});

function createDatasourceInstance(ctx, data) {
ctx.instanceSettings = {};
ctx.templateSrv = {};
ctx.backendSrv = {
datasourceRequest: function () {
return Promise.resolve({
status: 200, data
});
}
};

ctx.kentikAPI = new KentikAPI(ctx.backendSrv);
ctx.kentikProxy = new KentikProxy({}, ctx.kentikAPI);

ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.kentikProxy);
}
56 changes: 56 additions & 0 deletions specs/datasource/kentikProxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {KentikAPI} from '../../src/datasource/kentikAPI';
import {KentikProxy} from '../../src/datasource/kentikProxy';

describe('KentikProxy', () => {
let ctx: any = {};

describe('When getting custom dimensions', () => {
const data = {
customDimensions: [
{
display_name: 'just-testing', name: 'c_test',
populators: [
{ value: 'value1' }, { value: 'value2' }
]
},
{
display_name: 'just-testing-2', name: 'c_test_2',
populators: [
{ value: 'value3' }, { value: 'value4' }
]
}
]
};
beforeEach(() => getKentikProxyInstance(ctx, data));

it('Should parse it properly', async () => {
const dimensions = await ctx.kentikProxy.getCustomDimensions();
expect(dimensions).toHaveLength(2);
expect(dimensions[0]).toEqual({
text: 'Custom just-testing',
value: 'c_test',
field: 'c_test',
values: ['value1', 'value2'],
});
expect(dimensions[1]).toEqual({
text: 'Custom just-testing-2',
value: 'c_test_2',
field: 'c_test_2',
values: ['value3', 'value4'],
});
});
});
});

function getKentikProxyInstance(ctx, data) {
ctx.backendSrv = {
datasourceRequest: function () {
return Promise.resolve({
status: 200, data
});
}
};

ctx.kentikAPI = new KentikAPI(ctx.backendSrv);
ctx.kentikProxy = new KentikProxy({}, ctx.kentikAPI);
}
51 changes: 35 additions & 16 deletions src/datasource/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class KentikDatasource {
return value.join(',');
}

query(options) {
async query(options) {
if (!options.targets || options.targets.length === 0) {
return Promise.resolve({ data: [] });
}
Expand All @@ -40,7 +40,8 @@ class KentikDatasource {
);

let kentikFilters = this.templateSrv.getAdhocFilters(this.name);
kentikFilters = queryBuilder.convertToKentikFilterGroup(kentikFilters);
const customDimensions = await this.kentik.getCustomDimensions();
kentikFilters = queryBuilder.convertToKentikFilterGroup(kentikFilters, customDimensions);

const queryOptions = {
deviceNames: deviceNames,
Expand All @@ -64,7 +65,7 @@ class KentikDatasource {
});
}

processResponse(query, mode, options, data) {
async processResponse(query, mode, options, data) {
if (!data.results) {
return Promise.reject({ message: 'no kentik data' });
}
Expand All @@ -74,7 +75,12 @@ class KentikDatasource {
return [];
}

const metricDef = _.find(metricList, { value: query.dimension[0] });
const extendedMetricList = await this._getExtendedDimensionsList(metricList);
const metricDef = _.find(
extendedMetricList,
{ value: query.dimension[0] }
);

const unitDef = _.find(unitList, { value: query.metric });

if (mode === 'table') {
Expand Down Expand Up @@ -141,12 +147,12 @@ class KentikDatasource {
return [table];
}

metricFindQuery(query) {
async metricFindQuery(query) {
if (query === 'metrics()') {
return Promise.resolve(metricList);
return this._getExtendedDimensionsList(metricList);
}
if (query === 'units()') {
return Promise.resolve(unitList);
return unitList;
}

return this.kentik.getDevices().then(devices => {
Expand All @@ -156,22 +162,35 @@ class KentikDatasource {
});
}

getTagKeys() {
return Promise.resolve(filterFieldList);
async getTagKeys() {
return this._getExtendedDimensionsList(filterFieldList);
}

getTagValues(options) {
async getTagValues(options) {
if (options) {
const field = _.find(filterFieldList, { text: options.key }).field;
return this.kentik.getFieldValues(field).then(result => {
return result.rows.map(row => {
return { text: row[field].toString() };
const filter = _.find(filterFieldList, { text: options.key });

if (filter === undefined) {
const customDimensions = await this.kentik.getCustomDimensions();
const dimension = _.find(customDimensions, { text: options.key });
return dimension.values.map(value => ({ text: value }));
} else {
const field = filter.field;
return this.kentik.getFieldValues(field).then(result => {
return result.rows.map(row => {
return { text: row[field].toString() };
});
});
});
}
} else {
return Promise.resolve([]);
return [];
}
}

private async _getExtendedDimensionsList(list: Array<any>) {
const customDimensions = await this.kentik.getCustomDimensions();
return _.concat(list, customDimensions);
}
}

export { KentikDatasource };
7 changes: 6 additions & 1 deletion src/datasource/kentikAPI.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import angular from 'angular';

class KentikAPI {
export class KentikAPI {
baseUrl: string;

/** @ngInject */
Expand All @@ -23,6 +23,11 @@ class KentikAPI {
return this.invokeSQLQuery(query);
}

async getCustomDimensions() {
const data = await this._get('/api/v5/customdimensions');
return data.data.customDimensions;
}

invokeTopXDataQuery(query) {
const kentikV5Query = {
queries: [{ query: query, bucketIndex: 0 }],
Expand Down
22 changes: 21 additions & 1 deletion src/datasource/kentikProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function getMaxRefreshInterval(query) {
}
}

class KentikProxy {
export class KentikProxy {
kentikAPI: any;
cache: any;
cacheUpdateInterval: number;
Expand Down Expand Up @@ -113,6 +113,26 @@ class KentikProxy {
});
}
}

async getCustomDimensions() {
if (this.cache.customDimensions === undefined) {
const customDimensions = await this.kentikAPI.getCustomDimensions();
this.cache.customDimensions = customDimensions.map(dimension => ({
values: this._getDimensionPopulatorsValues(dimension),
text: `Custom ${dimension.display_name}`,
value: dimension.name,
field: dimension.name
}));
}
return this.cache.customDimensions;
}

private _getDimensionPopulatorsValues(dimension) {
return dimension.populators.reduce((values, populator) => {
values.push(populator.value);
return values;
}, []);
}
}

angular.module('grafana.services').service('kentikProxySrv', KentikProxy);
9 changes: 5 additions & 4 deletions src/datasource/query_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,16 @@ function buildTopXdataQuery(options) {
return query;
}

function convertToKentikFilter(filterObj) {
function convertToKentikFilter(filterObj, customDimensions: Array<any>) {
// Use Kentik 'not equal' style
if (filterObj.operator === '!=') {
filterObj.operator = '<>';
}

// If no field definition found assume that custom field is used.
let filterField;
const filterFieldDef = _.find(filterFieldList, { text: filterObj.key });
const filterFieldDefExtended = _.concat(filterFieldList, customDimensions);
const filterFieldDef = _.find(filterFieldDefExtended, { text: filterObj.key });
if (filterFieldDef) {
filterField = filterFieldDef.field;
} else {
Expand All @@ -145,9 +146,9 @@ function convertToKentikFilter(filterObj) {
};
}

function convertToKentikFilterGroup(filters) {
function convertToKentikFilterGroup(filters, customDimensions = []) {
if (filters.length) {
const kentikFilters = _.map(filters, convertToKentikFilter);
const kentikFilters = _.map(filters, filter => convertToKentikFilter(filter, customDimensions));
let connector = 'All';
if (
filters[0].condition &&
Expand Down

0 comments on commit 229e044

Please sign in to comment.