Skip to content

Commit

Permalink
CIRC-9448 add anonymized usage statistics along with a toggle (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
graefen authored Jan 16, 2023
1 parent a36e022 commit 3a35082
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.9.27

* Added anonymized usage statistics so we can prioritize development time based
on feature usage.

## 0.9.26

* A new variable query type is available: "Last Metric Value" which will
Expand Down
2 changes: 1 addition & 1 deletion dist/module.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/module.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "circonus-irondb-datasource",
"version": "0.9.26",
"version": "0.9.27",
"description": "IRONdb Data Source for Grafana.",
"scripts": {
"build": "grafana-toolkit plugin:build",
Expand Down
1 change: 1 addition & 0 deletions src/config_ctrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class IrondbConfigCtrl {
this.current.jsonData.queryPrefixDefault = '';
this.current.jsonData.queryPrefix =
this.current.jsonData.queryPrefix || this.current.jsonData.queryPrefixDefault;
this.current.jsonData.disableUsageStatistics = _.defaultTo(this.current.jsonData.disableUsageStatistics, false);
}

resultsLimitKeyUp(event) {
Expand Down
240 changes: 238 additions & 2 deletions src/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export interface IrondbOptions extends DataSourceJsonData {
allowGraphite: boolean; // Whether to show UI elements to allow the use of graphite-style queries
hideCAQLWarnings: boolean; // Whether to hide CAQL warnings and show the data, instead of throwing errors to show the warnings
queryPrefix: string; // When using graphite-style queries, this is any pre-set query prefix needed for the IRONdb setup in use
disableUsageStatistics: boolean; // Whether to disable anonymized usage statistics
}

export default class IrondbDatasource extends DataSourceApi<IrondbQueryInterface, IrondbOptions> {
Expand All @@ -165,6 +166,8 @@ export default class IrondbDatasource extends DataSourceApi<IrondbQueryInterface
allowGraphite: boolean;
hideCAQLWarnings: boolean;
queryPrefix: string;
disableUsageStatistics: boolean;
userHash: string;
url: any;
apiToken: string;
appName: string;
Expand Down Expand Up @@ -196,8 +199,12 @@ export default class IrondbDatasource extends DataSourceApi<IrondbQueryInterface
throw new Error('Unsupported HTTP method type: ' + (httpMethod || '?'));
}

static setupCache(useCaching, backendSrv) {
static setupCache(useCaching, backendSrv, datasourceInstance) {
const doRequest = (options) => {
if (!datasourceInstance.disableUsageStatistics) {
const urlHasParams = !!~options.url.indexOf('?');
options.url += (urlHasParams ? '&' : '?') +'u='+ datasourceInstance.userHash;
}
return backendSrv.datasourceRequest(options);
};
if (!useCaching) {
Expand Down Expand Up @@ -245,11 +252,22 @@ export default class IrondbDatasource extends DataSourceApi<IrondbQueryInterface
this.allowGraphite = instanceSettings.jsonData.allowGraphite;
this.hideCAQLWarnings = instanceSettings.jsonData.hideCAQLWarnings;
this.queryPrefix = instanceSettings.jsonData.queryPrefix;
this.disableUsageStatistics = instanceSettings.jsonData.disableUsageStatistics;
this.userHash = '';
this.url = instanceSettings.url;
this.supportAnnotations = false;
this.supportMetrics = true;
this.appName = 'Grafana';
this.datasourceRequest = IrondbDatasource.setupCache(this.useCaching, backendSrv);
this.datasourceRequest = IrondbDatasource.setupCache(this.useCaching, backendSrv, this);

if (!this.disableUsageStatistics) {
backendSrv
.get('/api/user')
.then((info) => {
this.userHash = md5(info.email);
})
.catch((e) => window.console.log(e));
}
}

query(options: DataQueryRequest<IrondbQueryInterface>): Promise<DataQueryResponse> {
Expand Down Expand Up @@ -2513,3 +2531,221 @@ function getOtherField(name): MutableField {
values: new ArrayVector(),
};
}

/*
* http://www.myersdaily.org/joseph/javascript/md5-text.html
*/
const md5 = (function (global) {
var hex_chr = '0123456789abcdef'.split(''),
use_alternate_add32 = false;

/* Some IEs are the only ones I know of that need the alternate function */
if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
use_alternate_add32 = true;
}

return md5;


function md5(s) {
return hex(md51(s));
}


function md5cycle(x, k) {
var a = x[0],
b = x[1],
c = x[2],
d = x[3];

a = ff(a, b, c, d, k[0], 7, -680876936);
d = ff(d, a, b, c, k[1], 12, -389564586);
c = ff(c, d, a, b, k[2], 17, 606105819);
b = ff(b, c, d, a, k[3], 22, -1044525330);
a = ff(a, b, c, d, k[4], 7, -176418897);
d = ff(d, a, b, c, k[5], 12, 1200080426);
c = ff(c, d, a, b, k[6], 17, -1473231341);
b = ff(b, c, d, a, k[7], 22, -45705983);
a = ff(a, b, c, d, k[8], 7, 1770035416);
d = ff(d, a, b, c, k[9], 12, -1958414417);
c = ff(c, d, a, b, k[10], 17, -42063);
b = ff(b, c, d, a, k[11], 22, -1990404162);
a = ff(a, b, c, d, k[12], 7, 1804603682);
d = ff(d, a, b, c, k[13], 12, -40341101);
c = ff(c, d, a, b, k[14], 17, -1502002290);
b = ff(b, c, d, a, k[15], 22, 1236535329);

a = gg(a, b, c, d, k[1], 5, -165796510);
d = gg(d, a, b, c, k[6], 9, -1069501632);
c = gg(c, d, a, b, k[11], 14, 643717713);
b = gg(b, c, d, a, k[0], 20, -373897302);
a = gg(a, b, c, d, k[5], 5, -701558691);
d = gg(d, a, b, c, k[10], 9, 38016083);
c = gg(c, d, a, b, k[15], 14, -660478335);
b = gg(b, c, d, a, k[4], 20, -405537848);
a = gg(a, b, c, d, k[9], 5, 568446438);
d = gg(d, a, b, c, k[14], 9, -1019803690);
c = gg(c, d, a, b, k[3], 14, -187363961);
b = gg(b, c, d, a, k[8], 20, 1163531501);
a = gg(a, b, c, d, k[13], 5, -1444681467);
d = gg(d, a, b, c, k[2], 9, -51403784);
c = gg(c, d, a, b, k[7], 14, 1735328473);
b = gg(b, c, d, a, k[12], 20, -1926607734);

a = hh(a, b, c, d, k[5], 4, -378558);
d = hh(d, a, b, c, k[8], 11, -2022574463);
c = hh(c, d, a, b, k[11], 16, 1839030562);
b = hh(b, c, d, a, k[14], 23, -35309556);
a = hh(a, b, c, d, k[1], 4, -1530992060);
d = hh(d, a, b, c, k[4], 11, 1272893353);
c = hh(c, d, a, b, k[7], 16, -155497632);
b = hh(b, c, d, a, k[10], 23, -1094730640);
a = hh(a, b, c, d, k[13], 4, 681279174);
d = hh(d, a, b, c, k[0], 11, -358537222);
c = hh(c, d, a, b, k[3], 16, -722521979);
b = hh(b, c, d, a, k[6], 23, 76029189);
a = hh(a, b, c, d, k[9], 4, -640364487);
d = hh(d, a, b, c, k[12], 11, -421815835);
c = hh(c, d, a, b, k[15], 16, 530742520);
b = hh(b, c, d, a, k[2], 23, -995338651);

a = ii(a, b, c, d, k[0], 6, -198630844);
d = ii(d, a, b, c, k[7], 10, 1126891415);
c = ii(c, d, a, b, k[14], 15, -1416354905);
b = ii(b, c, d, a, k[5], 21, -57434055);
a = ii(a, b, c, d, k[12], 6, 1700485571);
d = ii(d, a, b, c, k[3], 10, -1894986606);
c = ii(c, d, a, b, k[10], 15, -1051523);
b = ii(b, c, d, a, k[1], 21, -2054922799);
a = ii(a, b, c, d, k[8], 6, 1873313359);
d = ii(d, a, b, c, k[15], 10, -30611744);
c = ii(c, d, a, b, k[6], 15, -1560198380);
b = ii(b, c, d, a, k[13], 21, 1309151649);
a = ii(a, b, c, d, k[4], 6, -145523070);
d = ii(d, a, b, c, k[11], 10, -1120210379);
c = ii(c, d, a, b, k[2], 15, 718787259);
b = ii(b, c, d, a, k[9], 21, -343485551);

x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);
}


function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t));
return add32((a << s) | (a >>> (32 - s)), b);
}


function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}


function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}


function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
}


function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}


function md51(s) {
var txt = '',
n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i;

for (i = 64; i <= s.length; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < s.length; i++) {
tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i++) {
tail[i] = 0;
}
}
tail[14] = n * 8;
md5cycle(state, tail);

return state;
}

/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
* by adding every four 16-bit characters and
* shortening the sum to 32 bits). Otherwise
* I suggest performing MD-5 as if every character
* was two bytes--e.g., 0040 0025 = @%--but then
* how will an ordinary MD-5 sum be matched?
* There is no way to standardize text to something
* like UTF-8 before transformation; speed cost is
* utterly prohibitive. The JavaScript standard
* itself needs to look at this: it should start
* providing access to strings as preformed UTF-8
* 8-bit unsigned value arrays.
*/
function md5blk(s) { /* I figured global was faster. */
var md5blks = [],
i; /* Andy King said do it this way. */

for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
}

return md5blks;
}


function rhex(n) {
var s = '',
j = 0;

for (; j < 4; j++) {
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
}

return s;
}


function hex(x) {
for (var i = 0; i < x.length; i++) {
x[i] = rhex(x[i]);
}

return x.join('');
}


/* the standard function is much faster, so if possible, use it. */
function add32(a, b) {
return (use_alternate_add32 ? alternate : standard)();

function standard() {
return (a + b) & 0xFFFFFFFF;
}

function alternate() {
var lsw = (a & 0xFFFF) + (b & 0xFFFF),
msw = (a >> 16) + (b >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
}
})(window);
13 changes: 13 additions & 0 deletions src/partials/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,16 @@ <h3 class="page-heading">IRONdb Details</h3>
</gf-form-switch>
</div>
</div>

<h3 class="page-heading">Options</h3>

<div class="gf-form-group">
<div class="gf-form-inline">
<gf-form-switch class="gf-form"
label-class="width-13" switch-class="width-5"
label="Disable Usage Statistics" checked="ctrl.current.jsonData.disableUsageStatistics"
tooltip="By default, Circonus collects anonymized usage statistics to help prioritize our development efforts.">
</gf-form-switch>
</div>

</div>
4 changes: 2 additions & 2 deletions src/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
{ "name": "Project site", "url": "https://www.circonus.com/irondb/" },
{ "name": "License", "url": "https://github.com/circonus-labs/circonusllhist/blob/master/LICENSE" }
],
"version": "0.9.26",
"updated": "2023-01-13"
"version": "0.9.27",
"updated": "2023-01-16"
},

"dependencies": {
Expand Down

0 comments on commit 3a35082

Please sign in to comment.