diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 367010b..4e65133 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,8 @@ jobs: - name: Check types run: yarn run typecheck + - name: Check formatting + run: yarn run format:check - name: Lint run: yarn run lint - name: Unit tests diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..dc24fe6 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Ignore artifacts +dist + +# Ignore files created by `@grafana/create-plugin` +.config diff --git a/CHANGELOG.md b/CHANGELOG.md index 4486992..77dc870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Development +### Fix + +- different query start times with multiple queries due to mutating of grafana start time + +### Added + +- Default Percentile Value when percentile metric is selected + ## 1.1.1 ### Added diff --git a/README.md b/README.md index 6a61167..84b6c01 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Add the plugin and acquire your Bitmovin Analytics API key from the [bitmovin da Configure the datasource: | Setting | Value | -|--------------|----------------------------------------------------------| +| ------------ | -------------------------------------------------------- | | URL | `https://api.bitmovin.com/v1` | | API Key | Your API key | | Ad Analytics | If checked, the datasource is switched to query ads data | @@ -27,18 +27,18 @@ See the [example_dashboard.json](example_dashboard.json) for a demo. Configure t Add a new panel and select the bitmovin analytics datasource. Configure the metric with following settings: -| Setting | Description | -|------------------------|------------------------------------------------------------------------------------------| -| License* | Your analytics license | -| Metric* | Aggregation method to use, e.g. `count`, `sum` | -| Dimension* | Dimension to aggregate over | -| Filter | Apply filters to the query | -| Format as time series* | Check the switch to see time series data | -| Group By | Group query by dimension and plot as individual time series | -| Order By | Order query ascending or descending by dimension | -| Limit | Limit the result to given number | -| Interval* | Time granularity of queries, select `AUTO` to automatically adapt to selected time range | -| Alias By | Set the name of series (only visible with multiple queries in one Graph) | +| Setting | Description | +| ----------------------- | ---------------------------------------------------------------------------------------- | +| License\* | Your analytics license | +| Metric\* | Aggregation method to use, e.g. `count`, `sum` | +| Dimension\* | Dimension to aggregate over | +| Filter | Apply filters to the query | +| Format as time series\* | Check the switch to see time series data | +| Group By | Group query by dimension and plot as individual time series | +| Order By | Order query ascending or descending by dimension | +| Limit | Limit the result to given number | +| Interval\* | Time granularity of queries, select `AUTO` to automatically adapt to selected time range | +| Alias By | Set the name of series (only visible with multiple queries in one Graph) | Settings marked with `*` are required for the time series graph. @@ -52,7 +52,7 @@ Configure the metric as described in [Time Series Graph](#time-series-graph) but ## Gauges -Configure the Gauge's `Value Options`, depending on your query. +Configure the Gauge's `Value Options`, depending on your query. - For table data (`Format as time series` option **unchecked**) for the `Show` option select `All Values`. - For time series data (`Format as time series` option **checked**) for the `Show` option select `Calculate` and choose a reducer function. @@ -61,7 +61,7 @@ Configure the Gauge's `Value Options`, depending on your query. Please refer to our [Documentation](https://developer.bitmovin.com/playback/docs/integrating-bitmovin-analytics-with-grafana) and [Analytics Api Reference](https://developer.bitmovin.com/playback/reference/overview) for more information or reach out to us at [bitmovin.com](https://bitmovin.com/contact-bitmovin/). ------ +--- ## Development diff --git a/example_dashboard.json b/example_dashboard.json index e06ddec..fc14ed2 100644 --- a/example_dashboard.json +++ b/example_dashboard.json @@ -621,9 +621,7 @@ "value": "0" } ], - "groupBy": [ - "BROWSER" - ], + "groupBy": ["BROWSER"], "interval": "AUTO", "license": "", "metric": "count", @@ -723,9 +721,7 @@ "value": "0" } ], - "groupBy": [ - "COUNTRY" - ], + "groupBy": ["COUNTRY"], "interval": "AUTO", "license": "", "metric": "count", @@ -781,9 +777,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -800,9 +794,7 @@ "value": "0" } ], - "groupBy": [ - "PLAYER_TECH" - ], + "groupBy": ["PLAYER_TECH"], "interval": "AUTO", "license": "", "metric": "count", @@ -863,9 +855,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -882,9 +872,7 @@ "value": "0" } ], - "groupBy": [ - "OPERATINGSYSTEM" - ], + "groupBy": ["OPERATINGSYSTEM"], "interval": "AUTO", "license": "", "limit": 10, @@ -946,9 +934,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -959,9 +945,7 @@ "datasource": {}, "dimension": "IMPRESSION_ID", "filter": [], - "groupBy": [ - "BROWSER" - ], + "groupBy": ["BROWSER"], "interval": "AUTO", "license": "", "limit": 10, @@ -1023,9 +1007,7 @@ "footer": { "countRows": false, "fields": "", - "reducer": [ - "sum" - ], + "reducer": ["sum"], "show": false }, "showHeader": true @@ -1036,9 +1018,7 @@ "datasource": {}, "dimension": "IMPRESSION_ID", "filter": [], - "groupBy": [ - "COUNTRY" - ], + "groupBy": ["COUNTRY"], "interval": "AUTO", "license": "", "limit": 10, diff --git a/package.json b/package.json index 367f9d2..6126762 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "typecheck": "tsc --noEmit", "lint": "eslint --cache --ignore-pattern 'dist/**' --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx .", "lint:fix": "yarn run lint --fix", + "format": "yarn prettier . --write", + "format:check": "yarn prettier --check .", "e2e": "yarn playwright test", "server": "docker-compose up --build", "sign": "npx --yes @grafana/sign-plugin@latest" diff --git a/src/README.md b/src/README.md index 7cbe264..55009f2 100644 --- a/src/README.md +++ b/src/README.md @@ -11,7 +11,7 @@ Add the plugin and acquire your Bitmovin Analytics API key from the [bitmovin da Configure the datasource: | Setting | Value | -|--------------|----------------------------------------------------------| +| ------------ | -------------------------------------------------------- | | URL | `https://api.bitmovin.com/v1` | | API Key | Your API key | | Ad Analytics | If checked, the datasource is switched to query ads data | @@ -27,18 +27,18 @@ See the [example_dashboard.json](example_dashboard.json) for a demo. Configure t Add a new panel and select the bitmovin analytics datasource. Configure the metric with following settings: -| Setting | Description | -|------------------------|------------------------------------------------------------------------------------------| -| License* | Your analytics license | -| Metric* | Aggregation method to use, e.g. `count`, `sum` | -| Dimension* | Dimension to aggregate over | -| Filter | Apply filters to the query | -| Format as time series* | Check the switch to see time series data | -| Group By | Group query by dimension and plot as individual time series | -| Order By | Order query ascending or descending by dimension | -| Limit | Limit the result to given number | -| Interval* | Time granularity of queries, select `AUTO` to automatically adapt to selected time range | -| Alias By | Set the name of series (only visible with multiple queries in one Graph) | +| Setting | Description | +| ----------------------- | ---------------------------------------------------------------------------------------- | +| License\* | Your analytics license | +| Metric\* | Aggregation method to use, e.g. `count`, `sum` | +| Dimension\* | Dimension to aggregate over | +| Filter | Apply filters to the query | +| Format as time series\* | Check the switch to see time series data | +| Group By | Group query by dimension and plot as individual time series | +| Order By | Order query ascending or descending by dimension | +| Limit | Limit the result to given number | +| Interval\* | Time granularity of queries, select `AUTO` to automatically adapt to selected time range | +| Alias By | Set the name of series (only visible with multiple queries in one Graph) | Settings marked with `*` are required for the time series graph. @@ -52,7 +52,7 @@ Configure the metric as described in [Time Series Graph](#time-series-graph) but ## Gauges -Configure the Gauge's `Value Options`, depending on your query. +Configure the Gauge's `Value Options`, depending on your query. - For table data (`Format as time series` option **unchecked**) for the `Show` option select `All Values`. - For time series data (`Format as time series` option **checked**) for the `Show` option select `Calculate` and choose a reducer function. diff --git a/src/components/QueryEditor.tsx b/src/components/QueryEditor.tsx index 2a9715d..d35ebeb 100644 --- a/src/components/QueryEditor.tsx +++ b/src/components/QueryEditor.tsx @@ -69,7 +69,17 @@ export function QueryEditor(props: Props) { }; const handleAggregationChange = (item: SelectableValue) => { - props.onChange({ ...query, metric: item.value }); + // set a default value when percentile is selected and delete percentileValue when percentile is deselected + // to not pollute the dashboard.json file + let percentile = undefined; + if (item.value === 'percentile' && percentileValue == null) { + setPercentileValue(95); + percentile = 95; + } else { + setPercentileValue(undefined); + } + + props.onChange({ ...query, metric: item.value, percentileValue: percentile }); props.onRunQuery(); }; diff --git a/src/datasource.ts b/src/datasource.ts index 6cc15d3..c953815 100644 --- a/src/datasource.ts +++ b/src/datasource.ts @@ -11,6 +11,8 @@ import { } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; import { filter, isEmpty } from 'lodash'; +// eslint-disable-next-line no-restricted-imports +import moment from 'moment'; import { catchError, lastValueFrom, map, Observable, of } from 'rxjs'; import { @@ -88,6 +90,7 @@ export class DataSource extends DataSourceApi< async query(options: DataQueryRequest): Promise { const { range } = options; const isRelativeRangeFrom = this.isRelativeRangeFrom(range.raw); + let momentTimeUnit = undefined; //filter disabled queries const enabledQueries = (options.targets = filter(options.targets, (t) => !t.hide)); @@ -101,7 +104,9 @@ export class DataSource extends DataSourceApi< ? calculateQueryInterval(target.interval, range!.from.valueOf(), range!.to.valueOf()) : undefined; - let queryFrom = range!.from; + // create new moment object to not mutate the original grafana object with startOf() to not change + // the grafana graph at this point as this would change the timeframe for all the following queries + let queryFrom = moment(range!.from.valueOf()); const queryTo = range!.to; // floor the query start time to improve cache hitting @@ -111,11 +116,9 @@ export class DataSource extends DataSourceApi< // to allow higher granularity if interval is selected by user flooringInterval = getSmallerInterval(interval, flooringInterval); } - const momentTimeUnit = getMomentTimeUnitForQueryInterval(flooringInterval); + momentTimeUnit = getMomentTimeUnitForQueryInterval(flooringInterval); if (momentTimeUnit != null) { - // range from is a moment and startOf is mutating moment object so this has a side effect to also change the - // grafana selected timeframe value which will adapt the grafana graph as well - queryFrom = range!.from.startOf(momentTimeUnit); + queryFrom.startOf(momentTimeUnit); } } @@ -203,6 +206,11 @@ export class DataSource extends DataSourceApi< }); }); + // round down grafana start time to adjust the grafana graph and show first data point + if (momentTimeUnit != null) { + range.from.startOf(momentTimeUnit); + } + return Promise.all(promises).then((data) => ({ data })); } diff --git a/src/plugin.json b/src/plugin.json index a7be010..cba2910 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -16,8 +16,14 @@ "large": "img/logo.svg" }, "links": [ - {"name": "Project site", "url": "https://github.com/bitmovin/analytics-grafana-datasource"}, - {"name": "Apache License", "url": "https://github.com/bitmovin/analytics-grafana-datasource/blob/main/LICENSE"} + { + "name": "Project site", + "url": "https://github.com/bitmovin/analytics-grafana-datasource" + }, + { + "name": "Apache License", + "url": "https://github.com/bitmovin/analytics-grafana-datasource/blob/main/LICENSE" + } ], "screenshots": [], "version": "%VERSION%",