Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
jotak committed Feb 9, 2018
2 parents 00fa4eb + af4efe5 commit 5cc1f5e
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 8 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ Example, JSON posted on [the Hawkular's REST API](http://www.hawkular.org/hawkul

In the case of Hawkular Alerts events, you need to provide the trigger ID (several comma-separated IDs are allowed).

### Legend

Metric names can be customized in chart legend. The `Legend` field can receive regular expressions in that purpose. Regex must be written between double curly braces, and include a parentheses group to point to what must be written: `{{(.*)}}`

_Example:_
> From metric name `pod/c6e2a9ab-8d1c-11e7-b7be-06415eb17bbf/custom/haproxy_server_bytes_in_total{namespace=my-namespace,pod=web-45-6f464,route=web,server=10.1.10.138:8080,service=web}`
>
> Legend: `HAProxy Server Bytes In {{namespace=([^,}]+)}} / {{pod=([^,}]+)}}`
>
> Result: `HAProxy Server Bytes In my-namespace / web-45-6f464`
## Installing from sources

Additional information on installing from sources can be found on [hawkular.org](http://www.hawkular.org/hawkular-clients/grafana/docs/quickstart-guide/).
Expand Down
5 changes: 3 additions & 2 deletions spec/datasource-downsamples_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ describe('HawkularDatasource for downsamples', () => {
to: 30
},
targets: [{
refId: 'A',
seriesAggFn: 'sum',
stats: ['avg', '90 %ile'],
tags: [{name: 'type', value: 'memory'}],
Expand Down Expand Up @@ -245,9 +246,9 @@ describe('HawkularDatasource for downsamples', () => {

ctx.ds.query(options).then(result => {
expect(result.data).to.have.length(2);
expect(result.data[1].target).to.equal('avg');
expect(result.data[1].target).to.equal('[A] avg');
expect(result.data[1].datapoints).to.deep.equal([[20.25, 20], [23.25, 25]]);
expect(result.data[0].target).to.equal('90 %ile');
expect(result.data[0].target).to.equal('[A] 90 %ile');
expect(result.data[0].datapoints).to.deep.equal([[23.1, 20], [26.1, 25]]);
}).then(v => done(), err => done(err));
});
Expand Down
19 changes: 19 additions & 0 deletions spec/datasource_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,23 @@ describe('HawkularDatasource', () => {
expect(result[1]).to.deep.equal({ text: 'app', value: 'app' });
}).then(v => done(), err => done(err));
});

it('should get name without legend', done => {
let legend = ctx.ds.queryProcessor.legend({}, "my-metric");
expect(legend).to.equal('my-metric');
done();
});

it('should get simple legend', done => {
let legend = ctx.ds.queryProcessor.legend({legend: "my-legend"}, "my-metric");
expect(legend).to.equal('my-legend');
done();
});

it('should resolve regex in legend', done => {
let legend = ctx.ds.queryProcessor.legend({legend: "my-legend {{a}} {{foo=([^,}]+)}} {{foo2=([^,}]+)}}"},
"my-metric{foo=bar,foo2=bar2}");
expect(legend).to.equal('my-legend {{a}} bar bar2');
done();
});
});
9 changes: 9 additions & 0 deletions src/partials/query.editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,13 @@
</div>
</div>
</div>
<!-- chart panel -->
<div ng-if="ctrl.panel.type !== 'singlestat'">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword fix-query-keyword">Legend</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.legend" ng-change="ctrl.onChangeInternal()" placeholder="default">
</div>
</div>
</div>
</query-editor-row>
30 changes: 24 additions & 6 deletions src/queryProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class QueryProcessor {
this.typeResources = typeResources;
this.numericMapping = point => [point.value, point.timestamp];
this.availMapping = point => [point.value == 'up' ? 1 : 0, point.timestamp];
this.legendRegexp = /{{(.+?)(?=}})}}/g;
}

run(target, options) {
Expand Down Expand Up @@ -102,12 +103,29 @@ export class QueryProcessor {
return allSeries.map(timeSerie => {
return {
refId: target.refId,
target: timeSerie.prefix + timeSerie.id,
target: this.legend(target, timeSerie.prefix + timeSerie.id),
datapoints: timeSerie.data.map(target.type == 'availability' ? this.availMapping : this.numericMapping)
};
});
}

legend(target, name) {
if (target.legend) {
let legend = target.legend.replace(this.legendRegexp, function(str, group) {
try {
let match = new RegExp(group).exec(name);
if (match && match.length > 1) {
return match[1];
}
} catch(e) {
}
return str;
});
return legend;
}
return name;
}

processRawResponseLegacy(target, metric, data) {
let datapoints;
if (target.type == 'availability') {
Expand Down Expand Up @@ -159,22 +177,22 @@ export class QueryProcessor {
// Response example: [ { tenant: 't1', result: [...] }, { tenant: 't2', result: [...] } ]
// Detailed `data[i].result`: [{start:1234, end:5678, avg:100.0, min:90.0, max:110.0, (...), percentiles:[{quantile: 90, value: 105.0}]}]
const flatten = [];
const prefixer = multiTenantsData.length > 1 ? (tenant) => `[${tenant}] ` : (tenant) => '';
const prefixer = multiTenantsData.length > 1 ? (tenant) => `[${target.refId}: ${tenant}] ` : (tenant) => `[${target.refId}] `;
multiTenantsData.forEach(tenantData => {
if (tenantData.result) {
target.stats.forEach(stat => {
const percentile = this.getPercentileValue(stat);
if (percentile) {
flatten.push({
refId: target.refId,
target: prefixer(tenantData.tenant) + stat,
target: this.legend(target, prefixer(tenantData.tenant) + stat),
datapoints: tenantData.result.filter(bucket => !bucket.empty)
.map(bucket => [this.findQuantileInBucket(percentile, bucket), bucket.start])
});
} else {
flatten.push({
refId: target.refId,
target: prefixer(tenantData.tenant) + stat,
target: this.legend(target, prefixer(tenantData.tenant) + stat),
datapoints: tenantData.result.filter(bucket => !bucket.empty).map(bucket => [bucket[stat], bucket.start])
});
}
Expand Down Expand Up @@ -222,14 +240,14 @@ export class QueryProcessor {
if (percentile) {
series.push({
refId: target.refId,
target: `${prefix}${metricId} [${stat}]`,
target: this.legend(target, `${prefix}${metricId} [${stat}]`),
datapoints: buckets.filter(bucket => !bucket.empty)
.map(bucket => [this.findQuantileInBucket(percentile, bucket), bucket.start])
});
} else {
series.push({
refId: target.refId,
target: `${prefix}${metricId} [${stat}]`,
target: this.legend(target, `${prefix}${metricId} [${stat}]`),
datapoints: buckets.filter(bucket => !bucket.empty).map(bucket => [bucket[stat], bucket.start])
});
}
Expand Down

0 comments on commit 5cc1f5e

Please sign in to comment.