mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into develop
This commit is contained in:
commit
fff0fa2aee
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,6 +12,8 @@ awsconfig
|
||||
/tmp
|
||||
vendor/phantomjs/phantomjs
|
||||
vendor/phantomjs/phantomjs.exe
|
||||
profile.out
|
||||
coverage.txt
|
||||
|
||||
docs/AWS_S3_BUCKET
|
||||
docs/GIT_BRANCH
|
||||
|
19
CHANGELOG.md
19
CHANGELOG.md
@ -7,6 +7,21 @@
|
||||
- UX changes to nav & side menu
|
||||
- New dashboard grid layout system
|
||||
|
||||
# 4.7.0 (unreleased)
|
||||
|
||||
## New Features
|
||||
* **Data Source Proxy**: Add support for whitelisting specified cookies that will be passed through to the data source when proxying data source requests [#5457](https://github.com/grafana/grafana/issues/5457), thanks [@robingustafsson](https://github.com/robingustafsson)
|
||||
|
||||
* **Postgres**: modify group by time macro so it can be used in select clause [#9527](https://github.com/grafana/grafana/pull/9527), thanks [@svenklemm](https://github.com/svenklemm)
|
||||
|
||||
## Fixes
|
||||
* **Sensu**: Send alert message to sensu output [#9551](https://github.com/grafana/grafana/issues/9551), thx [@cjchand](https://github.com/cjchand)
|
||||
|
||||
# 4.6.0-beta3 (unreleased)
|
||||
* **Prometheus**: Fix for browser crash for short time ranges. [#9575](https://github.com/grafana/grafana/issues/9575)
|
||||
* **Heatmap**: Fix for y-axis not showing. [#9576](https://github.com/grafana/grafana/issues/9576)
|
||||
* **Save to file**: Fix for save to file in export modal. [#9586](https://github.com/grafana/grafana/issues/9586)
|
||||
|
||||
# 4.6.0-beta2 (2017-10-17)
|
||||
|
||||
## Fixes
|
||||
@ -15,7 +30,9 @@
|
||||
* **Cloudwatch**: Provide error message when failing to add cloudwatch datasource [#9534](https://github.com/grafana/grafana/pull/9534), thx [@mtanda](https://github.com/mtanda)
|
||||
* **Cloudwatch**: Fix unused period parameter [#9536](https://github.com/grafana/grafana/pull/9536), thx [@mtanda](https://github.com/mtanda)
|
||||
* **CSV Export**: Fix for broken CSV export [#9525](https://github.com/grafana/grafana/issues/9525)
|
||||
* **Text panel**: Fixes issue with break lines in Firefox [#9491](https://github.com/grafana/grafana/issues/9491)
|
||||
* **Text panel**: Fix for issue with break lines in Firefox [#9491](https://github.com/grafana/grafana/issues/9491)
|
||||
* **Annotations**: Fix for issue saving annotation event in MySQL DB [#9550](https://github.com/grafana/grafana/issues/9550), thanks [@krise3k](https://github.com/krise3k)
|
||||
|
||||
|
||||
# 4.6.0-beta1 (2017-10-13)
|
||||
|
||||
|
@ -22,9 +22,10 @@ module.exports = function (grunt) {
|
||||
}
|
||||
}
|
||||
|
||||
config.coverage = grunt.option('coverage');
|
||||
config.phjs = grunt.option('phjsToRelease');
|
||||
|
||||
config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
|
||||
|
||||
console.log('Version', config.pkg.version);
|
||||
|
||||
// load plugins
|
||||
|
16
README.md
16
README.md
@ -1,4 +1,4 @@
|
||||
[Grafana](https://grafana.com) [](https://circleci.com/gh/grafana/grafana) [](https://goreportcard.com/report/github.com/grafana/grafana)
|
||||
[Grafana](https://grafana.com) [](https://circleci.com/gh/grafana/grafana) [](https://goreportcard.com/report/github.com/grafana/grafana) [](https://codecov.io/gh/grafana/grafana)
|
||||
================
|
||||
[Website](https://grafana.com) |
|
||||
[Twitter](https://twitter.com/grafana) |
|
||||
@ -81,6 +81,20 @@ You only need to add the options you want to override. Config files are applied
|
||||
|
||||
In your custom.ini uncomment (remove the leading `;`) sign. And set `app_mode = development`.
|
||||
|
||||
### Running tests
|
||||
|
||||
- You can run backend Golang tests using "go test ./pkg/...".
|
||||
- Execute all frontend tests with "npm run test"
|
||||
|
||||
Writing & watching frontend tests (we have two test runners)
|
||||
|
||||
- jest for all new tests that do not require browser context (React+more)
|
||||
- Start watcher: `npm run jest`
|
||||
- Jest will run all test files that end with the name ".jest.ts"
|
||||
- karma + mocha is used for testing angularjs components. We do want to migrate these test to jest over time (if possible).
|
||||
- Start watcher: `npm run karma`
|
||||
- Karma+Mocha runs all files that end with the name "_specs.ts".
|
||||
|
||||
## Contribute
|
||||
|
||||
If you have any idea for an improvement or found a bug do not hesitate to open an issue.
|
||||
|
@ -48,7 +48,7 @@ Macro example | Description
|
||||
*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn > to_timestamp(1494410783) AND dateColumn < to_timestamp(1494497183)*
|
||||
*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *to_timestamp(1494410783)*
|
||||
*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *to_timestamp(1494497183)*
|
||||
*$__timeGroup(dateColumn,'5m')* | Will be replaced by an expression usable in GROUP BY clause. For example, *(extract(epoch from "dateColumn")/extract(epoch from '5m'::interval))::int*
|
||||
*$__timeGroup(dateColumn,'5m')* | Will be replaced by an expression usable in GROUP BY clause. For example, *(extract(epoch from "dateColumn")/extract(epoch from '5m'::interval))::int*extract(epoch from '5m'::interval)*
|
||||
*$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
|
||||
*$__unixEpochFrom()* | Will be replaced by the start of the currently active time selection as unix timestamp. For example, *1494410783*
|
||||
*$__unixEpochTo()* | Will be replaced by the end of the currently active time selection as unix timestamp. For example, *1494497183*
|
||||
@ -94,26 +94,26 @@ Example with `metric` column
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
min(time_date_time) as time,
|
||||
$__timeGroup(time_date_time,'5m') as time,
|
||||
min(value_double),
|
||||
'min' as metric
|
||||
FROM test_data
|
||||
WHERE $__timeFilter(time_date_time)
|
||||
GROUP BY metric1, (extract(epoch from time_date_time)/extract(epoch from $__interval::interval))::int
|
||||
ORDER BY time asc
|
||||
GROUP BY time
|
||||
ORDER BY time
|
||||
```
|
||||
|
||||
Example with multiple columns:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
min(time_date_time) as time,
|
||||
$__timeGroup(time_date_time,'5m') as time,
|
||||
min(value_double) as min_value,
|
||||
max(value_double) as max_value
|
||||
FROM test_data
|
||||
WHERE $__timeFilter(time_date_time)
|
||||
GROUP BY metric1, (extract(epoch from time_date_time)/extract(epoch from $__interval::interval))::int
|
||||
ORDER BY time asc
|
||||
GROUP BY time
|
||||
ORDER BY time
|
||||
```
|
||||
|
||||
## Templating
|
||||
|
@ -120,6 +120,37 @@ Content-Type: application/json
|
||||
{"message":"Annotation added"}
|
||||
```
|
||||
|
||||
## Create Annotation in Graphite format
|
||||
|
||||
Creates an annotation by using Graphite-compatible event format. The `when` and `data` fields are optional. If `when` is not specified then the current time will be used as annotation's timestamp. The `tags` field can also be in prior to Graphite `0.10.0`
|
||||
format (string with multiple tags being separated by a space).
|
||||
|
||||
`POST /api/annotations/graphite`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```json
|
||||
POST /api/annotations/graphite HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"what": "Event - deploy",
|
||||
"tags": ["deploy", "production"],
|
||||
"when": 1467844481,
|
||||
"data": "deploy of master branch happened at Wed Jul 6 22:34:41 UTC 2016"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```json
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
{"message":"Graphite annotation added"}
|
||||
```
|
||||
|
||||
## Update Annotation
|
||||
|
||||
`PUT /api/annotations/:id`
|
||||
|
@ -84,6 +84,20 @@ bra run
|
||||
|
||||
You'll also need to run `npm run watch` to watch for changes to the front-end (typescript, html, sass)
|
||||
|
||||
### Running tests
|
||||
|
||||
- You can run backend Golang tests using "go test ./pkg/...".
|
||||
- Execute all frontend tests with "npm run test"
|
||||
|
||||
Writing & watching frontend tests (we have two test runners)
|
||||
|
||||
- jest for all new tests that do not require browser context (React+more)
|
||||
- Start watcher: `npm run jest`
|
||||
- Jest will run all test files that end with the name ".jest.ts"
|
||||
- karma + mocha is used for testing angularjs components. We do want to migrate these test to jest over time (if possible).
|
||||
- Start watcher: `npm run karma`
|
||||
- Karma+Mocha runs all files that end with the name "_specs.ts".
|
||||
|
||||
## Creating optimized release packages
|
||||
|
||||
This step builds linux packages and requires that fpm is installed. Install fpm via `gem install fpm`.
|
||||
|
23
jest.config.js
Normal file
23
jest.config.js
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
module.exports = {
|
||||
verbose: false,
|
||||
"transform": {
|
||||
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
|
||||
},
|
||||
"moduleDirectories": ["<rootDir>node_modules", "<rootDir>/public"],
|
||||
"roots": [
|
||||
"<rootDir>/public"
|
||||
],
|
||||
"testRegex": "(\\.|/)(jest)\\.(jsx?|tsx?)$",
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"json"
|
||||
],
|
||||
"setupFiles": [
|
||||
"./public/test/jest-shim.ts",
|
||||
"./public/test/jest-setup.ts"
|
||||
]
|
||||
};
|
12
package.json
12
package.json
@ -12,6 +12,7 @@
|
||||
"devDependencies": {
|
||||
"@types/d3": "^4.10.1",
|
||||
"@types/enzyme": "^2.8.9",
|
||||
"@types/jest": "^21.1.4",
|
||||
"@types/node": "^8.0.31",
|
||||
"@types/react": "^16.0.5",
|
||||
"@types/react-dom": "^15.5.4",
|
||||
@ -22,8 +23,8 @@
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"enzyme": "^3.0.0",
|
||||
"enzyme-adapter-react-16": "^1.0.0",
|
||||
"enzyme": "^3.1.0",
|
||||
"enzyme-adapter-react-16": "^1.0.1",
|
||||
"es6-promise": "^3.0.2",
|
||||
"es6-shim": "^0.35.3",
|
||||
"expect.js": "~0.2.0",
|
||||
@ -53,11 +54,11 @@
|
||||
"html-loader": "^0.5.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"husky": "^0.14.3",
|
||||
"jest": "^21.2.1",
|
||||
"jshint-stylish": "~2.2.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"karma": "1.7.0",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage": "1.1.1",
|
||||
"karma-expect": "~1.1.3",
|
||||
"karma-mocha": "~1.3.0",
|
||||
"karma-phantomjs-launcher": "1.0.4",
|
||||
@ -82,6 +83,7 @@
|
||||
"sinon": "1.17.6",
|
||||
"systemjs": "0.20.19",
|
||||
"systemjs-plugin-css": "^0.1.36",
|
||||
"ts-jest": "^21.1.3",
|
||||
"ts-loader": "^2.3.7",
|
||||
"tslint": "^5.7.0",
|
||||
"tslint-loader": "^3.5.3",
|
||||
@ -97,8 +99,10 @@
|
||||
"watch": "./node_modules/.bin/webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
|
||||
"build": "./node_modules/.bin/grunt build",
|
||||
"test": "./node_modules/.bin/grunt test",
|
||||
"test-ci": "./node_modules/.bin/grunt test --coverage=true",
|
||||
"lint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --type-check",
|
||||
"watch-test": "./node_modules/grunt-cli/bin/grunt karma:dev"
|
||||
"karma": "./node_modules/grunt-cli/bin/grunt karma:dev",
|
||||
"jest": "./node_modules/jest-cli/bin/jest --notify --watch"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
@ -91,7 +91,7 @@ case "$1" in
|
||||
then
|
||||
sleep 1
|
||||
|
||||
# check if pid file has been written two
|
||||
# check if pid file has been written to
|
||||
if ! [[ -s $PID_FILE ]]; then
|
||||
log_end_msg 1
|
||||
exit 1
|
||||
|
@ -96,7 +96,7 @@ case "$1" in
|
||||
if [ $return -eq 0 ]
|
||||
then
|
||||
sleep 1
|
||||
# check if pid file has been written two
|
||||
# check if pid file has been written to
|
||||
if ! [[ -s $PID_FILE ]]; then
|
||||
echo "FAILED"
|
||||
exit 1
|
||||
|
@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -41,9 +40,22 @@ func GetAnnotations(c *middleware.Context) Response {
|
||||
return Json(200, items)
|
||||
}
|
||||
|
||||
type CreateAnnotationError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (e *CreateAnnotationError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response {
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if cmd.Text == "" {
|
||||
err := &CreateAnnotationError{"text field should not be empty"}
|
||||
return ApiError(500, "Failed to save annotation", err)
|
||||
}
|
||||
|
||||
item := annotations.Item{
|
||||
OrgId: c.OrgId,
|
||||
UserId: c.UserId,
|
||||
@ -55,6 +67,10 @@ func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response
|
||||
Tags: cmd.Tags,
|
||||
}
|
||||
|
||||
if item.Epoch == 0 {
|
||||
item.Epoch = time.Now().Unix()
|
||||
}
|
||||
|
||||
if err := repo.Save(&item); err != nil {
|
||||
return ApiError(500, "Failed to save annotation", err)
|
||||
}
|
||||
@ -82,21 +98,22 @@ func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response
|
||||
return ApiSuccess("Annotation added")
|
||||
}
|
||||
|
||||
type GraphiteAnnotationError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (e *GraphiteAnnotationError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func formatGraphiteAnnotation(what string, data string) string {
|
||||
return fmt.Sprintf("%s\n%s", what, data)
|
||||
text := what
|
||||
if data != "" {
|
||||
text = text + "\n" + data
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
func PostGraphiteAnnotation(c *middleware.Context, cmd dtos.PostGraphiteAnnotationsCmd) Response {
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if cmd.What == "" {
|
||||
err := &CreateAnnotationError{"what field should not be empty"}
|
||||
return ApiError(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
if cmd.When == 0 {
|
||||
cmd.When = time.Now().Unix()
|
||||
}
|
||||
@ -106,18 +123,22 @@ func PostGraphiteAnnotation(c *middleware.Context, cmd dtos.PostGraphiteAnnotati
|
||||
var tagsArray []string
|
||||
switch tags := cmd.Tags.(type) {
|
||||
case string:
|
||||
if tags != "" {
|
||||
tagsArray = strings.Split(tags, " ")
|
||||
} else {
|
||||
tagsArray = []string{}
|
||||
}
|
||||
case []interface{}:
|
||||
for _, t := range tags {
|
||||
if tagStr, ok := t.(string); ok {
|
||||
tagsArray = append(tagsArray, tagStr)
|
||||
} else {
|
||||
err := &GraphiteAnnotationError{"tag should be a string"}
|
||||
err := &CreateAnnotationError{"tag should be a string"}
|
||||
return ApiError(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
err := &GraphiteAnnotationError{"unsupported tags format"}
|
||||
err := &CreateAnnotationError{"unsupported tags format"}
|
||||
return ApiError(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
@ -133,7 +154,7 @@ func PostGraphiteAnnotation(c *middleware.Context, cmd dtos.PostGraphiteAnnotati
|
||||
return ApiError(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
return ApiSuccess("Graphite Annotation added")
|
||||
return ApiSuccess("Graphite annotation added")
|
||||
}
|
||||
|
||||
func UpdateAnnotation(c *middleware.Context, cmd dtos.UpdateAnnotationsCmd) Response {
|
||||
|
@ -18,6 +18,7 @@ const (
|
||||
DS_KAIROSDB = "kairosdb"
|
||||
DS_PROMETHEUS = "prometheus"
|
||||
DS_POSTGRES = "postgres"
|
||||
DS_MYSQL = "mysql"
|
||||
DS_ACCESS_DIRECT = "direct"
|
||||
DS_ACCESS_PROXY = "proxy"
|
||||
)
|
||||
@ -64,6 +65,7 @@ var knownDatasourcePlugins map[string]bool = map[string]bool{
|
||||
DS_PROMETHEUS: true,
|
||||
DS_OPENTSDB: true,
|
||||
DS_POSTGRES: true,
|
||||
DS_MYSQL: true,
|
||||
"opennms": true,
|
||||
"druid": true,
|
||||
"dalmatinerdb": true,
|
||||
|
@ -112,7 +112,7 @@ func (this *SensuNotifier) Notify(evalContext *alerting.EvalContext) error {
|
||||
}
|
||||
|
||||
if evalContext.Rule.Message != "" {
|
||||
bodyJSON.Set("message", evalContext.Rule.Message)
|
||||
bodyJSON.Set("output", evalContext.Rule.Message)
|
||||
}
|
||||
|
||||
body, _ := bodyJSON.MarshalJSON()
|
||||
|
@ -74,7 +74,7 @@ func (m *PostgresMacroEngine) evaluateMacro(name string, args []string) (string,
|
||||
if len(args) == 0 {
|
||||
return "", fmt.Errorf("missing time column argument for macro %v", name)
|
||||
}
|
||||
return fmt.Sprintf("%s >= to_timestamp(%d) AND %s <= to_timestamp(%d)", args[0], uint64(m.TimeRange.GetFromAsMsEpoch()/1000), args[0], uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
|
||||
return fmt.Sprintf("extract(epoch from %s) BETWEEN %d AND %d", args[0], uint64(m.TimeRange.GetFromAsMsEpoch()/1000), uint64(m.TimeRange.GetToAsMsEpoch()/1000)), nil
|
||||
case "__timeFrom":
|
||||
return fmt.Sprintf("to_timestamp(%d)", uint64(m.TimeRange.GetFromAsMsEpoch()/1000)), nil
|
||||
case "__timeTo":
|
||||
@ -83,7 +83,7 @@ func (m *PostgresMacroEngine) evaluateMacro(name string, args []string) (string,
|
||||
if len(args) < 2 {
|
||||
return "", fmt.Errorf("macro %v needs time column and interval", name)
|
||||
}
|
||||
return fmt.Sprintf("(extract(epoch from \"%s\")/extract(epoch from %s::interval))::int", args[0], args[1]), nil
|
||||
return fmt.Sprintf("(extract(epoch from \"%s\")/extract(epoch from %s::interval))::int*extract(epoch from %s::interval)", args[0], args[1], args[1]), nil
|
||||
case "__unixEpochFilter":
|
||||
if len(args) == 0 {
|
||||
return "", fmt.Errorf("missing time column argument for macro %v", name)
|
||||
|
@ -30,7 +30,7 @@ func TestMacroEngine(t *testing.T) {
|
||||
sql, err := engine.Interpolate(timeRange, "WHERE $__timeFilter(time_column)")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(sql, ShouldEqual, "WHERE time_column >= to_timestamp(18446744066914186738) AND time_column <= to_timestamp(18446744066914187038)")
|
||||
So(sql, ShouldEqual, "WHERE extract(epoch from time_column) BETWEEN 18446744066914186738 AND 18446744066914187038")
|
||||
})
|
||||
|
||||
Convey("interpolate __timeFrom function", func() {
|
||||
@ -45,7 +45,7 @@ func TestMacroEngine(t *testing.T) {
|
||||
sql, err := engine.Interpolate(timeRange, "GROUP BY $__timeGroup(time_column,'5m')")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(sql, ShouldEqual, "GROUP BY (extract(epoch from \"time_column\")/extract(epoch from '5m'::interval))::int")
|
||||
So(sql, ShouldEqual, "GROUP BY (extract(epoch from \"time_column\")/extract(epoch from '5m'::interval))::int*extract(epoch from '5m'::interval)")
|
||||
})
|
||||
|
||||
Convey("interpolate __timeTo function", func() {
|
||||
|
8
public/app/core/angular_wrappers.ts
Normal file
8
public/app/core/angular_wrappers.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { react2AngularDirective } from 'app/core/utils/react2angular';
|
||||
import { PasswordStrength } from './ui/PasswordStrength';
|
||||
|
||||
export function registerAngularDirectives() {
|
||||
|
||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||
|
||||
}
|
@ -43,7 +43,6 @@ import {assignModelProperties} from './utils/model_utils';
|
||||
import {contextSrv} from './services/context_srv';
|
||||
import {KeybindingSrv} from './services/keybindingSrv';
|
||||
import {helpModal} from './components/help/help';
|
||||
import {PasswordStrength} from './components/PasswordStrength';
|
||||
import {JsonExplorer} from './components/json_explorer/json_explorer';
|
||||
import {NavModelSrv, NavModel} from './nav_model_srv';
|
||||
import {userPicker} from './components/user_picker';
|
||||
@ -52,6 +51,9 @@ import {geminiScrollbar} from './components/scroll/scroll';
|
||||
import {gfPageDirective} from './components/gf_page';
|
||||
import {orgSwitcher} from './components/org_switcher';
|
||||
import {profiler} from './profiler';
|
||||
import {registerAngularDirectives} from './angular_wrappers';
|
||||
|
||||
registerAngularDirectives();
|
||||
|
||||
export {
|
||||
profiler,
|
||||
@ -82,6 +84,5 @@ export {
|
||||
userGroupPicker,
|
||||
geminiScrollbar,
|
||||
gfPageDirective,
|
||||
orgSwitcher,
|
||||
PasswordStrength,
|
||||
orgSwitcher
|
||||
};
|
||||
|
@ -7,6 +7,8 @@ define([
|
||||
function (angular, require, coreModule, kbn) {
|
||||
'use strict';
|
||||
|
||||
kbn = kbn.default;
|
||||
|
||||
coreModule.default.directive('tip', function($compile) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
|
@ -1,9 +1,8 @@
|
||||
define([
|
||||
'../core_module',
|
||||
'app/core/utils/kbn',
|
||||
'app/core/utils/rangeutil',
|
||||
],
|
||||
function (coreModule, kbn, rangeUtil) {
|
||||
function (coreModule, rangeUtil) {
|
||||
'use strict';
|
||||
|
||||
coreModule.default.directive('ngModelOnblur', function() {
|
||||
|
@ -1,24 +1,23 @@
|
||||
import React from 'react';
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
import {shallow} from 'enzyme';
|
||||
|
||||
import {PasswordStrength} from '../components/PasswordStrength';
|
||||
import {PasswordStrength} from '../ui/PasswordStrength';
|
||||
|
||||
describe('PasswordStrength', () => {
|
||||
|
||||
it('should have class bad if length below 4', () => {
|
||||
const wrapper = shallow(<PasswordStrength password="asd" />);
|
||||
expect(wrapper.find(".password-strength-bad")).to.have.length(1);
|
||||
expect(wrapper.find(".password-strength-bad")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should have class ok if length below 8', () => {
|
||||
const wrapper = shallow(<PasswordStrength password="asdasd" />);
|
||||
expect(wrapper.find(".password-strength-ok")).to.have.length(1);
|
||||
expect(wrapper.find(".password-strength-ok")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should have class good if length above 8', () => {
|
||||
const wrapper = shallow(<PasswordStrength password="asdaasdda" />);
|
||||
expect(wrapper.find(".password-strength-good")).to.have.length(1);
|
||||
expect(wrapper.find(".password-strength-good")).toHaveLength(1);
|
||||
});
|
||||
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import {describe, beforeEach, afterEach, it, sinon, expect} from 'test/lib/common';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
import moment from 'moment';
|
||||
@ -13,25 +13,25 @@ describe("DateMath", () => {
|
||||
|
||||
describe('errors', () => {
|
||||
it('should return undefined if passed something falsy', () => {
|
||||
expect(dateMath.parse(false)).to.be(undefined);
|
||||
expect(dateMath.parse(false)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should return undefined if I pass an operator besides [+-/]', () => {
|
||||
expect(dateMath.parse('now&1d')).to.be(undefined);
|
||||
expect(dateMath.parse('now&1d')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should return undefined if I pass a unit besides' + spans.toString(), () => {
|
||||
expect(dateMath.parse('now+5f')).to.be(undefined);
|
||||
expect(dateMath.parse('now+5f')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should return undefined if rounding unit is not 1', () => {
|
||||
expect(dateMath.parse('now/2y')).to.be(undefined);
|
||||
expect(dateMath.parse('now/0.5y')).to.be(undefined);
|
||||
expect(dateMath.parse('now/2y')).toBe(undefined);
|
||||
expect(dateMath.parse('now/0.5y')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should not go into an infinite loop when missing a unit', () => {
|
||||
expect(dateMath.parse('now-0')).to.be(undefined);
|
||||
expect(dateMath.parse('now-00')).to.be(undefined);
|
||||
expect(dateMath.parse('now-0')).toBe(undefined);
|
||||
expect(dateMath.parse('now-00')).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@ -43,7 +43,7 @@ describe("DateMath", () => {
|
||||
expected.setMilliseconds(0);
|
||||
|
||||
var startOfDay = dateMath.parse('now/d', false).valueOf();
|
||||
expect(startOfDay).to.be(expected.getTime());
|
||||
expect(startOfDay).toBe(expected.getTime());
|
||||
});
|
||||
|
||||
it("now/d on a utc dashboard should be start of the current day in UTC time", () => {
|
||||
@ -51,7 +51,7 @@ describe("DateMath", () => {
|
||||
var expected = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0));
|
||||
|
||||
var startOfDay = dateMath.parse('now/d', false, 'utc').valueOf();
|
||||
expect(startOfDay).to.be(expected.getTime());
|
||||
expect(startOfDay).toBe(expected.getTime());
|
||||
});
|
||||
|
||||
describe('subtraction', () => {
|
||||
@ -69,11 +69,11 @@ describe("DateMath", () => {
|
||||
var thenEx = anchor + '||-5' + span;
|
||||
|
||||
it('should return 5' + span + ' ago', () => {
|
||||
expect(dateMath.parse(nowEx).format(format)).to.eql(now.subtract(5, span).format(format));
|
||||
expect(dateMath.parse(nowEx).format(format)).toEqual(now.subtract(5, span).format(format));
|
||||
});
|
||||
|
||||
it('should return 5' + span + ' before ' + anchor, () => {
|
||||
expect(dateMath.parse(thenEx).format(format)).to.eql(anchored.subtract(5, span).format(format));
|
||||
expect(dateMath.parse(thenEx).format(format)).toEqual(anchored.subtract(5, span).format(format));
|
||||
});
|
||||
});
|
||||
|
||||
@ -94,11 +94,11 @@ describe("DateMath", () => {
|
||||
|
||||
_.each(spans, (span) => {
|
||||
it('should round now to the beginning of the ' + span, function () {
|
||||
expect(dateMath.parse('now/' + span).format(format)).to.eql(now.startOf(span).format(format));
|
||||
expect(dateMath.parse('now/' + span).format(format)).toEqual(now.startOf(span).format(format));
|
||||
});
|
||||
|
||||
it('should round now to the end of the ' + span, function () {
|
||||
expect(dateMath.parse('now/' + span, true).format(format)).to.eql(now.endOf(span).format(format));
|
||||
expect(dateMath.parse('now/' + span, true).format(format)).toEqual(now.endOf(span).format(format));
|
||||
});
|
||||
});
|
||||
|
||||
@ -109,27 +109,27 @@ describe("DateMath", () => {
|
||||
|
||||
describe('isValid', () => {
|
||||
it('should return false when invalid date text', () => {
|
||||
expect(dateMath.isValid('asd')).to.be(false);
|
||||
expect(dateMath.isValid('asd')).toBe(false);
|
||||
});
|
||||
it('should return true when valid date text', () => {
|
||||
expect(dateMath.isValid('now-1h')).to.be(true);
|
||||
expect(dateMath.isValid('now-1h')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('relative time to date parsing', function() {
|
||||
it('should handle negative time', function() {
|
||||
var date = dateMath.parseDateMath('-2d', moment([2014, 1, 5]));
|
||||
expect(date.valueOf()).to.equal(moment([2014, 1, 3]).valueOf());
|
||||
expect(date.valueOf()).toEqual(moment([2014, 1, 3]).valueOf());
|
||||
});
|
||||
|
||||
it('should handle multiple math expressions', function() {
|
||||
var date = dateMath.parseDateMath('-2d-6h', moment([2014, 1, 5]));
|
||||
expect(date.valueOf()).to.equal(moment([2014, 1, 2, 18]).valueOf());
|
||||
expect(date.valueOf()).toEqual(moment([2014, 1, 2, 18]).valueOf());
|
||||
});
|
||||
|
||||
it('should return false when invalid expression', function() {
|
||||
var date = dateMath.parseDateMath('2', moment([2014, 1, 5]));
|
||||
expect(date).to.equal(undefined);
|
||||
expect(date).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,4 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import {Emitter} from 'app/core/core';
|
||||
import {Emitter} from '../utils/emitter';
|
||||
|
||||
describe("Emitter", () => {
|
||||
|
||||
@ -20,8 +18,8 @@ describe("Emitter", () => {
|
||||
|
||||
events.emit('test', null);
|
||||
|
||||
expect(sub1Called).to.be(true);
|
||||
expect(sub2Called).to.be(true);
|
||||
expect(sub1Called).toBe(true);
|
||||
expect(sub2Called).toBe(true);
|
||||
});
|
||||
|
||||
it('when subscribing twice', () => {
|
||||
@ -37,7 +35,7 @@ describe("Emitter", () => {
|
||||
|
||||
events.emit('test', null);
|
||||
|
||||
expect(sub1Called).to.be(2);
|
||||
expect(sub1Called).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle errors', () => {
|
||||
@ -57,8 +55,8 @@ describe("Emitter", () => {
|
||||
try { events.emit('test', null); } catch (_) { }
|
||||
try { events.emit('test', null); } catch (_) {}
|
||||
|
||||
expect(sub1Called).to.be(2);
|
||||
expect(sub2Called).to.be(0);
|
||||
expect(sub1Called).toBe(2);
|
||||
expect(sub2Called).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import flatten from 'app/core/utils/flatten';
|
||||
|
||||
describe("flatten", () => {
|
||||
@ -15,9 +13,9 @@ describe("flatten", () => {
|
||||
}
|
||||
}, null);
|
||||
|
||||
expect(flattened['level1']).to.be('level1-value');
|
||||
expect(flattened['deeper.level2']).to.be('level2-value');
|
||||
expect(flattened['deeper.deeper.level3']).to.be('level3-value');
|
||||
expect(flattened['level1']).toBe('level1-value');
|
||||
expect(flattened['deeper.level2']).toBe('level2-value');
|
||||
expect(flattened['deeper.deeper.level3']).toBe('level3-value');
|
||||
});
|
||||
|
||||
});
|
347
public/app/core/specs/kbn.jest.ts
Normal file
347
public/app/core/specs/kbn.jest.ts
Normal file
@ -0,0 +1,347 @@
|
||||
import kbn from '../utils/kbn';
|
||||
import * as dateMath from '../utils/datemath';
|
||||
import moment from 'moment';
|
||||
|
||||
describe('unit format menu', function() {
|
||||
var menu = kbn.getUnitFormats();
|
||||
menu.map(function(submenu) {
|
||||
|
||||
describe('submenu ' + submenu.text, function() {
|
||||
|
||||
it('should have a title', function() {
|
||||
expect(typeof submenu.text).toBe('string');
|
||||
});
|
||||
|
||||
it('should have a submenu', function() {
|
||||
expect(Array.isArray(submenu.submenu)).toBe(true);
|
||||
});
|
||||
|
||||
submenu.submenu.map(function(entry) {
|
||||
describe('entry ' + entry.text, function() {
|
||||
it('should have a title', function() { expect(typeof entry.text).toBe('string'); });
|
||||
it('should have a format', function() { expect(typeof entry.value).toBe('string'); });
|
||||
it('should have a valid format', function() {
|
||||
expect(typeof kbn.valueFormats[entry.value]).toBe('function');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function describeValueFormat(desc, value, tickSize, tickDecimals, result) {
|
||||
|
||||
describe('value format: ' + desc, function() {
|
||||
it('should translate ' + value + ' as ' + result, function() {
|
||||
var scaledDecimals = tickDecimals - Math.floor(Math.log(tickSize) / Math.LN10);
|
||||
var str = kbn.valueFormats[desc](value, tickDecimals, scaledDecimals);
|
||||
expect(str).toBe(result);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
describeValueFormat('ms', 0.0024, 0.0005, 4, '0.0024 ms');
|
||||
describeValueFormat('ms', 100, 1, 0, '100 ms');
|
||||
describeValueFormat('ms', 1250, 10, 0, '1.25 s');
|
||||
describeValueFormat('ms', 1250, 300, 0, '1.3 s');
|
||||
describeValueFormat('ms', 65150, 10000, 0, '1.1 min');
|
||||
describeValueFormat('ms', 6515000, 1500000, 0, '1.8 hour');
|
||||
describeValueFormat('ms', 651500000, 150000000, 0, '8 day');
|
||||
|
||||
describeValueFormat('none', 2.75e-10, 0, 10, '3e-10');
|
||||
describeValueFormat('none', 0, 0, 2, '0');
|
||||
describeValueFormat('dB', 10, 1000, 2, '10.00 dB');
|
||||
|
||||
describeValueFormat('percent', 0, 0, 0, '0%');
|
||||
describeValueFormat('percent', 53, 0, 1, '53.0%');
|
||||
describeValueFormat('percentunit', 0.0, 0, 0, '0%');
|
||||
describeValueFormat('percentunit', 0.278, 0, 1, '27.8%');
|
||||
describeValueFormat('percentunit', 1.0, 0, 0, '100%');
|
||||
|
||||
describeValueFormat('currencyUSD', 7.42, 10000, 2, '$7.42');
|
||||
describeValueFormat('currencyUSD', 1532.82, 1000, 1, '$1.53K');
|
||||
describeValueFormat('currencyUSD', 18520408.7, 10000000, 0, '$19M');
|
||||
|
||||
describeValueFormat('bytes', -1.57e+308, -1.57e+308, 2, 'NA');
|
||||
|
||||
describeValueFormat('ns', 25, 1, 0, '25 ns');
|
||||
describeValueFormat('ns', 2558, 50, 0, '2.56 µs');
|
||||
|
||||
describeValueFormat('ops', 123, 1, 0, '123 ops');
|
||||
describeValueFormat('rps', 456000, 1000, -1, '456K rps');
|
||||
describeValueFormat('rps', 123456789, 1000000, 2, '123.457M rps');
|
||||
describeValueFormat('wps', 789000000, 1000000, -1, '789M wps');
|
||||
describeValueFormat('iops', 11000000000, 1000000000, -1, '11B iops');
|
||||
|
||||
describeValueFormat('s', 1.23456789e-7, 1e-10, 8, '123.5 ns');
|
||||
describeValueFormat('s', 1.23456789e-4, 1e-7, 5, '123.5 µs');
|
||||
describeValueFormat('s', 1.23456789e-3, 1e-6, 4, '1.235 ms');
|
||||
describeValueFormat('s', 1.23456789e-2, 1e-5, 3, '12.35 ms');
|
||||
describeValueFormat('s', 1.23456789e-1, 1e-4, 2, '123.5 ms');
|
||||
describeValueFormat('s', 24, 1, 0, '24 s');
|
||||
describeValueFormat('s', 246, 1, 0, '4.1 min');
|
||||
describeValueFormat('s', 24567, 100, 0, '6.82 hour');
|
||||
describeValueFormat('s', 24567890, 10000, 0, '40.62 week');
|
||||
describeValueFormat('s', 24567890000, 1000000, 0, '778.53 year');
|
||||
|
||||
describeValueFormat('m', 24, 1, 0, '24 min');
|
||||
describeValueFormat('m', 246, 10, 0, '4.1 hour');
|
||||
describeValueFormat('m', 6545, 10, 0, '4.55 day');
|
||||
describeValueFormat('m', 24567, 100, 0, '2.44 week');
|
||||
describeValueFormat('m', 24567892, 10000, 0, '46.7 year');
|
||||
|
||||
describeValueFormat('h', 21, 1, 0, '21 hour');
|
||||
describeValueFormat('h', 145, 1, 0, '6.04 day');
|
||||
describeValueFormat('h', 1234, 100, 0, '7.3 week');
|
||||
describeValueFormat('h', 9458, 1000, 0, '1.08 year');
|
||||
|
||||
describeValueFormat('d', 3, 1, 0, '3 day');
|
||||
describeValueFormat('d', 245, 100, 0, '35 week');
|
||||
describeValueFormat('d', 2456, 10, 0, '6.73 year');
|
||||
|
||||
describe('date time formats', function() {
|
||||
it('should format as iso date', function() {
|
||||
var str = kbn.valueFormats.dateTimeAsIso(1505634997920, 1);
|
||||
expect(str).toBe(moment(1505634997920).format('YYYY-MM-DD HH:mm:ss'));
|
||||
});
|
||||
|
||||
it('should format as iso date and skip date when today', function() {
|
||||
var now = moment();
|
||||
var str = kbn.valueFormats.dateTimeAsIso(now.valueOf(), 1);
|
||||
expect(str).toBe(now.format("HH:mm:ss"));
|
||||
});
|
||||
|
||||
it('should format as US date', function() {
|
||||
var str = kbn.valueFormats.dateTimeAsUS(1505634997920, 1);
|
||||
expect(str).toBe(moment(1505634997920).format('MM/DD/YYYY H:mm:ss a'));
|
||||
});
|
||||
|
||||
it('should format as US date and skip date when today', function() {
|
||||
var now = moment();
|
||||
var str = kbn.valueFormats.dateTimeAsUS(now.valueOf(), 1);
|
||||
expect(str).toBe(now.format("h:mm:ss a"));
|
||||
});
|
||||
|
||||
it('should format as from now with days', function() {
|
||||
var daysAgo = moment().add(-7, 'd');
|
||||
var str = kbn.valueFormats.dateTimeFromNow(daysAgo.valueOf(), 1);
|
||||
expect(str).toBe('7 days ago');
|
||||
});
|
||||
|
||||
it('should format as from now with minutes', function() {
|
||||
var daysAgo = moment().add(-2, 'm');
|
||||
var str = kbn.valueFormats.dateTimeFromNow(daysAgo.valueOf(), 1);
|
||||
expect(str).toBe('2 minutes ago');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn.toFixed and negative decimals', function() {
|
||||
it('should treat as zero decimals', function() {
|
||||
var str = kbn.toFixed(186.123, -2);
|
||||
expect(str).toBe('186');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn ms format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['ms'](10000086.123, 1, null);
|
||||
expect(str).toBe('2.8 hour');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn kbytes format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['kbytes'](10000000, 3, null);
|
||||
expect(str).toBe('9.537 GiB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn deckbytes format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['deckbytes'](10000000, 3, null);
|
||||
expect(str).toBe('10.000 GB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn roundValue', function() {
|
||||
it('should should handle null value', function() {
|
||||
var str = kbn.roundValue(null, 2);
|
||||
expect(str).toBe(null);
|
||||
});
|
||||
it('should round value', function() {
|
||||
var str = kbn.roundValue(200.877, 2);
|
||||
expect(str).toBe(200.88);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calculateInterval', function() {
|
||||
it('1h 100 resultion', function() {
|
||||
var range = { from: dateMath.parse('now-1h'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 100, null);
|
||||
expect(res.interval).toBe('30s');
|
||||
});
|
||||
|
||||
it('10m 1600 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-10m'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1600, null);
|
||||
expect(res.interval).toBe('500ms');
|
||||
expect(res.intervalMs).toBe(500);
|
||||
});
|
||||
|
||||
it('fixed user min interval', function() {
|
||||
var range = {from: dateMath.parse('now-10m'), to: dateMath.parse('now')};
|
||||
var res = kbn.calculateInterval(range, 1600, '10s');
|
||||
expect(res.interval).toBe('10s');
|
||||
expect(res.intervalMs).toBe(10000);
|
||||
});
|
||||
|
||||
it('short time range and user low limit', function() {
|
||||
var range = { from: dateMath.parse('now-10m'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1600, '>10s');
|
||||
expect(res.interval).toBe('10s');
|
||||
});
|
||||
|
||||
it('large time range and user low limit', function() {
|
||||
var range = {from: dateMath.parse('now-14d'), to: dateMath.parse('now')};
|
||||
var res = kbn.calculateInterval(range, 1000, '>10s');
|
||||
expect(res.interval).toBe('20m');
|
||||
});
|
||||
|
||||
it('10s 900 resolution and user low limit in ms', function() {
|
||||
var range = { from: dateMath.parse('now-10s'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 900, '>15ms');
|
||||
expect(res.interval).toBe('15ms');
|
||||
});
|
||||
|
||||
it('1d 1 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-1d'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1, null);
|
||||
expect(res.interval).toBe('1d');
|
||||
expect(res.intervalMs).toBe(86400000);
|
||||
});
|
||||
|
||||
it('86399s 1 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-86390s'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1, null);
|
||||
expect(res.interval).toBe('12h');
|
||||
expect(res.intervalMs).toBe(43200000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hex', function() {
|
||||
it('positive integer', function() {
|
||||
var str = kbn.valueFormats.hex(100, 0);
|
||||
expect(str).toBe('64');
|
||||
});
|
||||
it('negative integer', function() {
|
||||
var str = kbn.valueFormats.hex(-100, 0);
|
||||
expect(str).toBe('-64');
|
||||
});
|
||||
it('null', function() {
|
||||
var str = kbn.valueFormats.hex(null, 0);
|
||||
expect(str).toBe('');
|
||||
});
|
||||
it('positive float', function() {
|
||||
var str = kbn.valueFormats.hex(50.52, 1);
|
||||
expect(str).toBe('32.8');
|
||||
});
|
||||
it('negative float', function() {
|
||||
var str = kbn.valueFormats.hex(-50.333, 2);
|
||||
expect(str).toBe('-32.547AE147AE14');
|
||||
});
|
||||
});
|
||||
|
||||
describe('hex 0x', function() {
|
||||
it('positive integeter', function() {
|
||||
var str = kbn.valueFormats.hex0x(7999,0);
|
||||
expect(str).toBe('0x1F3F');
|
||||
});
|
||||
it('negative integer', function() {
|
||||
var str = kbn.valueFormats.hex0x(-584,0);
|
||||
expect(str).toBe('-0x248');
|
||||
});
|
||||
it('null', function() {
|
||||
var str = kbn.valueFormats.hex0x(null, 0);
|
||||
expect(str).toBe('');
|
||||
});
|
||||
it('positive float', function() {
|
||||
var str = kbn.valueFormats.hex0x(74.443, 3);
|
||||
expect(str).toBe('0x4A.716872B020C4');
|
||||
});
|
||||
it('negative float', function() {
|
||||
var str = kbn.valueFormats.hex0x(-65.458, 1);
|
||||
expect(str).toBe('-0x41.8');
|
||||
});
|
||||
});
|
||||
|
||||
describe('duration', function() {
|
||||
it('null', function() {
|
||||
var str = kbn.toDuration(null, 0, "millisecond");
|
||||
expect(str).toBe('');
|
||||
});
|
||||
it('0 milliseconds', function() {
|
||||
var str = kbn.toDuration(0, 0, "millisecond");
|
||||
expect(str).toBe('0 milliseconds');
|
||||
});
|
||||
it('1 millisecond', function() {
|
||||
var str = kbn.toDuration(1, 0, "millisecond");
|
||||
expect(str).toBe('1 millisecond');
|
||||
});
|
||||
it('-1 millisecond', function() {
|
||||
var str = kbn.toDuration(-1, 0, "millisecond");
|
||||
expect(str).toBe('1 millisecond ago');
|
||||
});
|
||||
it('seconds', function() {
|
||||
var str = kbn.toDuration(1, 0, "second");
|
||||
expect(str).toBe('1 second');
|
||||
});
|
||||
it('minutes', function() {
|
||||
var str = kbn.toDuration(1, 0, "minute");
|
||||
expect(str).toBe('1 minute');
|
||||
});
|
||||
it('hours', function() {
|
||||
var str = kbn.toDuration(1, 0, "hour");
|
||||
expect(str).toBe('1 hour');
|
||||
});
|
||||
it('days', function() {
|
||||
var str = kbn.toDuration(1, 0, "day");
|
||||
expect(str).toBe('1 day');
|
||||
});
|
||||
it('weeks', function() {
|
||||
var str = kbn.toDuration(1, 0, "week");
|
||||
expect(str).toBe('1 week');
|
||||
});
|
||||
it('months', function() {
|
||||
var str = kbn.toDuration(1, 0, "month");
|
||||
expect(str).toBe('1 month');
|
||||
});
|
||||
it('years', function() {
|
||||
var str = kbn.toDuration(1, 0, "year");
|
||||
expect(str).toBe('1 year');
|
||||
});
|
||||
it('decimal days', function() {
|
||||
var str = kbn.toDuration(1.5, 2, "day");
|
||||
expect(str).toBe('1 day, 12 hours, 0 minutes');
|
||||
});
|
||||
it('decimal months', function() {
|
||||
var str = kbn.toDuration(1.5, 3, "month");
|
||||
expect(str).toBe('1 month, 2 weeks, 1 day, 0 hours');
|
||||
});
|
||||
it('no decimals', function() {
|
||||
var str = kbn.toDuration(38898367008, 0, "millisecond");
|
||||
expect(str).toBe('1 year');
|
||||
});
|
||||
it('1 decimal', function() {
|
||||
var str = kbn.toDuration(38898367008, 1, "millisecond");
|
||||
expect(str).toBe('1 year, 2 months');
|
||||
});
|
||||
it('too many decimals', function() {
|
||||
var str = kbn.toDuration(38898367008, 20, "millisecond");
|
||||
expect(str).toBe('1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, 7 seconds, 8 milliseconds');
|
||||
});
|
||||
it('floating point error', function() {
|
||||
var str = kbn.toDuration(36993906007, 8, "millisecond");
|
||||
expect(str).toBe('1 year, 2 months, 0 weeks, 3 days, 4 hours, 5 minutes, 6 seconds, 7 milliseconds');
|
||||
});
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import * as rangeUtil from 'app/core/utils/rangeutil';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
@ -9,100 +7,100 @@ describe("rangeUtil", () => {
|
||||
describe("Can get range grouped list of ranges", () => {
|
||||
it('when custom settings should return default range list', () => {
|
||||
var groups = rangeUtil.getRelativeTimesList({time_options: []}, 'Last 5 minutes');
|
||||
expect(_.keys(groups).length).to.be(4);
|
||||
expect(groups[3][0].active).to.be(true);
|
||||
expect(_.keys(groups).length).toBe(4);
|
||||
expect(groups[3][0].active).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Can get range text described", () => {
|
||||
it('should handle simple old expression with only amount and unit', () => {
|
||||
var info = rangeUtil.describeTextRange('5m');
|
||||
expect(info.display).to.be('Last 5 minutes');
|
||||
expect(info.display).toBe('Last 5 minutes');
|
||||
});
|
||||
|
||||
it('should have singular when amount is 1', () => {
|
||||
var info = rangeUtil.describeTextRange('1h');
|
||||
expect(info.display).to.be('Last 1 hour');
|
||||
expect(info.display).toBe('Last 1 hour');
|
||||
});
|
||||
|
||||
it('should handle non default amount', () => {
|
||||
var info = rangeUtil.describeTextRange('13h');
|
||||
expect(info.display).to.be('Last 13 hours');
|
||||
expect(info.from).to.be('now-13h');
|
||||
expect(info.display).toBe('Last 13 hours');
|
||||
expect(info.from).toBe('now-13h');
|
||||
});
|
||||
|
||||
it('should handle non default future amount', () => {
|
||||
var info = rangeUtil.describeTextRange('+3h');
|
||||
expect(info.display).to.be('Next 3 hours');
|
||||
expect(info.from).to.be('now');
|
||||
expect(info.to).to.be('now+3h');
|
||||
expect(info.display).toBe('Next 3 hours');
|
||||
expect(info.from).toBe('now');
|
||||
expect(info.to).toBe('now+3h');
|
||||
});
|
||||
|
||||
it('should handle now/d', () => {
|
||||
var info = rangeUtil.describeTextRange('now/d');
|
||||
expect(info.display).to.be('Today so far');
|
||||
expect(info.display).toBe('Today so far');
|
||||
});
|
||||
|
||||
it('should handle now/w', () => {
|
||||
var info = rangeUtil.describeTextRange('now/w');
|
||||
expect(info.display).to.be('This week so far');
|
||||
expect(info.display).toBe('This week so far');
|
||||
});
|
||||
|
||||
it('should handle now/M', () => {
|
||||
var info = rangeUtil.describeTextRange('now/M');
|
||||
expect(info.display).to.be('This month so far');
|
||||
expect(info.display).toBe('This month so far');
|
||||
});
|
||||
|
||||
it('should handle now/y', () => {
|
||||
var info = rangeUtil.describeTextRange('now/y');
|
||||
expect(info.display).to.be('This year so far');
|
||||
expect(info.display).toBe('This year so far');
|
||||
});
|
||||
});
|
||||
|
||||
describe("Can get date range described", () => {
|
||||
it('Date range with simple ranges', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now-1h', to: 'now'});
|
||||
expect(text).to.be('Last 1 hour');
|
||||
expect(text).toBe('Last 1 hour');
|
||||
});
|
||||
|
||||
it('Date range with rounding ranges', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now'});
|
||||
expect(text).to.be('now/d+6h to now');
|
||||
expect(text).toBe('now/d+6h to now');
|
||||
});
|
||||
|
||||
it('Date range with absolute to now', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now'});
|
||||
expect(text).to.be('Nov 10, 2014 02:03:04 to a few seconds ago');
|
||||
expect(text).toBe('Nov 10, 2014 02:03:04 to a few seconds ago');
|
||||
});
|
||||
|
||||
it('Date range with absolute to relative', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now-1d'});
|
||||
expect(text).to.be('Nov 10, 2014 02:03:04 to a day ago');
|
||||
expect(text).toBe('Nov 10, 2014 02:03:04 to a day ago');
|
||||
});
|
||||
|
||||
it('Date range with relative to absolute', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now-7d', to: moment([2014,10,10,2,3,4])});
|
||||
expect(text).to.be('7 days ago to Nov 10, 2014 02:03:04');
|
||||
expect(text).toBe('7 days ago to Nov 10, 2014 02:03:04');
|
||||
});
|
||||
|
||||
it('Date range with non matching default ranges', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now-13h', to: 'now'});
|
||||
expect(text).to.be('Last 13 hours');
|
||||
expect(text).toBe('Last 13 hours');
|
||||
});
|
||||
|
||||
it('Date range with from and to both are in now-* format', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now-3h'});
|
||||
expect(text).to.be('now-6h to now-3h');
|
||||
expect(text).toBe('now-6h to now-3h');
|
||||
});
|
||||
|
||||
it('Date range with from and to both are either in now-* or now/* format', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now-3h'});
|
||||
expect(text).to.be('now/d+6h to now-3h');
|
||||
expect(text).toBe('now/d+6h to now-3h');
|
||||
});
|
||||
|
||||
it('Date range with from and to both are either in now-* or now+* format', () => {
|
||||
var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now+1h'});
|
||||
expect(text).to.be('now-6h to now+1h');
|
||||
expect(text).toBe('now-6h to now+1h');
|
||||
});
|
||||
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import {describe, beforeEach, it, expect} from 'test/lib/common';
|
||||
|
||||
import TableModel from 'app/core/table_model';
|
||||
|
||||
describe('when sorting table desc', () => {
|
||||
@ -16,14 +14,14 @@ describe('when sorting table desc', () => {
|
||||
});
|
||||
|
||||
it('should sort by time', () => {
|
||||
expect(table.rows[0][0]).to.be(105);
|
||||
expect(table.rows[1][0]).to.be(103);
|
||||
expect(table.rows[2][0]).to.be(100);
|
||||
expect(table.rows[0][0]).toBe(105);
|
||||
expect(table.rows[1][0]).toBe(103);
|
||||
expect(table.rows[2][0]).toBe(100);
|
||||
});
|
||||
|
||||
it ('should mark column being sorted', () => {
|
||||
expect(table.columns[0].sort).to.be(true);
|
||||
expect(table.columns[0].desc).to.be(true);
|
||||
expect(table.columns[0].sort).toBe(true);
|
||||
expect(table.columns[0].desc).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
@ -42,9 +40,9 @@ describe('when sorting table asc', () => {
|
||||
});
|
||||
|
||||
it('should sort by time', () => {
|
||||
expect(table.rows[0][1]).to.be(10);
|
||||
expect(table.rows[1][1]).to.be(11);
|
||||
expect(table.rows[2][1]).to.be(15);
|
||||
expect(table.rows[0][1]).toBe(10);
|
||||
expect(table.rows[1][1]).toBe(11);
|
||||
expect(table.rows[2][1]).toBe(15);
|
||||
});
|
||||
|
||||
});
|
@ -1,4 +1,3 @@
|
||||
import {describe, beforeEach, it, expect} from 'test/lib/common';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
|
||||
describe("TimeSeries", function() {
|
||||
@ -19,14 +18,14 @@ describe("TimeSeries", function() {
|
||||
it('with connected style, should ignore nulls', function() {
|
||||
series = new TimeSeries(testData);
|
||||
points = series.getFlotPairs('connected', yAxisFormats);
|
||||
expect(points.length).to.be(3);
|
||||
expect(points.length).toBe(3);
|
||||
});
|
||||
|
||||
it('with null as zero style, should replace nulls with zero', function() {
|
||||
series = new TimeSeries(testData);
|
||||
points = series.getFlotPairs('null as zero', yAxisFormats);
|
||||
expect(points.length).to.be(4);
|
||||
expect(points[1][1]).to.be(0);
|
||||
expect(points.length).toBe(4);
|
||||
expect(points[1][1]).toBe(0);
|
||||
});
|
||||
|
||||
it('if last is null current should pick next to last', function() {
|
||||
@ -34,7 +33,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[10,1], [null, 2]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.current).to.be(10);
|
||||
expect(series.stats.current).toBe(10);
|
||||
});
|
||||
|
||||
it('max value should work for negative values', function() {
|
||||
@ -42,13 +41,13 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[-10,1], [-4, 2]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.max).to.be(-4);
|
||||
expect(series.stats.max).toBe(-4);
|
||||
});
|
||||
|
||||
it('average value should ignore nulls', function() {
|
||||
series = new TimeSeries(testData);
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.avg).to.be(6.333333333333333);
|
||||
expect(series.stats.avg).toBe(6.333333333333333);
|
||||
});
|
||||
|
||||
it('the delta value should account for nulls', function() {
|
||||
@ -56,7 +55,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[1,2],[3,3],[null,4],[10,5],[15,6]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.delta).to.be(14);
|
||||
expect(series.stats.delta).toBe(14);
|
||||
});
|
||||
|
||||
it('the delta value should account for nulls on first', function() {
|
||||
@ -64,7 +63,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[null,2],[1,3],[10,4],[15,5]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.delta).to.be(14);
|
||||
expect(series.stats.delta).toBe(14);
|
||||
});
|
||||
|
||||
it('the delta value should account for nulls on last', function() {
|
||||
@ -72,7 +71,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[1,2],[5,3],[10,4],[null,5]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.delta).to.be(9);
|
||||
expect(series.stats.delta).toBe(9);
|
||||
});
|
||||
|
||||
it('the delta value should account for resets', function() {
|
||||
@ -80,7 +79,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[1,2],[5,3],[10,4],[0,5],[10,6]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.delta).to.be(19);
|
||||
expect(series.stats.delta).toBe(19);
|
||||
});
|
||||
|
||||
it('the delta value should account for resets on last', function() {
|
||||
@ -88,30 +87,30 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[1,2],[2,3],[10,4],[8,5]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.delta).to.be(17);
|
||||
expect(series.stats.delta).toBe(17);
|
||||
});
|
||||
|
||||
it('the range value should be max - min', function() {
|
||||
series = new TimeSeries(testData);
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.range).to.be(9);
|
||||
expect(series.stats.range).toBe(9);
|
||||
});
|
||||
|
||||
it('first value should ingone nulls', function() {
|
||||
series = new TimeSeries(testData);
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.first).to.be(1);
|
||||
expect(series.stats.first).toBe(1);
|
||||
series = new TimeSeries({
|
||||
datapoints: [[null,2],[1,3],[10,4],[8,5]]
|
||||
});
|
||||
series.getFlotPairs('null', yAxisFormats);
|
||||
expect(series.stats.first).to.be(1);
|
||||
expect(series.stats.first).toBe(1);
|
||||
});
|
||||
|
||||
it('with null as zero style, average value should treat nulls as 0', function() {
|
||||
series = new TimeSeries(testData);
|
||||
series.getFlotPairs('null as zero', yAxisFormats);
|
||||
expect(series.stats.avg).to.be(4.75);
|
||||
expect(series.stats.avg).toBe(4.75);
|
||||
});
|
||||
|
||||
it('average value should be null if all values is null', function() {
|
||||
@ -119,7 +118,7 @@ describe("TimeSeries", function() {
|
||||
datapoints: [[null,2],[null,3],[null,4],[null,5]]
|
||||
});
|
||||
series.getFlotPairs('null');
|
||||
expect(series.stats.avg).to.be(null);
|
||||
expect(series.stats.avg).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
@ -130,7 +129,7 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should set hasMsResolution to false', function() {
|
||||
expect(series.hasMsResolution).to.be(false);
|
||||
expect(series.hasMsResolution).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -140,7 +139,7 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should show millisecond resolution tooltip', function() {
|
||||
expect(series.hasMsResolution).to.be(true);
|
||||
expect(series.hasMsResolution).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -150,7 +149,7 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should not show millisecond resolution tooltip', function() {
|
||||
expect(series.hasMsResolution).to.be(false);
|
||||
expect(series.hasMsResolution).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -165,13 +164,13 @@ describe("TimeSeries", function() {
|
||||
it('missing datapoint with ms precision', function() {
|
||||
fakedata.datapoints[0] = [1337, 1234567890000];
|
||||
series = new TimeSeries(fakedata);
|
||||
expect(series.isMsResolutionNeeded()).to.be(false);
|
||||
expect(series.isMsResolutionNeeded()).toBe(false);
|
||||
});
|
||||
|
||||
it('contains datapoint with ms precision', function() {
|
||||
fakedata.datapoints[0] = [1337, 1236547890001];
|
||||
series = new TimeSeries(fakedata);
|
||||
expect(series.isMsResolutionNeeded()).to.be(true);
|
||||
expect(series.isMsResolutionNeeded()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -188,8 +187,8 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should set fill zero, and enable points', function() {
|
||||
expect(series.lines.fill).to.be(0.001);
|
||||
expect(series.points.show).to.be(true);
|
||||
expect(series.lines.fill).toBe(0.001);
|
||||
expect(series.points.show).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -200,8 +199,8 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should disable lines, and enable bars', function() {
|
||||
expect(series.lines.show).to.be(false);
|
||||
expect(series.bars.show).to.be(true);
|
||||
expect(series.lines.show).toBe(false);
|
||||
expect(series.bars.show).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -212,8 +211,8 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should disable stack, and set lineWidth', function() {
|
||||
expect(series.stack).to.be(false);
|
||||
expect(series.lines.lineWidth).to.be(5);
|
||||
expect(series.stack).toBe(false);
|
||||
expect(series.lines.lineWidth).toBe(5);
|
||||
});
|
||||
});
|
||||
|
||||
@ -224,9 +223,9 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should enable dashes, set dashes lineWidth to 5 and lines lineWidth to 0', function() {
|
||||
expect(series.dashes.show).to.be(true);
|
||||
expect(series.dashes.lineWidth).to.be(5);
|
||||
expect(series.lines.lineWidth).to.be(0);
|
||||
expect(series.dashes.show).toBe(true);
|
||||
expect(series.dashes.lineWidth).toBe(5);
|
||||
expect(series.lines.lineWidth).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -237,7 +236,7 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should disable line fill and add fillBelowTo', function() {
|
||||
expect(series.fillBelowTo).to.be('min');
|
||||
expect(series.fillBelowTo).toBe('min');
|
||||
});
|
||||
});
|
||||
|
||||
@ -248,8 +247,8 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should set pointradius, and set steppedLine', function() {
|
||||
expect(series.points.radius).to.be(5);
|
||||
expect(series.lines.steps).to.be(true);
|
||||
expect(series.points.radius).toBe(5);
|
||||
expect(series.lines.steps).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -260,7 +259,7 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should match second series', function() {
|
||||
expect(series.lines.show).to.be(false);
|
||||
expect(series.lines.show).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -271,11 +270,11 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should set yaxis', function() {
|
||||
expect(series.yaxis).to.be(2);
|
||||
expect(series.yaxis).toBe(2);
|
||||
});
|
||||
|
||||
it('should set zindex', function() {
|
||||
expect(series.zindex).to.be(2);
|
||||
expect(series.zindex).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@ -288,11 +287,11 @@ describe("TimeSeries", function() {
|
||||
});
|
||||
|
||||
it('should format non-numeric values as empty string', function() {
|
||||
expect(series.formatValue(null)).to.be("");
|
||||
expect(series.formatValue(undefined)).to.be("");
|
||||
expect(series.formatValue(NaN)).to.be("");
|
||||
expect(series.formatValue(Infinity)).to.be("");
|
||||
expect(series.formatValue(-Infinity)).to.be("");
|
||||
expect(series.formatValue(null)).toBe("");
|
||||
expect(series.formatValue(undefined)).toBe("");
|
||||
expect(series.formatValue(NaN)).toBe("");
|
||||
expect(series.formatValue(Infinity)).toBe("");
|
||||
expect(series.formatValue(-Infinity)).toBe("");
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +0,0 @@
|
||||
define([
|
||||
'./time_series2'
|
||||
], function(timeSeries) {
|
||||
'use strict';
|
||||
// backward compatability hack;
|
||||
return timeSeries.default;
|
||||
});
|
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { react2AngularDirective } from 'app/core/utils/react2angular';
|
||||
|
||||
export interface IProps {
|
||||
password: string;
|
||||
@ -33,5 +32,4 @@ export class PasswordStrength extends React.Component<IProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||
|
@ -1,936 +0,0 @@
|
||||
define([
|
||||
'jquery',
|
||||
'lodash',
|
||||
'moment'
|
||||
],
|
||||
function($, _, moment) {
|
||||
'use strict';
|
||||
|
||||
var kbn = {};
|
||||
kbn.valueFormats = {};
|
||||
|
||||
kbn.regexEscape = function(value) {
|
||||
return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
|
||||
};
|
||||
|
||||
///// HELPER FUNCTIONS /////
|
||||
|
||||
kbn.round_interval = function(interval) {
|
||||
switch (true) {
|
||||
// 0.015s
|
||||
case (interval < 15):
|
||||
return 10; // 0.01s
|
||||
// 0.035s
|
||||
case (interval < 35):
|
||||
return 20; // 0.02s
|
||||
// 0.075s
|
||||
case (interval < 75):
|
||||
return 50; // 0.05s
|
||||
// 0.15s
|
||||
case (interval < 150):
|
||||
return 100; // 0.1s
|
||||
// 0.35s
|
||||
case (interval < 350):
|
||||
return 200; // 0.2s
|
||||
// 0.75s
|
||||
case (interval < 750):
|
||||
return 500; // 0.5s
|
||||
// 1.5s
|
||||
case (interval < 1500):
|
||||
return 1000; // 1s
|
||||
// 3.5s
|
||||
case (interval < 3500):
|
||||
return 2000; // 2s
|
||||
// 7.5s
|
||||
case (interval < 7500):
|
||||
return 5000; // 5s
|
||||
// 12.5s
|
||||
case (interval < 12500):
|
||||
return 10000; // 10s
|
||||
// 17.5s
|
||||
case (interval < 17500):
|
||||
return 15000; // 15s
|
||||
// 25s
|
||||
case (interval < 25000):
|
||||
return 20000; // 20s
|
||||
// 45s
|
||||
case (interval < 45000):
|
||||
return 30000; // 30s
|
||||
// 1.5m
|
||||
case (interval < 90000):
|
||||
return 60000; // 1m
|
||||
// 3.5m
|
||||
case (interval < 210000):
|
||||
return 120000; // 2m
|
||||
// 7.5m
|
||||
case (interval < 450000):
|
||||
return 300000; // 5m
|
||||
// 12.5m
|
||||
case (interval < 750000):
|
||||
return 600000; // 10m
|
||||
// 12.5m
|
||||
case (interval < 1050000):
|
||||
return 900000; // 15m
|
||||
// 25m
|
||||
case (interval < 1500000):
|
||||
return 1200000; // 20m
|
||||
// 45m
|
||||
case (interval < 2700000):
|
||||
return 1800000; // 30m
|
||||
// 1.5h
|
||||
case (interval < 5400000):
|
||||
return 3600000; // 1h
|
||||
// 2.5h
|
||||
case (interval < 9000000):
|
||||
return 7200000; // 2h
|
||||
// 4.5h
|
||||
case (interval < 16200000):
|
||||
return 10800000; // 3h
|
||||
// 9h
|
||||
case (interval < 32400000):
|
||||
return 21600000; // 6h
|
||||
// 1d
|
||||
case (interval < 86400000):
|
||||
return 43200000; // 12h
|
||||
// 1w
|
||||
case (interval < 604800000):
|
||||
return 86400000; // 1d
|
||||
// 3w
|
||||
case (interval < 1814400000):
|
||||
return 604800000; // 1w
|
||||
// 6w
|
||||
case (interval < 3628800000):
|
||||
return 2592000000; // 30d
|
||||
default:
|
||||
return 31536000000; // 1y
|
||||
}
|
||||
};
|
||||
|
||||
kbn.secondsToHms = function(seconds) {
|
||||
var numyears = Math.floor(seconds / 31536000);
|
||||
if(numyears){
|
||||
return numyears + 'y';
|
||||
}
|
||||
var numdays = Math.floor((seconds % 31536000) / 86400);
|
||||
if(numdays){
|
||||
return numdays + 'd';
|
||||
}
|
||||
var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
|
||||
if(numhours){
|
||||
return numhours + 'h';
|
||||
}
|
||||
var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
|
||||
if(numminutes){
|
||||
return numminutes + 'm';
|
||||
}
|
||||
var numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);
|
||||
if(numseconds){
|
||||
return numseconds + 's';
|
||||
}
|
||||
var nummilliseconds = Math.floor(seconds * 1000.0);
|
||||
if(nummilliseconds){
|
||||
return nummilliseconds + 'ms';
|
||||
}
|
||||
|
||||
return 'less than a millisecond'; //'just now' //or other string you like;
|
||||
};
|
||||
|
||||
kbn.to_percent = function(number,outof) {
|
||||
return Math.floor((number/outof)*10000)/100 + "%";
|
||||
};
|
||||
|
||||
kbn.addslashes = function(str) {
|
||||
str = str.replace(/\\/g, '\\\\');
|
||||
str = str.replace(/\'/g, '\\\'');
|
||||
str = str.replace(/\"/g, '\\"');
|
||||
str = str.replace(/\0/g, '\\0');
|
||||
return str;
|
||||
};
|
||||
|
||||
kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/;
|
||||
|
||||
// histogram & trends
|
||||
kbn.intervals_in_seconds = {
|
||||
y: 31536000,
|
||||
M: 2592000,
|
||||
w: 604800,
|
||||
d: 86400,
|
||||
h: 3600,
|
||||
m: 60,
|
||||
s: 1,
|
||||
ms: 0.001
|
||||
};
|
||||
|
||||
kbn.calculateInterval = function(range, resolution, lowLimitInterval) {
|
||||
var lowLimitMs = 1; // 1 millisecond default low limit
|
||||
var intervalMs;
|
||||
|
||||
if (lowLimitInterval) {
|
||||
if (lowLimitInterval[0] === '>') {
|
||||
lowLimitInterval = lowLimitInterval.slice(1);
|
||||
}
|
||||
lowLimitMs = kbn.interval_to_ms(lowLimitInterval);
|
||||
}
|
||||
|
||||
intervalMs = kbn.round_interval((range.to.valueOf() - range.from.valueOf()) / resolution);
|
||||
if (lowLimitMs > intervalMs) {
|
||||
intervalMs = lowLimitMs;
|
||||
}
|
||||
|
||||
return {
|
||||
intervalMs: intervalMs,
|
||||
interval: kbn.secondsToHms(intervalMs / 1000),
|
||||
};
|
||||
};
|
||||
|
||||
kbn.describe_interval = function (string) {
|
||||
var matches = string.match(kbn.interval_regex);
|
||||
if (!matches || !_.has(kbn.intervals_in_seconds, matches[2])) {
|
||||
throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"');
|
||||
} else {
|
||||
return {
|
||||
sec: kbn.intervals_in_seconds[matches[2]],
|
||||
type: matches[2],
|
||||
count: parseInt(matches[1], 10)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
kbn.interval_to_ms = function(string) {
|
||||
var info = kbn.describe_interval(string);
|
||||
return info.sec * 1000 * info.count;
|
||||
};
|
||||
|
||||
kbn.interval_to_seconds = function (string) {
|
||||
var info = kbn.describe_interval(string);
|
||||
return info.sec * info.count;
|
||||
};
|
||||
|
||||
kbn.query_color_dot = function (color, diameter) {
|
||||
return '<div class="icon-circle" style="' + [
|
||||
'display:inline-block',
|
||||
'color:' + color,
|
||||
'font-size:' + diameter + 'px',
|
||||
].join(';') + '"></div>';
|
||||
};
|
||||
|
||||
kbn.slugifyForUrl = function(str) {
|
||||
return str
|
||||
.toLowerCase()
|
||||
.replace(/[^\w ]+/g,'')
|
||||
.replace(/ +/g,'-');
|
||||
};
|
||||
|
||||
kbn.stringToJsRegex = function(str) {
|
||||
if (str[0] !== '/') {
|
||||
return new RegExp('^' + str + '$');
|
||||
}
|
||||
|
||||
var match = str.match(new RegExp('^/(.*?)/(g?i?m?y?)$'));
|
||||
return new RegExp(match[1], match[2]);
|
||||
};
|
||||
|
||||
kbn.toFixed = function(value, decimals) {
|
||||
if (value === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1;
|
||||
var formatted = String(Math.round(value * factor) / factor);
|
||||
|
||||
// if exponent return directly
|
||||
if (formatted.indexOf('e') !== -1 || value === 0) {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
// If tickDecimals was specified, ensure that we have exactly that
|
||||
// much precision; otherwise default to the value's own precision.
|
||||
if (decimals != null) {
|
||||
var decimalPos = formatted.indexOf(".");
|
||||
var precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1;
|
||||
if (precision < decimals) {
|
||||
return (precision ? formatted : formatted + ".") + (String(factor)).substr(1, decimals - precision);
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
};
|
||||
|
||||
kbn.toFixedScaled = function(value, decimals, scaledDecimals, additionalDecimals, ext) {
|
||||
if (scaledDecimals === null) {
|
||||
return kbn.toFixed(value, decimals) + ext;
|
||||
} else {
|
||||
return kbn.toFixed(value, scaledDecimals + additionalDecimals) + ext;
|
||||
}
|
||||
};
|
||||
|
||||
kbn.roundValue = function (num, decimals) {
|
||||
if (num === null) { return null; }
|
||||
var n = Math.pow(10, decimals);
|
||||
return Math.round((n * num).toFixed(decimals)) / n;
|
||||
};
|
||||
|
||||
///// FORMAT FUNCTION CONSTRUCTORS /////
|
||||
|
||||
kbn.formatBuilders = {};
|
||||
|
||||
// Formatter which always appends a fixed unit string to the value. No
|
||||
// scaling of the value is performed.
|
||||
kbn.formatBuilders.fixedUnit = function(unit) {
|
||||
return function(size, decimals) {
|
||||
if (size === null) { return ""; }
|
||||
return kbn.toFixed(size, decimals) + ' ' + unit;
|
||||
};
|
||||
};
|
||||
|
||||
// Formatter which scales the unit string geometrically according to the given
|
||||
// numeric factor. Repeatedly scales the value down by the factor until it is
|
||||
// less than the factor in magnitude, or the end of the array is reached.
|
||||
kbn.formatBuilders.scaledUnits = function(factor, extArray) {
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var steps = 0;
|
||||
var limit = extArray.length;
|
||||
|
||||
while (Math.abs(size) >= factor) {
|
||||
steps++;
|
||||
size /= factor;
|
||||
|
||||
if (steps >= limit) { return "NA"; }
|
||||
}
|
||||
|
||||
if (steps > 0 && scaledDecimals !== null) {
|
||||
decimals = scaledDecimals + (3 * steps);
|
||||
}
|
||||
|
||||
return kbn.toFixed(size, decimals) + extArray[steps];
|
||||
};
|
||||
};
|
||||
|
||||
// Extension of the scaledUnits builder which uses SI decimal prefixes. If an
|
||||
// offset is given, it adjusts the starting units at the given prefix; a value
|
||||
// of 0 starts at no scale; -3 drops to nano, +2 starts at mega, etc.
|
||||
kbn.formatBuilders.decimalSIPrefix = function(unit, offset) {
|
||||
var prefixes = ['n', 'µ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
||||
prefixes = prefixes.slice(3 + (offset || 0));
|
||||
var units = prefixes.map(function(p) { return ' ' + p + unit; });
|
||||
return kbn.formatBuilders.scaledUnits(1000, units);
|
||||
};
|
||||
|
||||
// Extension of the scaledUnits builder which uses SI binary prefixes. If
|
||||
// offset is given, it starts the units at the given prefix; otherwise, the
|
||||
// offset defaults to zero and the initial unit is not prefixed.
|
||||
kbn.formatBuilders.binarySIPrefix = function(unit, offset) {
|
||||
var prefixes = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'].slice(offset);
|
||||
var units = prefixes.map(function(p) { return ' ' + p + unit; });
|
||||
return kbn.formatBuilders.scaledUnits(1024, units);
|
||||
};
|
||||
|
||||
// Currency formatter for prefixing a symbol onto a number. Supports scaling
|
||||
// up to the trillions.
|
||||
kbn.formatBuilders.currency = function(symbol) {
|
||||
var units = ['', 'K', 'M', 'B', 'T'];
|
||||
var scaler = kbn.formatBuilders.scaledUnits(1000, units);
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
var scaled = scaler(size, decimals, scaledDecimals);
|
||||
return symbol + scaled;
|
||||
};
|
||||
};
|
||||
|
||||
kbn.formatBuilders.simpleCountUnit = function(symbol) {
|
||||
var units = ['', 'K', 'M', 'B', 'T'];
|
||||
var scaler = kbn.formatBuilders.scaledUnits(1000, units);
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
var scaled = scaler(size, decimals, scaledDecimals);
|
||||
return scaled + " " + symbol;
|
||||
};
|
||||
};
|
||||
|
||||
///// VALUE FORMATS /////
|
||||
|
||||
// Dimensionless Units
|
||||
kbn.valueFormats.none = kbn.toFixed;
|
||||
kbn.valueFormats.short = kbn.formatBuilders.scaledUnits(1000, ['', ' K', ' Mil', ' Bil', ' Tri', ' Quadr', ' Quint', ' Sext', ' Sept']);
|
||||
kbn.valueFormats.dB = kbn.formatBuilders.fixedUnit('dB');
|
||||
kbn.valueFormats.ppm = kbn.formatBuilders.fixedUnit('ppm');
|
||||
|
||||
kbn.valueFormats.percent = function(size, decimals) {
|
||||
if (size === null) { return ""; }
|
||||
return kbn.toFixed(size, decimals) + '%';
|
||||
};
|
||||
|
||||
kbn.valueFormats.percentunit = function(size, decimals) {
|
||||
if (size === null) { return ""; }
|
||||
return kbn.toFixed(100*size, decimals) + '%';
|
||||
};
|
||||
|
||||
/* Formats the value to hex. Uses float if specified decimals are not 0.
|
||||
* There are two options, one with 0x, and one without */
|
||||
|
||||
kbn.valueFormats.hex = function(value, decimals) {
|
||||
if (value == null) { return ""; }
|
||||
return parseFloat(kbn.toFixed(value, decimals)).toString(16).toUpperCase();
|
||||
};
|
||||
|
||||
kbn.valueFormats.hex0x = function(value, decimals) {
|
||||
if (value == null) { return ""; }
|
||||
var hexString = kbn.valueFormats.hex(value, decimals);
|
||||
if (hexString.substring(0,1) === "-") {
|
||||
return "-0x" + hexString.substring(1);
|
||||
}
|
||||
return "0x" + hexString;
|
||||
};
|
||||
|
||||
kbn.valueFormats.sci = function(value, decimals) {
|
||||
return value.toExponential(decimals);
|
||||
};
|
||||
|
||||
kbn.valueFormats.locale = function(value, decimals) {
|
||||
return value.toLocaleString(undefined, {maximumFractionDigits: decimals});
|
||||
};
|
||||
|
||||
// Currencies
|
||||
kbn.valueFormats.currencyUSD = kbn.formatBuilders.currency('$');
|
||||
kbn.valueFormats.currencyGBP = kbn.formatBuilders.currency('£');
|
||||
kbn.valueFormats.currencyEUR = kbn.formatBuilders.currency('€');
|
||||
kbn.valueFormats.currencyJPY = kbn.formatBuilders.currency('¥');
|
||||
kbn.valueFormats.currencyRUB = kbn.formatBuilders.currency('₽');
|
||||
kbn.valueFormats.currencyUAH = kbn.formatBuilders.currency('₴');
|
||||
kbn.valueFormats.currencyBRL = kbn.formatBuilders.currency('R$');
|
||||
kbn.valueFormats.currencyDKK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencyISK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencyNOK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencySEK = kbn.formatBuilders.currency('kr');
|
||||
|
||||
// Data (Binary)
|
||||
kbn.valueFormats.bits = kbn.formatBuilders.binarySIPrefix('b');
|
||||
kbn.valueFormats.bytes = kbn.formatBuilders.binarySIPrefix('B');
|
||||
kbn.valueFormats.kbytes = kbn.formatBuilders.binarySIPrefix('B', 1);
|
||||
kbn.valueFormats.mbytes = kbn.formatBuilders.binarySIPrefix('B', 2);
|
||||
kbn.valueFormats.gbytes = kbn.formatBuilders.binarySIPrefix('B', 3);
|
||||
|
||||
// Data (Decimal)
|
||||
kbn.valueFormats.decbits = kbn.formatBuilders.decimalSIPrefix('b');
|
||||
kbn.valueFormats.decbytes = kbn.formatBuilders.decimalSIPrefix('B');
|
||||
kbn.valueFormats.deckbytes = kbn.formatBuilders.decimalSIPrefix('B', 1);
|
||||
kbn.valueFormats.decmbytes = kbn.formatBuilders.decimalSIPrefix('B', 2);
|
||||
kbn.valueFormats.decgbytes = kbn.formatBuilders.decimalSIPrefix('B', 3);
|
||||
|
||||
// Data Rate
|
||||
kbn.valueFormats.pps = kbn.formatBuilders.decimalSIPrefix('pps');
|
||||
kbn.valueFormats.bps = kbn.formatBuilders.decimalSIPrefix('bps');
|
||||
kbn.valueFormats.Bps = kbn.formatBuilders.decimalSIPrefix('Bps');
|
||||
kbn.valueFormats.KBs = kbn.formatBuilders.decimalSIPrefix('Bs', 1);
|
||||
kbn.valueFormats.Kbits = kbn.formatBuilders.decimalSIPrefix('bps', 1);
|
||||
kbn.valueFormats.MBs = kbn.formatBuilders.decimalSIPrefix('Bs', 2);
|
||||
kbn.valueFormats.Mbits = kbn.formatBuilders.decimalSIPrefix('bps', 2);
|
||||
kbn.valueFormats.GBs = kbn.formatBuilders.decimalSIPrefix('Bs', 3);
|
||||
kbn.valueFormats.Gbits = kbn.formatBuilders.decimalSIPrefix('bps', 3);
|
||||
|
||||
// Throughput
|
||||
kbn.valueFormats.ops = kbn.formatBuilders.simpleCountUnit('ops');
|
||||
kbn.valueFormats.rps = kbn.formatBuilders.simpleCountUnit('rps');
|
||||
kbn.valueFormats.wps = kbn.formatBuilders.simpleCountUnit('wps');
|
||||
kbn.valueFormats.iops = kbn.formatBuilders.simpleCountUnit('iops');
|
||||
kbn.valueFormats.opm = kbn.formatBuilders.simpleCountUnit('opm');
|
||||
kbn.valueFormats.rpm = kbn.formatBuilders.simpleCountUnit('rpm');
|
||||
kbn.valueFormats.wpm = kbn.formatBuilders.simpleCountUnit('wpm');
|
||||
|
||||
// Energy
|
||||
kbn.valueFormats.watt = kbn.formatBuilders.decimalSIPrefix('W');
|
||||
kbn.valueFormats.kwatt = kbn.formatBuilders.decimalSIPrefix('W', 1);
|
||||
kbn.valueFormats.voltamp = kbn.formatBuilders.decimalSIPrefix('VA');
|
||||
kbn.valueFormats.kvoltamp = kbn.formatBuilders.decimalSIPrefix('VA', 1);
|
||||
kbn.valueFormats.voltampreact = kbn.formatBuilders.decimalSIPrefix('var');
|
||||
kbn.valueFormats.kvoltampreact = kbn.formatBuilders.decimalSIPrefix('var', 1);
|
||||
kbn.valueFormats.watth = kbn.formatBuilders.decimalSIPrefix('Wh');
|
||||
kbn.valueFormats.kwatth = kbn.formatBuilders.decimalSIPrefix('Wh', 1);
|
||||
kbn.valueFormats.joule = kbn.formatBuilders.decimalSIPrefix('J');
|
||||
kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV');
|
||||
kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A');
|
||||
kbn.valueFormats.kamp = kbn.formatBuilders.decimalSIPrefix('A', 1);
|
||||
kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V');
|
||||
kbn.valueFormats.kvolt = kbn.formatBuilders.decimalSIPrefix('V', 1);
|
||||
kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm');
|
||||
|
||||
// Temperature
|
||||
kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C');
|
||||
kbn.valueFormats.farenheit = kbn.formatBuilders.fixedUnit('°F');
|
||||
kbn.valueFormats.kelvin = kbn.formatBuilders.fixedUnit('K');
|
||||
kbn.valueFormats.humidity = kbn.formatBuilders.fixedUnit('%H');
|
||||
|
||||
// Pressure
|
||||
kbn.valueFormats.pressurebar = kbn.formatBuilders.decimalSIPrefix('bar');
|
||||
kbn.valueFormats.pressurembar = kbn.formatBuilders.decimalSIPrefix('bar', -1);
|
||||
kbn.valueFormats.pressurekbar = kbn.formatBuilders.decimalSIPrefix('bar', 1);
|
||||
kbn.valueFormats.pressurehpa = kbn.formatBuilders.fixedUnit('hPa');
|
||||
kbn.valueFormats.pressurehg = kbn.formatBuilders.fixedUnit('"Hg');
|
||||
kbn.valueFormats.pressurepsi = kbn.formatBuilders.scaledUnits(1000, [' psi', ' ksi', ' Mpsi']);
|
||||
|
||||
// Force
|
||||
kbn.valueFormats.forceNm = kbn.formatBuilders.decimalSIPrefix('Nm');
|
||||
kbn.valueFormats.forcekNm = kbn.formatBuilders.decimalSIPrefix('Nm', 1);
|
||||
kbn.valueFormats.forceN = kbn.formatBuilders.decimalSIPrefix('N');
|
||||
kbn.valueFormats.forcekN = kbn.formatBuilders.decimalSIPrefix('N', 1);
|
||||
|
||||
// Length
|
||||
kbn.valueFormats.lengthm = kbn.formatBuilders.decimalSIPrefix('m');
|
||||
kbn.valueFormats.lengthmm = kbn.formatBuilders.decimalSIPrefix('m', -1);
|
||||
kbn.valueFormats.lengthkm = kbn.formatBuilders.decimalSIPrefix('m', 1);
|
||||
kbn.valueFormats.lengthmi = kbn.formatBuilders.fixedUnit('mi');
|
||||
|
||||
// Mass
|
||||
kbn.valueFormats.massmg = kbn.formatBuilders.decimalSIPrefix('g', -1);
|
||||
kbn.valueFormats.massg = kbn.formatBuilders.decimalSIPrefix('g');
|
||||
kbn.valueFormats.masskg = kbn.formatBuilders.decimalSIPrefix('g', 1);
|
||||
kbn.valueFormats.masst = kbn.formatBuilders.fixedUnit('t');
|
||||
|
||||
// Velocity
|
||||
kbn.valueFormats.velocityms = kbn.formatBuilders.fixedUnit('m/s');
|
||||
kbn.valueFormats.velocitykmh = kbn.formatBuilders.fixedUnit('km/h');
|
||||
kbn.valueFormats.velocitymph = kbn.formatBuilders.fixedUnit('mph');
|
||||
kbn.valueFormats.velocityknot = kbn.formatBuilders.fixedUnit('kn');
|
||||
|
||||
// Volume
|
||||
kbn.valueFormats.litre = kbn.formatBuilders.decimalSIPrefix('L');
|
||||
kbn.valueFormats.mlitre = kbn.formatBuilders.decimalSIPrefix('L', -1);
|
||||
kbn.valueFormats.m3 = kbn.formatBuilders.decimalSIPrefix('m3');
|
||||
kbn.valueFormats.dm3 = kbn.formatBuilders.decimalSIPrefix('dm3');
|
||||
kbn.valueFormats.gallons = kbn.formatBuilders.fixedUnit('gal');
|
||||
|
||||
// Flow
|
||||
kbn.valueFormats.flowgpm = kbn.formatBuilders.fixedUnit('gpm');
|
||||
kbn.valueFormats.flowcms = kbn.formatBuilders.fixedUnit('cms');
|
||||
kbn.valueFormats.flowcfs = kbn.formatBuilders.fixedUnit('cfs');
|
||||
kbn.valueFormats.flowcfm = kbn.formatBuilders.fixedUnit('cfm');
|
||||
|
||||
// Time
|
||||
kbn.valueFormats.hertz = kbn.formatBuilders.decimalSIPrefix('Hz');
|
||||
|
||||
kbn.valueFormats.ms = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + " ms";
|
||||
}
|
||||
// Less than 1 min
|
||||
else if (Math.abs(size) < 60000) {
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, " s");
|
||||
}
|
||||
// Less than 1 hour, devide in minutes
|
||||
else if (Math.abs(size) < 3600000) {
|
||||
return kbn.toFixedScaled(size / 60000, decimals, scaledDecimals, 5, " min");
|
||||
}
|
||||
// Less than one day, devide in hours
|
||||
else if (Math.abs(size) < 86400000) {
|
||||
return kbn.toFixedScaled(size / 3600000, decimals, scaledDecimals, 7, " hour");
|
||||
}
|
||||
// Less than one year, devide in days
|
||||
else if (Math.abs(size) < 31536000000) {
|
||||
return kbn.toFixedScaled(size / 86400000, decimals, scaledDecimals, 8, " day");
|
||||
}
|
||||
|
||||
return kbn.toFixedScaled(size / 31536000000, decimals, scaledDecimals, 10, " year");
|
||||
};
|
||||
|
||||
kbn.valueFormats.s = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
// Less than 1 µs, devide in ns
|
||||
if (Math.abs(size) < 0.000001) {
|
||||
return kbn.toFixedScaled(size * 1.e9, decimals, scaledDecimals - decimals, -9, " ns");
|
||||
}
|
||||
// Less than 1 ms, devide in µs
|
||||
if (Math.abs(size) < 0.001) {
|
||||
return kbn.toFixedScaled(size * 1.e6, decimals, scaledDecimals - decimals, -6, " µs");
|
||||
}
|
||||
// Less than 1 second, devide in ms
|
||||
if (Math.abs(size) < 1) {
|
||||
return kbn.toFixedScaled(size * 1.e3, decimals, scaledDecimals - decimals, -3, " ms");
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 60) {
|
||||
return kbn.toFixed(size, decimals) + " s";
|
||||
}
|
||||
// Less than 1 hour, devide in minutes
|
||||
else if (Math.abs(size) < 3600) {
|
||||
return kbn.toFixedScaled(size / 60, decimals, scaledDecimals, 1, " min");
|
||||
}
|
||||
// Less than one day, devide in hours
|
||||
else if (Math.abs(size) < 86400) {
|
||||
return kbn.toFixedScaled(size / 3600, decimals, scaledDecimals, 4, " hour");
|
||||
}
|
||||
// Less than one week, devide in days
|
||||
else if (Math.abs(size) < 604800) {
|
||||
return kbn.toFixedScaled(size / 86400, decimals, scaledDecimals, 5, " day");
|
||||
}
|
||||
// Less than one year, devide in week
|
||||
else if (Math.abs(size) < 31536000) {
|
||||
return kbn.toFixedScaled(size / 604800, decimals, scaledDecimals, 6, " week");
|
||||
}
|
||||
|
||||
return kbn.toFixedScaled(size / 3.15569e7, decimals, scaledDecimals, 7, " year");
|
||||
};
|
||||
|
||||
kbn.valueFormats['µs'] = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + " µs";
|
||||
}
|
||||
else if (Math.abs(size) < 1000000) {
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, " ms");
|
||||
}
|
||||
else {
|
||||
return kbn.toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, " s");
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.ns = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + " ns";
|
||||
}
|
||||
else if (Math.abs(size) < 1000000) {
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, " µs");
|
||||
}
|
||||
else if (Math.abs(size) < 1000000000) {
|
||||
return kbn.toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, " ms");
|
||||
}
|
||||
else if (Math.abs(size) < 60000000000){
|
||||
return kbn.toFixedScaled(size / 1000000000, decimals, scaledDecimals, 9, " s");
|
||||
}
|
||||
else {
|
||||
return kbn.toFixedScaled(size / 60000000000, decimals, scaledDecimals, 12, " min");
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.m = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 60) {
|
||||
return kbn.toFixed(size, decimals) + " min";
|
||||
}
|
||||
else if (Math.abs(size) < 1440) {
|
||||
return kbn.toFixedScaled(size / 60, decimals, scaledDecimals, 2, " hour");
|
||||
}
|
||||
else if (Math.abs(size) < 10080) {
|
||||
return kbn.toFixedScaled(size / 1440, decimals, scaledDecimals, 3, " day");
|
||||
}
|
||||
else if (Math.abs(size) < 604800) {
|
||||
return kbn.toFixedScaled(size / 10080, decimals, scaledDecimals, 4, " week");
|
||||
}
|
||||
else {
|
||||
return kbn.toFixedScaled(size / 5.25948e5, decimals, scaledDecimals, 5, " year");
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.h = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 24) {
|
||||
return kbn.toFixed(size, decimals) + " hour";
|
||||
}
|
||||
else if (Math.abs(size) < 168) {
|
||||
return kbn.toFixedScaled(size / 24, decimals, scaledDecimals, 2, " day");
|
||||
}
|
||||
else if (Math.abs(size) < 8760) {
|
||||
return kbn.toFixedScaled(size / 168, decimals, scaledDecimals, 3, " week");
|
||||
}
|
||||
else {
|
||||
return kbn.toFixedScaled(size / 8760, decimals, scaledDecimals, 4, " year");
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.d = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) { return ""; }
|
||||
|
||||
if (Math.abs(size) < 7) {
|
||||
return kbn.toFixed(size, decimals) + " day";
|
||||
}
|
||||
else if (Math.abs(size) < 365) {
|
||||
return kbn.toFixedScaled(size / 7, decimals, scaledDecimals, 2, " week");
|
||||
}
|
||||
else {
|
||||
return kbn.toFixedScaled(size / 365, decimals, scaledDecimals, 3, " year");
|
||||
}
|
||||
};
|
||||
|
||||
kbn.toDuration = function(size, decimals, timeScale) {
|
||||
if (size === null) { return ""; }
|
||||
if (size === 0) { return "0 " + timeScale + "s"; }
|
||||
if (size < 0) { return kbn.toDuration(-size, decimals, timeScale) + " ago"; }
|
||||
|
||||
var units = [
|
||||
{short: "y", long: "year"},
|
||||
{short: "M", long: "month"},
|
||||
{short: "w", long: "week"},
|
||||
{short: "d", long: "day"},
|
||||
{short: "h", long: "hour"},
|
||||
{short: "m", long: "minute"},
|
||||
{short: "s", long: "second"},
|
||||
{short: "ms", long: "millisecond"}
|
||||
];
|
||||
// convert $size to milliseconds
|
||||
// intervals_in_seconds uses seconds (duh), convert them to milliseconds here to minimize floating point errors
|
||||
size *= kbn.intervals_in_seconds[units.find(function(e) { return e.long === timeScale; }).short] * 1000;
|
||||
|
||||
var string = [];
|
||||
// after first value >= 1 print only $decimals more
|
||||
var decrementDecimals = false;
|
||||
for (var i = 0; i < units.length && decimals >= 0; i++) {
|
||||
var interval = kbn.intervals_in_seconds[units[i].short] * 1000;
|
||||
var value = size / interval;
|
||||
if (value >= 1 || decrementDecimals) {
|
||||
decrementDecimals = true;
|
||||
var floor = Math.floor(value);
|
||||
var unit = units[i].long + (floor !== 1 ? "s" : "");
|
||||
string.push(floor + " " + unit);
|
||||
size = size % interval;
|
||||
decimals--;
|
||||
}
|
||||
}
|
||||
|
||||
return string.join(", ");
|
||||
};
|
||||
|
||||
kbn.valueFormats.dtdurationms = function(size, decimals) {
|
||||
return kbn.toDuration(size, decimals, 'millisecond');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dtdurations = function(size, decimals) {
|
||||
return kbn.toDuration(size, decimals, 'second');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeAsIso = function(epoch) {
|
||||
var time = moment(epoch);
|
||||
|
||||
if (moment().isSame(epoch, 'day')) {
|
||||
return time.format('HH:mm:ss');
|
||||
}
|
||||
return time.format('YYYY-MM-DD HH:mm:ss');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeAsUS = function(epoch) {
|
||||
var time = moment(epoch);
|
||||
|
||||
if (moment().isSame(epoch, 'day')) {
|
||||
return time.format('h:mm:ss a');
|
||||
}
|
||||
return time.format('MM/DD/YYYY h:mm:ss a');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeFromNow = function(epoch) {
|
||||
return moment(epoch).fromNow();
|
||||
};
|
||||
|
||||
///// FORMAT MENU /////
|
||||
|
||||
kbn.getUnitFormats = function() {
|
||||
return [
|
||||
{
|
||||
text: 'none',
|
||||
submenu: [
|
||||
{text: 'none' , value: 'none' },
|
||||
{text: 'short', value: 'short' },
|
||||
{text: 'percent (0-100)', value: 'percent' },
|
||||
{text: 'percent (0.0-1.0)', value: 'percentunit'},
|
||||
{text: 'Humidity (%H)', value: 'humidity' },
|
||||
{text: 'ppm', value: 'ppm' },
|
||||
{text: 'decibel', value: 'dB' },
|
||||
{text: 'hexadecimal (0x)', value: 'hex0x' },
|
||||
{text: 'hexadecimal', value: 'hex' },
|
||||
{text: 'scientific notation', value: 'sci' },
|
||||
{text: 'locale format', value: 'locale' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'currency',
|
||||
submenu: [
|
||||
{text: 'Dollars ($)', value: 'currencyUSD'},
|
||||
{text: 'Pounds (£)', value: 'currencyGBP'},
|
||||
{text: 'Euro (€)', value: 'currencyEUR'},
|
||||
{text: 'Yen (¥)', value: 'currencyJPY'},
|
||||
{text: 'Rubles (₽)', value: 'currencyRUB'},
|
||||
{text: 'Hryvnias (₴)', value: 'currencyUAH'},
|
||||
{text: 'Real (R$)', value: 'currencyBRL'},
|
||||
{text: 'Danish Krone (kr)', value: 'currencyDKK'},
|
||||
{text: 'Icelandic Krone (kr)', value: 'currencyISK'},
|
||||
{text: 'Norwegian Krone (kr)', value: 'currencyNOK'},
|
||||
{text: 'Swedish Krone (kr)', value: 'currencySEK'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'time',
|
||||
submenu: [
|
||||
{text: 'Hertz (1/s)', value: 'hertz'},
|
||||
{text: 'nanoseconds (ns)' , value: 'ns' },
|
||||
{text: 'microseconds (µs)', value: 'µs' },
|
||||
{text: 'milliseconds (ms)', value: 'ms' },
|
||||
{text: 'seconds (s)', value: 's' },
|
||||
{text: 'minutes (m)', value: 'm' },
|
||||
{text: 'hours (h)', value: 'h' },
|
||||
{text: 'days (d)', value: 'd' },
|
||||
{text: 'duration (ms)', value: 'dtdurationms' },
|
||||
{text: 'duration (s)', value: 'dtdurations' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'date & time',
|
||||
submenu: [
|
||||
{text: 'YYYY-MM-DD HH:mm:ss', value: 'dateTimeAsIso' },
|
||||
{text: 'DD/MM/YYYY h:mm:ss a', value: 'dateTimeAsUS' },
|
||||
{text: 'From Now', value: 'dateTimeFromNow' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'data (IEC)',
|
||||
submenu: [
|
||||
{text: 'bits', value: 'bits' },
|
||||
{text: 'bytes', value: 'bytes' },
|
||||
{text: 'kibibytes', value: 'kbytes'},
|
||||
{text: 'mebibytes', value: 'mbytes'},
|
||||
{text: 'gibibytes', value: 'gbytes'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'data (Metric)',
|
||||
submenu: [
|
||||
{text: 'bits', value: 'decbits' },
|
||||
{text: 'bytes', value: 'decbytes' },
|
||||
{text: 'kilobytes', value: 'deckbytes'},
|
||||
{text: 'megabytes', value: 'decmbytes'},
|
||||
{text: 'gigabytes', value: 'decgbytes'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'data rate',
|
||||
submenu: [
|
||||
{text: 'packets/sec', value: 'pps'},
|
||||
{text: 'bits/sec', value: 'bps'},
|
||||
{text: 'bytes/sec', value: 'Bps'},
|
||||
{text: 'kilobits/sec', value: 'Kbits'},
|
||||
{text: 'kilobytes/sec', value: 'KBs'},
|
||||
{text: 'megabits/sec', value: 'Mbits'},
|
||||
{text: 'megabytes/sec', value: 'MBs'},
|
||||
{text: 'gigabytes/sec', value: 'GBs'},
|
||||
{text: 'gigabits/sec', value: 'Gbits'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'throughput',
|
||||
submenu: [
|
||||
{text: 'ops/sec (ops)', value: 'ops' },
|
||||
{text: 'reads/sec (rps)', value: 'rps' },
|
||||
{text: 'writes/sec (wps)', value: 'wps' },
|
||||
{text: 'I/O ops/sec (iops)', value: 'iops'},
|
||||
{text: 'ops/min (opm)', value: 'opm' },
|
||||
{text: 'reads/min (rpm)', value: 'rpm' },
|
||||
{text: 'writes/min (wpm)', value: 'wpm' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'length',
|
||||
submenu: [
|
||||
{text: 'millimetre (mm)', value: 'lengthmm'},
|
||||
{text: 'meter (m)', value: 'lengthm' },
|
||||
{text: 'kilometer (km)', value: 'lengthkm'},
|
||||
{text: 'mile (mi)', value: 'lengthmi'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'mass',
|
||||
submenu: [
|
||||
{text: 'milligram (mg)', value: 'massmg'},
|
||||
{text: 'gram (g)', value: 'massg' },
|
||||
{text: 'kilogram (kg)', value: 'masskg'},
|
||||
{text: 'metric ton (t)', value: 'masst' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'velocity',
|
||||
submenu: [
|
||||
{text: 'm/s', value: 'velocityms' },
|
||||
{text: 'km/h', value: 'velocitykmh' },
|
||||
{text: 'mph', value: 'velocitymph' },
|
||||
{text: 'knot (kn)', value: 'velocityknot'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'volume',
|
||||
submenu: [
|
||||
{text: 'millilitre', value: 'mlitre' },
|
||||
{text: 'litre', value: 'litre' },
|
||||
{text: 'cubic metre', value: 'm3' },
|
||||
{text: 'cubic decimetre', value: 'dm3' },
|
||||
{text: 'gallons', value: 'gallons'},
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'energy',
|
||||
submenu: [
|
||||
{text: 'watt (W)', value: 'watt' },
|
||||
{text: 'kilowatt (kW)', value: 'kwatt' },
|
||||
{text: 'volt-ampere (VA)', value: 'voltamp' },
|
||||
{text: 'kilovolt-ampere (kVA)', value: 'kvoltamp' },
|
||||
{text: 'volt-ampere reactive (var)', value: 'voltampreact'},
|
||||
{text: 'kilovolt-ampere reactive (kvar)', value: 'kvoltampreact'},
|
||||
{text: 'watt-hour (Wh)', value: 'watth' },
|
||||
{text: 'kilowatt-hour (kWh)', value: 'kwatth' },
|
||||
{text: 'joule (J)', value: 'joule' },
|
||||
{text: 'electron volt (eV)', value: 'ev' },
|
||||
{text: 'Ampere (A)', value: 'amp' },
|
||||
{text: 'Kiloampere (kA)', value: 'kamp' },
|
||||
{text: 'Volt (V)', value: 'volt' },
|
||||
{text: 'Kilovolt (kV)', value: 'kvolt' },
|
||||
{text: 'Decibel-milliwatt (dBm)', value: 'dBm' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'temperature',
|
||||
submenu: [
|
||||
{text: 'Celsius (°C)', value: 'celsius' },
|
||||
{text: 'Farenheit (°F)', value: 'farenheit' },
|
||||
{text: 'Kelvin (K)', value: 'kelvin' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'pressure',
|
||||
submenu: [
|
||||
{text: 'Millibars', value: 'pressurembar'},
|
||||
{text: 'Bars', value: 'pressurebar' },
|
||||
{text: 'Kilobars', value: 'pressurekbar'},
|
||||
{text: 'Hectopascals', value: 'pressurehpa' },
|
||||
{text: 'Inches of mercury', value: 'pressurehg' },
|
||||
{text: 'PSI', value: 'pressurepsi' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'force',
|
||||
submenu: [
|
||||
{text: 'Newton-meters (Nm)', value: 'forceNm' },
|
||||
{text: 'Kilonewton-meters (kNm)', value: 'forcekNm' },
|
||||
{text: 'Newtons (N)', value: 'forceN' },
|
||||
{text: 'Kilonewtons (kN)', value: 'forcekN' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'flow',
|
||||
submenu: [
|
||||
{text: 'Gallons/min (gpm)', value: 'flowgpm' },
|
||||
{text: 'Cubic meters/sec (cms)', value: 'flowcms' },
|
||||
{text: 'Cubic feet/sec (cfs)', value: 'flowcfs' },
|
||||
{text: 'Cubic feet/min (cfm)', value: 'flowcfm' },
|
||||
]
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
return kbn;
|
||||
});
|
968
public/app/core/utils/kbn.ts
Normal file
968
public/app/core/utils/kbn.ts
Normal file
@ -0,0 +1,968 @@
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
var kbn: any = {};
|
||||
|
||||
kbn.valueFormats = {};
|
||||
|
||||
kbn.regexEscape = function(value) {
|
||||
return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
|
||||
};
|
||||
|
||||
///// HELPER FUNCTIONS /////
|
||||
|
||||
kbn.round_interval = function(interval) {
|
||||
switch (true) {
|
||||
// 0.015s
|
||||
case interval < 15:
|
||||
return 10; // 0.01s
|
||||
// 0.035s
|
||||
case interval < 35:
|
||||
return 20; // 0.02s
|
||||
// 0.075s
|
||||
case interval < 75:
|
||||
return 50; // 0.05s
|
||||
// 0.15s
|
||||
case interval < 150:
|
||||
return 100; // 0.1s
|
||||
// 0.35s
|
||||
case interval < 350:
|
||||
return 200; // 0.2s
|
||||
// 0.75s
|
||||
case interval < 750:
|
||||
return 500; // 0.5s
|
||||
// 1.5s
|
||||
case interval < 1500:
|
||||
return 1000; // 1s
|
||||
// 3.5s
|
||||
case interval < 3500:
|
||||
return 2000; // 2s
|
||||
// 7.5s
|
||||
case interval < 7500:
|
||||
return 5000; // 5s
|
||||
// 12.5s
|
||||
case interval < 12500:
|
||||
return 10000; // 10s
|
||||
// 17.5s
|
||||
case interval < 17500:
|
||||
return 15000; // 15s
|
||||
// 25s
|
||||
case interval < 25000:
|
||||
return 20000; // 20s
|
||||
// 45s
|
||||
case interval < 45000:
|
||||
return 30000; // 30s
|
||||
// 1.5m
|
||||
case interval < 90000:
|
||||
return 60000; // 1m
|
||||
// 3.5m
|
||||
case interval < 210000:
|
||||
return 120000; // 2m
|
||||
// 7.5m
|
||||
case interval < 450000:
|
||||
return 300000; // 5m
|
||||
// 12.5m
|
||||
case interval < 750000:
|
||||
return 600000; // 10m
|
||||
// 12.5m
|
||||
case interval < 1050000:
|
||||
return 900000; // 15m
|
||||
// 25m
|
||||
case interval < 1500000:
|
||||
return 1200000; // 20m
|
||||
// 45m
|
||||
case interval < 2700000:
|
||||
return 1800000; // 30m
|
||||
// 1.5h
|
||||
case interval < 5400000:
|
||||
return 3600000; // 1h
|
||||
// 2.5h
|
||||
case interval < 9000000:
|
||||
return 7200000; // 2h
|
||||
// 4.5h
|
||||
case interval < 16200000:
|
||||
return 10800000; // 3h
|
||||
// 9h
|
||||
case interval < 32400000:
|
||||
return 21600000; // 6h
|
||||
// 1d
|
||||
case interval < 86400000:
|
||||
return 43200000; // 12h
|
||||
// 1w
|
||||
case interval < 604800000:
|
||||
return 86400000; // 1d
|
||||
// 3w
|
||||
case interval < 1814400000:
|
||||
return 604800000; // 1w
|
||||
// 6w
|
||||
case interval < 3628800000:
|
||||
return 2592000000; // 30d
|
||||
default:
|
||||
return 31536000000; // 1y
|
||||
}
|
||||
};
|
||||
|
||||
kbn.secondsToHms = function(seconds) {
|
||||
var numyears = Math.floor(seconds / 31536000);
|
||||
if (numyears) {
|
||||
return numyears + 'y';
|
||||
}
|
||||
var numdays = Math.floor((seconds % 31536000) / 86400);
|
||||
if (numdays) {
|
||||
return numdays + 'd';
|
||||
}
|
||||
var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
|
||||
if (numhours) {
|
||||
return numhours + 'h';
|
||||
}
|
||||
var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
|
||||
if (numminutes) {
|
||||
return numminutes + 'm';
|
||||
}
|
||||
var numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);
|
||||
if (numseconds) {
|
||||
return numseconds + 's';
|
||||
}
|
||||
var nummilliseconds = Math.floor(seconds * 1000.0);
|
||||
if (nummilliseconds) {
|
||||
return nummilliseconds + 'ms';
|
||||
}
|
||||
|
||||
return 'less than a millisecond'; //'just now' //or other string you like;
|
||||
};
|
||||
|
||||
kbn.to_percent = function(nr, outof) {
|
||||
return Math.floor(nr / outof * 10000) / 100 + '%';
|
||||
};
|
||||
|
||||
kbn.addslashes = function(str) {
|
||||
str = str.replace(/\\/g, '\\\\');
|
||||
str = str.replace(/\'/g, "\\'");
|
||||
str = str.replace(/\"/g, '\\"');
|
||||
str = str.replace(/\0/g, '\\0');
|
||||
return str;
|
||||
};
|
||||
|
||||
kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/;
|
||||
|
||||
// histogram & trends
|
||||
kbn.intervals_in_seconds = {
|
||||
y: 31536000,
|
||||
M: 2592000,
|
||||
w: 604800,
|
||||
d: 86400,
|
||||
h: 3600,
|
||||
m: 60,
|
||||
s: 1,
|
||||
ms: 0.001,
|
||||
};
|
||||
|
||||
kbn.calculateInterval = function(range, resolution, lowLimitInterval) {
|
||||
var lowLimitMs = 1; // 1 millisecond default low limit
|
||||
var intervalMs;
|
||||
|
||||
if (lowLimitInterval) {
|
||||
if (lowLimitInterval[0] === '>') {
|
||||
lowLimitInterval = lowLimitInterval.slice(1);
|
||||
}
|
||||
lowLimitMs = kbn.interval_to_ms(lowLimitInterval);
|
||||
}
|
||||
|
||||
intervalMs = kbn.round_interval((range.to.valueOf() - range.from.valueOf()) / resolution);
|
||||
if (lowLimitMs > intervalMs) {
|
||||
intervalMs = lowLimitMs;
|
||||
}
|
||||
|
||||
return {
|
||||
intervalMs: intervalMs,
|
||||
interval: kbn.secondsToHms(intervalMs / 1000),
|
||||
};
|
||||
};
|
||||
|
||||
kbn.describe_interval = function(str) {
|
||||
var matches = str.match(kbn.interval_regex);
|
||||
if (!matches || !_.has(kbn.intervals_in_seconds, matches[2])) {
|
||||
throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"');
|
||||
} else {
|
||||
return {
|
||||
sec: kbn.intervals_in_seconds[matches[2]],
|
||||
type: matches[2],
|
||||
count: parseInt(matches[1], 10),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
kbn.interval_to_ms = function(str) {
|
||||
var info = kbn.describe_interval(str);
|
||||
return info.sec * 1000 * info.count;
|
||||
};
|
||||
|
||||
kbn.interval_to_seconds = function(str) {
|
||||
var info = kbn.describe_interval(str);
|
||||
return info.sec * info.count;
|
||||
};
|
||||
|
||||
kbn.query_color_dot = function(color, diameter) {
|
||||
return (
|
||||
'<div class="icon-circle" style="' +
|
||||
['display:inline-block', 'color:' + color, 'font-size:' + diameter + 'px'].join(';') +
|
||||
'"></div>'
|
||||
);
|
||||
};
|
||||
|
||||
kbn.slugifyForUrl = function(str) {
|
||||
return str
|
||||
.toLowerCase()
|
||||
.replace(/[^\w ]+/g, '')
|
||||
.replace(/ +/g, '-');
|
||||
};
|
||||
|
||||
kbn.stringToJsRegex = function(str) {
|
||||
if (str[0] !== '/') {
|
||||
return new RegExp('^' + str + '$');
|
||||
}
|
||||
|
||||
var match = str.match(new RegExp('^/(.*?)/(g?i?m?y?)$'));
|
||||
return new RegExp(match[1], match[2]);
|
||||
};
|
||||
|
||||
kbn.toFixed = function(value, decimals) {
|
||||
if (value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1;
|
||||
var formatted = String(Math.round(value * factor) / factor);
|
||||
|
||||
// if exponent return directly
|
||||
if (formatted.indexOf('e') !== -1 || value === 0) {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
// If tickDecimals was specified, ensure that we have exactly that
|
||||
// much precision; otherwise default to the value's own precision.
|
||||
if (decimals != null) {
|
||||
var decimalPos = formatted.indexOf('.');
|
||||
var precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1;
|
||||
if (precision < decimals) {
|
||||
return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision);
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
};
|
||||
|
||||
kbn.toFixedScaled = function(value, decimals, scaledDecimals, additionalDecimals, ext) {
|
||||
if (scaledDecimals === null) {
|
||||
return kbn.toFixed(value, decimals) + ext;
|
||||
} else {
|
||||
return kbn.toFixed(value, scaledDecimals + additionalDecimals) + ext;
|
||||
}
|
||||
};
|
||||
|
||||
kbn.roundValue = function(num, decimals) {
|
||||
if (num === null) {
|
||||
return null;
|
||||
}
|
||||
var n = Math.pow(10, decimals);
|
||||
var formatted = (n * num).toFixed(decimals);
|
||||
return Math.round(parseFloat(formatted)) / n;
|
||||
};
|
||||
|
||||
///// FORMAT FUNCTION CONSTRUCTORS /////
|
||||
|
||||
kbn.formatBuilders = {};
|
||||
|
||||
// Formatter which always appends a fixed unit string to the value. No
|
||||
// scaling of the value is performed.
|
||||
kbn.formatBuilders.fixedUnit = function(unit) {
|
||||
return function(size, decimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
return kbn.toFixed(size, decimals) + ' ' + unit;
|
||||
};
|
||||
};
|
||||
|
||||
// Formatter which scales the unit string geometrically according to the given
|
||||
// numeric factor. Repeatedly scales the value down by the factor until it is
|
||||
// less than the factor in magnitude, or the end of the array is reached.
|
||||
kbn.formatBuilders.scaledUnits = function(factor, extArray) {
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var steps = 0;
|
||||
var limit = extArray.length;
|
||||
|
||||
while (Math.abs(size) >= factor) {
|
||||
steps++;
|
||||
size /= factor;
|
||||
|
||||
if (steps >= limit) {
|
||||
return 'NA';
|
||||
}
|
||||
}
|
||||
|
||||
if (steps > 0 && scaledDecimals !== null) {
|
||||
decimals = scaledDecimals + 3 * steps;
|
||||
}
|
||||
|
||||
return kbn.toFixed(size, decimals) + extArray[steps];
|
||||
};
|
||||
};
|
||||
|
||||
// Extension of the scaledUnits builder which uses SI decimal prefixes. If an
|
||||
// offset is given, it adjusts the starting units at the given prefix; a value
|
||||
// of 0 starts at no scale; -3 drops to nano, +2 starts at mega, etc.
|
||||
kbn.formatBuilders.decimalSIPrefix = function(unit, offset) {
|
||||
var prefixes = ['n', 'µ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
||||
prefixes = prefixes.slice(3 + (offset || 0));
|
||||
var units = prefixes.map(function(p) {
|
||||
return ' ' + p + unit;
|
||||
});
|
||||
return kbn.formatBuilders.scaledUnits(1000, units);
|
||||
};
|
||||
|
||||
// Extension of the scaledUnits builder which uses SI binary prefixes. If
|
||||
// offset is given, it starts the units at the given prefix; otherwise, the
|
||||
// offset defaults to zero and the initial unit is not prefixed.
|
||||
kbn.formatBuilders.binarySIPrefix = function(unit, offset) {
|
||||
var prefixes = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'].slice(offset);
|
||||
var units = prefixes.map(function(p) {
|
||||
return ' ' + p + unit;
|
||||
});
|
||||
return kbn.formatBuilders.scaledUnits(1024, units);
|
||||
};
|
||||
|
||||
// Currency formatter for prefixing a symbol onto a number. Supports scaling
|
||||
// up to the trillions.
|
||||
kbn.formatBuilders.currency = function(symbol) {
|
||||
var units = ['', 'K', 'M', 'B', 'T'];
|
||||
var scaler = kbn.formatBuilders.scaledUnits(1000, units);
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
var scaled = scaler(size, decimals, scaledDecimals);
|
||||
return symbol + scaled;
|
||||
};
|
||||
};
|
||||
|
||||
kbn.formatBuilders.simpleCountUnit = function(symbol) {
|
||||
var units = ['', 'K', 'M', 'B', 'T'];
|
||||
var scaler = kbn.formatBuilders.scaledUnits(1000, units);
|
||||
return function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
var scaled = scaler(size, decimals, scaledDecimals);
|
||||
return scaled + ' ' + symbol;
|
||||
};
|
||||
};
|
||||
|
||||
///// VALUE FORMATS /////
|
||||
|
||||
// Dimensionless Units
|
||||
kbn.valueFormats.none = kbn.toFixed;
|
||||
kbn.valueFormats.short = kbn.formatBuilders.scaledUnits(1000, [
|
||||
'',
|
||||
' K',
|
||||
' Mil',
|
||||
' Bil',
|
||||
' Tri',
|
||||
' Quadr',
|
||||
' Quint',
|
||||
' Sext',
|
||||
' Sept',
|
||||
]);
|
||||
kbn.valueFormats.dB = kbn.formatBuilders.fixedUnit('dB');
|
||||
kbn.valueFormats.ppm = kbn.formatBuilders.fixedUnit('ppm');
|
||||
|
||||
kbn.valueFormats.percent = function(size, decimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
return kbn.toFixed(size, decimals) + '%';
|
||||
};
|
||||
|
||||
kbn.valueFormats.percentunit = function(size, decimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
return kbn.toFixed(100 * size, decimals) + '%';
|
||||
};
|
||||
|
||||
/* Formats the value to hex. Uses float if specified decimals are not 0.
|
||||
* There are two options, one with 0x, and one without */
|
||||
|
||||
kbn.valueFormats.hex = function(value, decimals) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
return parseFloat(kbn.toFixed(value, decimals))
|
||||
.toString(16)
|
||||
.toUpperCase();
|
||||
};
|
||||
|
||||
kbn.valueFormats.hex0x = function(value, decimals) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
var hexString = kbn.valueFormats.hex(value, decimals);
|
||||
if (hexString.substring(0, 1) === '-') {
|
||||
return '-0x' + hexString.substring(1);
|
||||
}
|
||||
return '0x' + hexString;
|
||||
};
|
||||
|
||||
kbn.valueFormats.sci = function(value, decimals) {
|
||||
return value.toExponential(decimals);
|
||||
};
|
||||
|
||||
kbn.valueFormats.locale = function(value, decimals) {
|
||||
return value.toLocaleString(undefined, { maximumFractionDigits: decimals });
|
||||
};
|
||||
|
||||
// Currencies
|
||||
kbn.valueFormats.currencyUSD = kbn.formatBuilders.currency('$');
|
||||
kbn.valueFormats.currencyGBP = kbn.formatBuilders.currency('£');
|
||||
kbn.valueFormats.currencyEUR = kbn.formatBuilders.currency('€');
|
||||
kbn.valueFormats.currencyJPY = kbn.formatBuilders.currency('¥');
|
||||
kbn.valueFormats.currencyRUB = kbn.formatBuilders.currency('₽');
|
||||
kbn.valueFormats.currencyUAH = kbn.formatBuilders.currency('₴');
|
||||
kbn.valueFormats.currencyBRL = kbn.formatBuilders.currency('R$');
|
||||
kbn.valueFormats.currencyDKK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencyISK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencyNOK = kbn.formatBuilders.currency('kr');
|
||||
kbn.valueFormats.currencySEK = kbn.formatBuilders.currency('kr');
|
||||
|
||||
// Data (Binary)
|
||||
kbn.valueFormats.bits = kbn.formatBuilders.binarySIPrefix('b');
|
||||
kbn.valueFormats.bytes = kbn.formatBuilders.binarySIPrefix('B');
|
||||
kbn.valueFormats.kbytes = kbn.formatBuilders.binarySIPrefix('B', 1);
|
||||
kbn.valueFormats.mbytes = kbn.formatBuilders.binarySIPrefix('B', 2);
|
||||
kbn.valueFormats.gbytes = kbn.formatBuilders.binarySIPrefix('B', 3);
|
||||
|
||||
// Data (Decimal)
|
||||
kbn.valueFormats.decbits = kbn.formatBuilders.decimalSIPrefix('b');
|
||||
kbn.valueFormats.decbytes = kbn.formatBuilders.decimalSIPrefix('B');
|
||||
kbn.valueFormats.deckbytes = kbn.formatBuilders.decimalSIPrefix('B', 1);
|
||||
kbn.valueFormats.decmbytes = kbn.formatBuilders.decimalSIPrefix('B', 2);
|
||||
kbn.valueFormats.decgbytes = kbn.formatBuilders.decimalSIPrefix('B', 3);
|
||||
|
||||
// Data Rate
|
||||
kbn.valueFormats.pps = kbn.formatBuilders.decimalSIPrefix('pps');
|
||||
kbn.valueFormats.bps = kbn.formatBuilders.decimalSIPrefix('bps');
|
||||
kbn.valueFormats.Bps = kbn.formatBuilders.decimalSIPrefix('Bps');
|
||||
kbn.valueFormats.KBs = kbn.formatBuilders.decimalSIPrefix('Bs', 1);
|
||||
kbn.valueFormats.Kbits = kbn.formatBuilders.decimalSIPrefix('bps', 1);
|
||||
kbn.valueFormats.MBs = kbn.formatBuilders.decimalSIPrefix('Bs', 2);
|
||||
kbn.valueFormats.Mbits = kbn.formatBuilders.decimalSIPrefix('bps', 2);
|
||||
kbn.valueFormats.GBs = kbn.formatBuilders.decimalSIPrefix('Bs', 3);
|
||||
kbn.valueFormats.Gbits = kbn.formatBuilders.decimalSIPrefix('bps', 3);
|
||||
|
||||
// Throughput
|
||||
kbn.valueFormats.ops = kbn.formatBuilders.simpleCountUnit('ops');
|
||||
kbn.valueFormats.rps = kbn.formatBuilders.simpleCountUnit('rps');
|
||||
kbn.valueFormats.wps = kbn.formatBuilders.simpleCountUnit('wps');
|
||||
kbn.valueFormats.iops = kbn.formatBuilders.simpleCountUnit('iops');
|
||||
kbn.valueFormats.opm = kbn.formatBuilders.simpleCountUnit('opm');
|
||||
kbn.valueFormats.rpm = kbn.formatBuilders.simpleCountUnit('rpm');
|
||||
kbn.valueFormats.wpm = kbn.formatBuilders.simpleCountUnit('wpm');
|
||||
|
||||
// Energy
|
||||
kbn.valueFormats.watt = kbn.formatBuilders.decimalSIPrefix('W');
|
||||
kbn.valueFormats.kwatt = kbn.formatBuilders.decimalSIPrefix('W', 1);
|
||||
kbn.valueFormats.voltamp = kbn.formatBuilders.decimalSIPrefix('VA');
|
||||
kbn.valueFormats.kvoltamp = kbn.formatBuilders.decimalSIPrefix('VA', 1);
|
||||
kbn.valueFormats.voltampreact = kbn.formatBuilders.decimalSIPrefix('var');
|
||||
kbn.valueFormats.kvoltampreact = kbn.formatBuilders.decimalSIPrefix('var', 1);
|
||||
kbn.valueFormats.watth = kbn.formatBuilders.decimalSIPrefix('Wh');
|
||||
kbn.valueFormats.kwatth = kbn.formatBuilders.decimalSIPrefix('Wh', 1);
|
||||
kbn.valueFormats.joule = kbn.formatBuilders.decimalSIPrefix('J');
|
||||
kbn.valueFormats.ev = kbn.formatBuilders.decimalSIPrefix('eV');
|
||||
kbn.valueFormats.amp = kbn.formatBuilders.decimalSIPrefix('A');
|
||||
kbn.valueFormats.kamp = kbn.formatBuilders.decimalSIPrefix('A', 1);
|
||||
kbn.valueFormats.volt = kbn.formatBuilders.decimalSIPrefix('V');
|
||||
kbn.valueFormats.kvolt = kbn.formatBuilders.decimalSIPrefix('V', 1);
|
||||
kbn.valueFormats.dBm = kbn.formatBuilders.decimalSIPrefix('dBm');
|
||||
|
||||
// Temperature
|
||||
kbn.valueFormats.celsius = kbn.formatBuilders.fixedUnit('°C');
|
||||
kbn.valueFormats.farenheit = kbn.formatBuilders.fixedUnit('°F');
|
||||
kbn.valueFormats.kelvin = kbn.formatBuilders.fixedUnit('K');
|
||||
kbn.valueFormats.humidity = kbn.formatBuilders.fixedUnit('%H');
|
||||
|
||||
// Pressure
|
||||
kbn.valueFormats.pressurebar = kbn.formatBuilders.decimalSIPrefix('bar');
|
||||
kbn.valueFormats.pressurembar = kbn.formatBuilders.decimalSIPrefix('bar', -1);
|
||||
kbn.valueFormats.pressurekbar = kbn.formatBuilders.decimalSIPrefix('bar', 1);
|
||||
kbn.valueFormats.pressurehpa = kbn.formatBuilders.fixedUnit('hPa');
|
||||
kbn.valueFormats.pressurehg = kbn.formatBuilders.fixedUnit('"Hg');
|
||||
kbn.valueFormats.pressurepsi = kbn.formatBuilders.scaledUnits(1000, [' psi', ' ksi', ' Mpsi']);
|
||||
|
||||
// Force
|
||||
kbn.valueFormats.forceNm = kbn.formatBuilders.decimalSIPrefix('Nm');
|
||||
kbn.valueFormats.forcekNm = kbn.formatBuilders.decimalSIPrefix('Nm', 1);
|
||||
kbn.valueFormats.forceN = kbn.formatBuilders.decimalSIPrefix('N');
|
||||
kbn.valueFormats.forcekN = kbn.formatBuilders.decimalSIPrefix('N', 1);
|
||||
|
||||
// Length
|
||||
kbn.valueFormats.lengthm = kbn.formatBuilders.decimalSIPrefix('m');
|
||||
kbn.valueFormats.lengthmm = kbn.formatBuilders.decimalSIPrefix('m', -1);
|
||||
kbn.valueFormats.lengthkm = kbn.formatBuilders.decimalSIPrefix('m', 1);
|
||||
kbn.valueFormats.lengthmi = kbn.formatBuilders.fixedUnit('mi');
|
||||
|
||||
// Mass
|
||||
kbn.valueFormats.massmg = kbn.formatBuilders.decimalSIPrefix('g', -1);
|
||||
kbn.valueFormats.massg = kbn.formatBuilders.decimalSIPrefix('g');
|
||||
kbn.valueFormats.masskg = kbn.formatBuilders.decimalSIPrefix('g', 1);
|
||||
kbn.valueFormats.masst = kbn.formatBuilders.fixedUnit('t');
|
||||
|
||||
// Velocity
|
||||
kbn.valueFormats.velocityms = kbn.formatBuilders.fixedUnit('m/s');
|
||||
kbn.valueFormats.velocitykmh = kbn.formatBuilders.fixedUnit('km/h');
|
||||
kbn.valueFormats.velocitymph = kbn.formatBuilders.fixedUnit('mph');
|
||||
kbn.valueFormats.velocityknot = kbn.formatBuilders.fixedUnit('kn');
|
||||
|
||||
// Volume
|
||||
kbn.valueFormats.litre = kbn.formatBuilders.decimalSIPrefix('L');
|
||||
kbn.valueFormats.mlitre = kbn.formatBuilders.decimalSIPrefix('L', -1);
|
||||
kbn.valueFormats.m3 = kbn.formatBuilders.decimalSIPrefix('m3');
|
||||
kbn.valueFormats.dm3 = kbn.formatBuilders.decimalSIPrefix('dm3');
|
||||
kbn.valueFormats.gallons = kbn.formatBuilders.fixedUnit('gal');
|
||||
|
||||
// Flow
|
||||
kbn.valueFormats.flowgpm = kbn.formatBuilders.fixedUnit('gpm');
|
||||
kbn.valueFormats.flowcms = kbn.formatBuilders.fixedUnit('cms');
|
||||
kbn.valueFormats.flowcfs = kbn.formatBuilders.fixedUnit('cfs');
|
||||
kbn.valueFormats.flowcfm = kbn.formatBuilders.fixedUnit('cfm');
|
||||
|
||||
// Time
|
||||
kbn.valueFormats.hertz = kbn.formatBuilders.decimalSIPrefix('Hz');
|
||||
|
||||
kbn.valueFormats.ms = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + ' ms';
|
||||
} else if (Math.abs(size) < 60000) {
|
||||
// Less than 1 min
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' s');
|
||||
} else if (Math.abs(size) < 3600000) {
|
||||
// Less than 1 hour, devide in minutes
|
||||
return kbn.toFixedScaled(size / 60000, decimals, scaledDecimals, 5, ' min');
|
||||
} else if (Math.abs(size) < 86400000) {
|
||||
// Less than one day, devide in hours
|
||||
return kbn.toFixedScaled(size / 3600000, decimals, scaledDecimals, 7, ' hour');
|
||||
} else if (Math.abs(size) < 31536000000) {
|
||||
// Less than one year, devide in days
|
||||
return kbn.toFixedScaled(size / 86400000, decimals, scaledDecimals, 8, ' day');
|
||||
}
|
||||
|
||||
return kbn.toFixedScaled(size / 31536000000, decimals, scaledDecimals, 10, ' year');
|
||||
};
|
||||
|
||||
kbn.valueFormats.s = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Less than 1 µs, devide in ns
|
||||
if (Math.abs(size) < 0.000001) {
|
||||
return kbn.toFixedScaled(size * 1e9, decimals, scaledDecimals - decimals, -9, ' ns');
|
||||
}
|
||||
// Less than 1 ms, devide in µs
|
||||
if (Math.abs(size) < 0.001) {
|
||||
return kbn.toFixedScaled(size * 1e6, decimals, scaledDecimals - decimals, -6, ' µs');
|
||||
}
|
||||
// Less than 1 second, devide in ms
|
||||
if (Math.abs(size) < 1) {
|
||||
return kbn.toFixedScaled(size * 1e3, decimals, scaledDecimals - decimals, -3, ' ms');
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 60) {
|
||||
return kbn.toFixed(size, decimals) + ' s';
|
||||
} else if (Math.abs(size) < 3600) {
|
||||
// Less than 1 hour, devide in minutes
|
||||
return kbn.toFixedScaled(size / 60, decimals, scaledDecimals, 1, ' min');
|
||||
} else if (Math.abs(size) < 86400) {
|
||||
// Less than one day, devide in hours
|
||||
return kbn.toFixedScaled(size / 3600, decimals, scaledDecimals, 4, ' hour');
|
||||
} else if (Math.abs(size) < 604800) {
|
||||
// Less than one week, devide in days
|
||||
return kbn.toFixedScaled(size / 86400, decimals, scaledDecimals, 5, ' day');
|
||||
} else if (Math.abs(size) < 31536000) {
|
||||
// Less than one year, devide in week
|
||||
return kbn.toFixedScaled(size / 604800, decimals, scaledDecimals, 6, ' week');
|
||||
}
|
||||
|
||||
return kbn.toFixedScaled(size / 3.15569e7, decimals, scaledDecimals, 7, ' year');
|
||||
};
|
||||
|
||||
kbn.valueFormats['µs'] = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + ' µs';
|
||||
} else if (Math.abs(size) < 1000000) {
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' ms');
|
||||
} else {
|
||||
return kbn.toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, ' s');
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.ns = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 1000) {
|
||||
return kbn.toFixed(size, decimals) + ' ns';
|
||||
} else if (Math.abs(size) < 1000000) {
|
||||
return kbn.toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' µs');
|
||||
} else if (Math.abs(size) < 1000000000) {
|
||||
return kbn.toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, ' ms');
|
||||
} else if (Math.abs(size) < 60000000000) {
|
||||
return kbn.toFixedScaled(size / 1000000000, decimals, scaledDecimals, 9, ' s');
|
||||
} else {
|
||||
return kbn.toFixedScaled(size / 60000000000, decimals, scaledDecimals, 12, ' min');
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.m = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 60) {
|
||||
return kbn.toFixed(size, decimals) + ' min';
|
||||
} else if (Math.abs(size) < 1440) {
|
||||
return kbn.toFixedScaled(size / 60, decimals, scaledDecimals, 2, ' hour');
|
||||
} else if (Math.abs(size) < 10080) {
|
||||
return kbn.toFixedScaled(size / 1440, decimals, scaledDecimals, 3, ' day');
|
||||
} else if (Math.abs(size) < 604800) {
|
||||
return kbn.toFixedScaled(size / 10080, decimals, scaledDecimals, 4, ' week');
|
||||
} else {
|
||||
return kbn.toFixedScaled(size / 5.25948e5, decimals, scaledDecimals, 5, ' year');
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.h = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 24) {
|
||||
return kbn.toFixed(size, decimals) + ' hour';
|
||||
} else if (Math.abs(size) < 168) {
|
||||
return kbn.toFixedScaled(size / 24, decimals, scaledDecimals, 2, ' day');
|
||||
} else if (Math.abs(size) < 8760) {
|
||||
return kbn.toFixedScaled(size / 168, decimals, scaledDecimals, 3, ' week');
|
||||
} else {
|
||||
return kbn.toFixedScaled(size / 8760, decimals, scaledDecimals, 4, ' year');
|
||||
}
|
||||
};
|
||||
|
||||
kbn.valueFormats.d = function(size, decimals, scaledDecimals) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 7) {
|
||||
return kbn.toFixed(size, decimals) + ' day';
|
||||
} else if (Math.abs(size) < 365) {
|
||||
return kbn.toFixedScaled(size / 7, decimals, scaledDecimals, 2, ' week');
|
||||
} else {
|
||||
return kbn.toFixedScaled(size / 365, decimals, scaledDecimals, 3, ' year');
|
||||
}
|
||||
};
|
||||
|
||||
kbn.toDuration = function(size, decimals, timeScale) {
|
||||
if (size === null) {
|
||||
return '';
|
||||
}
|
||||
if (size === 0) {
|
||||
return '0 ' + timeScale + 's';
|
||||
}
|
||||
if (size < 0) {
|
||||
return kbn.toDuration(-size, decimals, timeScale) + ' ago';
|
||||
}
|
||||
|
||||
var units = [
|
||||
{ short: 'y', long: 'year' },
|
||||
{ short: 'M', long: 'month' },
|
||||
{ short: 'w', long: 'week' },
|
||||
{ short: 'd', long: 'day' },
|
||||
{ short: 'h', long: 'hour' },
|
||||
{ short: 'm', long: 'minute' },
|
||||
{ short: 's', long: 'second' },
|
||||
{ short: 'ms', long: 'millisecond' },
|
||||
];
|
||||
// convert $size to milliseconds
|
||||
// intervals_in_seconds uses seconds (duh), convert them to milliseconds here to minimize floating point errors
|
||||
size *=
|
||||
kbn.intervals_in_seconds[
|
||||
units.find(function(e) {
|
||||
return e.long === timeScale;
|
||||
}).short
|
||||
] * 1000;
|
||||
|
||||
var strings = [];
|
||||
// after first value >= 1 print only $decimals more
|
||||
var decrementDecimals = false;
|
||||
for (var i = 0; i < units.length && decimals >= 0; i++) {
|
||||
var interval = kbn.intervals_in_seconds[units[i].short] * 1000;
|
||||
var value = size / interval;
|
||||
if (value >= 1 || decrementDecimals) {
|
||||
decrementDecimals = true;
|
||||
var floor = Math.floor(value);
|
||||
var unit = units[i].long + (floor !== 1 ? 's' : '');
|
||||
strings.push(floor + ' ' + unit);
|
||||
size = size % interval;
|
||||
decimals--;
|
||||
}
|
||||
}
|
||||
|
||||
return strings.join(', ');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dtdurationms = function(size, decimals) {
|
||||
return kbn.toDuration(size, decimals, 'millisecond');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dtdurations = function(size, decimals) {
|
||||
return kbn.toDuration(size, decimals, 'second');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeAsIso = function(epoch) {
|
||||
var time = moment(epoch);
|
||||
|
||||
if (moment().isSame(epoch, 'day')) {
|
||||
return time.format('HH:mm:ss');
|
||||
}
|
||||
return time.format('YYYY-MM-DD HH:mm:ss');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeAsUS = function(epoch) {
|
||||
var time = moment(epoch);
|
||||
|
||||
if (moment().isSame(epoch, 'day')) {
|
||||
return time.format('h:mm:ss a');
|
||||
}
|
||||
return time.format('MM/DD/YYYY h:mm:ss a');
|
||||
};
|
||||
|
||||
kbn.valueFormats.dateTimeFromNow = function(epoch) {
|
||||
return moment(epoch).fromNow();
|
||||
};
|
||||
|
||||
///// FORMAT MENU /////
|
||||
|
||||
kbn.getUnitFormats = function() {
|
||||
return [
|
||||
{
|
||||
text: 'none',
|
||||
submenu: [
|
||||
{ text: 'none', value: 'none' },
|
||||
{ text: 'short', value: 'short' },
|
||||
{ text: 'percent (0-100)', value: 'percent' },
|
||||
{ text: 'percent (0.0-1.0)', value: 'percentunit' },
|
||||
{ text: 'Humidity (%H)', value: 'humidity' },
|
||||
{ text: 'ppm', value: 'ppm' },
|
||||
{ text: 'decibel', value: 'dB' },
|
||||
{ text: 'hexadecimal (0x)', value: 'hex0x' },
|
||||
{ text: 'hexadecimal', value: 'hex' },
|
||||
{ text: 'scientific notation', value: 'sci' },
|
||||
{ text: 'locale format', value: 'locale' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'currency',
|
||||
submenu: [
|
||||
{ text: 'Dollars ($)', value: 'currencyUSD' },
|
||||
{ text: 'Pounds (£)', value: 'currencyGBP' },
|
||||
{ text: 'Euro (€)', value: 'currencyEUR' },
|
||||
{ text: 'Yen (¥)', value: 'currencyJPY' },
|
||||
{ text: 'Rubles (₽)', value: 'currencyRUB' },
|
||||
{ text: 'Hryvnias (₴)', value: 'currencyUAH' },
|
||||
{ text: 'Real (R$)', value: 'currencyBRL' },
|
||||
{ text: 'Danish Krone (kr)', value: 'currencyDKK' },
|
||||
{ text: 'Icelandic Krone (kr)', value: 'currencyISK' },
|
||||
{ text: 'Norwegian Krone (kr)', value: 'currencyNOK' },
|
||||
{ text: 'Swedish Krone (kr)', value: 'currencySEK' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'time',
|
||||
submenu: [
|
||||
{ text: 'Hertz (1/s)', value: 'hertz' },
|
||||
{ text: 'nanoseconds (ns)', value: 'ns' },
|
||||
{ text: 'microseconds (µs)', value: 'µs' },
|
||||
{ text: 'milliseconds (ms)', value: 'ms' },
|
||||
{ text: 'seconds (s)', value: 's' },
|
||||
{ text: 'minutes (m)', value: 'm' },
|
||||
{ text: 'hours (h)', value: 'h' },
|
||||
{ text: 'days (d)', value: 'd' },
|
||||
{ text: 'duration (ms)', value: 'dtdurationms' },
|
||||
{ text: 'duration (s)', value: 'dtdurations' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'date & time',
|
||||
submenu: [
|
||||
{ text: 'YYYY-MM-DD HH:mm:ss', value: 'dateTimeAsIso' },
|
||||
{ text: 'DD/MM/YYYY h:mm:ss a', value: 'dateTimeAsUS' },
|
||||
{ text: 'From Now', value: 'dateTimeFromNow' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'data (IEC)',
|
||||
submenu: [
|
||||
{ text: 'bits', value: 'bits' },
|
||||
{ text: 'bytes', value: 'bytes' },
|
||||
{ text: 'kibibytes', value: 'kbytes' },
|
||||
{ text: 'mebibytes', value: 'mbytes' },
|
||||
{ text: 'gibibytes', value: 'gbytes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'data (Metric)',
|
||||
submenu: [
|
||||
{ text: 'bits', value: 'decbits' },
|
||||
{ text: 'bytes', value: 'decbytes' },
|
||||
{ text: 'kilobytes', value: 'deckbytes' },
|
||||
{ text: 'megabytes', value: 'decmbytes' },
|
||||
{ text: 'gigabytes', value: 'decgbytes' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'data rate',
|
||||
submenu: [
|
||||
{ text: 'packets/sec', value: 'pps' },
|
||||
{ text: 'bits/sec', value: 'bps' },
|
||||
{ text: 'bytes/sec', value: 'Bps' },
|
||||
{ text: 'kilobits/sec', value: 'Kbits' },
|
||||
{ text: 'kilobytes/sec', value: 'KBs' },
|
||||
{ text: 'megabits/sec', value: 'Mbits' },
|
||||
{ text: 'megabytes/sec', value: 'MBs' },
|
||||
{ text: 'gigabytes/sec', value: 'GBs' },
|
||||
{ text: 'gigabits/sec', value: 'Gbits' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'throughput',
|
||||
submenu: [
|
||||
{ text: 'ops/sec (ops)', value: 'ops' },
|
||||
{ text: 'reads/sec (rps)', value: 'rps' },
|
||||
{ text: 'writes/sec (wps)', value: 'wps' },
|
||||
{ text: 'I/O ops/sec (iops)', value: 'iops' },
|
||||
{ text: 'ops/min (opm)', value: 'opm' },
|
||||
{ text: 'reads/min (rpm)', value: 'rpm' },
|
||||
{ text: 'writes/min (wpm)', value: 'wpm' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'length',
|
||||
submenu: [
|
||||
{ text: 'millimetre (mm)', value: 'lengthmm' },
|
||||
{ text: 'meter (m)', value: 'lengthm' },
|
||||
{ text: 'kilometer (km)', value: 'lengthkm' },
|
||||
{ text: 'mile (mi)', value: 'lengthmi' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'mass',
|
||||
submenu: [
|
||||
{ text: 'milligram (mg)', value: 'massmg' },
|
||||
{ text: 'gram (g)', value: 'massg' },
|
||||
{ text: 'kilogram (kg)', value: 'masskg' },
|
||||
{ text: 'metric ton (t)', value: 'masst' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'velocity',
|
||||
submenu: [
|
||||
{ text: 'm/s', value: 'velocityms' },
|
||||
{ text: 'km/h', value: 'velocitykmh' },
|
||||
{ text: 'mph', value: 'velocitymph' },
|
||||
{ text: 'knot (kn)', value: 'velocityknot' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'volume',
|
||||
submenu: [
|
||||
{ text: 'millilitre', value: 'mlitre' },
|
||||
{ text: 'litre', value: 'litre' },
|
||||
{ text: 'cubic metre', value: 'm3' },
|
||||
{ text: 'cubic decimetre', value: 'dm3' },
|
||||
{ text: 'gallons', value: 'gallons' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'energy',
|
||||
submenu: [
|
||||
{ text: 'watt (W)', value: 'watt' },
|
||||
{ text: 'kilowatt (kW)', value: 'kwatt' },
|
||||
{ text: 'volt-ampere (VA)', value: 'voltamp' },
|
||||
{ text: 'kilovolt-ampere (kVA)', value: 'kvoltamp' },
|
||||
{ text: 'volt-ampere reactive (var)', value: 'voltampreact' },
|
||||
{ text: 'kilovolt-ampere reactive (kvar)', value: 'kvoltampreact' },
|
||||
{ text: 'watt-hour (Wh)', value: 'watth' },
|
||||
{ text: 'kilowatt-hour (kWh)', value: 'kwatth' },
|
||||
{ text: 'joule (J)', value: 'joule' },
|
||||
{ text: 'electron volt (eV)', value: 'ev' },
|
||||
{ text: 'Ampere (A)', value: 'amp' },
|
||||
{ text: 'Kiloampere (kA)', value: 'kamp' },
|
||||
{ text: 'Volt (V)', value: 'volt' },
|
||||
{ text: 'Kilovolt (kV)', value: 'kvolt' },
|
||||
{ text: 'Decibel-milliwatt (dBm)', value: 'dBm' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'temperature',
|
||||
submenu: [
|
||||
{ text: 'Celsius (°C)', value: 'celsius' },
|
||||
{ text: 'Farenheit (°F)', value: 'farenheit' },
|
||||
{ text: 'Kelvin (K)', value: 'kelvin' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'pressure',
|
||||
submenu: [
|
||||
{ text: 'Millibars', value: 'pressurembar' },
|
||||
{ text: 'Bars', value: 'pressurebar' },
|
||||
{ text: 'Kilobars', value: 'pressurekbar' },
|
||||
{ text: 'Hectopascals', value: 'pressurehpa' },
|
||||
{ text: 'Inches of mercury', value: 'pressurehg' },
|
||||
{ text: 'PSI', value: 'pressurepsi' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'force',
|
||||
submenu: [
|
||||
{ text: 'Newton-meters (Nm)', value: 'forceNm' },
|
||||
{ text: 'Kilonewton-meters (kNm)', value: 'forcekNm' },
|
||||
{ text: 'Newtons (N)', value: 'forceN' },
|
||||
{ text: 'Kilonewtons (kN)', value: 'forcekN' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'flow',
|
||||
submenu: [
|
||||
{ text: 'Gallons/min (gpm)', value: 'flowgpm' },
|
||||
{ text: 'Cubic meters/sec (cms)', value: 'flowcms' },
|
||||
{ text: 'Cubic feet/sec (cfs)', value: 'flowcfs' },
|
||||
{ text: 'Cubic feet/min (cfm)', value: 'flowcfm' },
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export default kbn;
|
@ -11,6 +11,8 @@ define([
|
||||
function (angular, moment, _, $, kbn, dateMath, impressionStore) {
|
||||
'use strict';
|
||||
|
||||
kbn = kbn.default;
|
||||
|
||||
var module = angular.module('grafana.services');
|
||||
|
||||
module.service('dashboardLoaderSrv', function(backendSrv,
|
||||
|
@ -1,8 +1,7 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import angular from 'angular';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import {saveAs} from 'file-saver';
|
||||
|
||||
import coreModule from 'app/core/core_module';
|
||||
import {DashboardExporter} from './exporter';
|
||||
|
||||
export class DashExportCtrl {
|
||||
@ -22,9 +21,8 @@ export class DashExportCtrl {
|
||||
}
|
||||
|
||||
save() {
|
||||
var blob = new Blob([angular.toJson(this.dash, true)], { type: "application/json;charset=utf-8" });
|
||||
var wnd: any = window;
|
||||
wnd.saveAs(blob, this.dash.title + '-' + new Date().getTime() + '.json');
|
||||
var blob = new Blob([angular.toJson(this.dash, true)], {type: 'application/json;charset=utf-8'});
|
||||
saveAs(blob, this.dash.title + '-' + new Date().getTime() + '.json');
|
||||
}
|
||||
|
||||
saveJson() {
|
||||
@ -44,7 +42,7 @@ export function dashExportDirective() {
|
||||
controller: DashExportCtrl,
|
||||
bindToController: true,
|
||||
controllerAs: 'ctrl',
|
||||
scope: {dismiss: "&"}
|
||||
scope: {dismiss: '&'},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ define([
|
||||
function (angular, _, kbn) {
|
||||
'use strict';
|
||||
|
||||
kbn = kbn.default;
|
||||
|
||||
angular
|
||||
.module('grafana.services')
|
||||
.service('linkSrv', function(templateSrv, timeSrv) {
|
||||
|
@ -9,15 +9,24 @@ import config from 'app/core/config';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import TableModel from 'app/core/table_model';
|
||||
import {coreModule, appEvents, contextSrv} from 'app/core/core';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
import * as datemath from 'app/core/utils/datemath';
|
||||
import * as fileExport from 'app/core/utils/file_export';
|
||||
import * as flatten from 'app/core/utils/flatten';
|
||||
import * as ticks from 'app/core/utils/ticks';
|
||||
import builtInPlugins from './buit_in_plugins';
|
||||
import {impressions} from 'app/features/dashboard/impression_store';
|
||||
import builtInPlugins from './built_in_plugins';
|
||||
import d3 from 'vendor/d3/d3';
|
||||
|
||||
// rxjs
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
|
||||
// these imports add functions to Observable
|
||||
import 'rxjs/add/observable/empty';
|
||||
import 'rxjs/add/observable/from';
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/combineAll';
|
||||
|
||||
System.config({
|
||||
baseURL: 'public',
|
||||
defaultExtension: 'js',
|
||||
@ -30,6 +39,9 @@ System.config({
|
||||
text: 'vendor/plugin-text/text.js',
|
||||
css: 'vendor/plugin-css/css.js'
|
||||
},
|
||||
meta: {
|
||||
'*': {esModule: true}
|
||||
}
|
||||
});
|
||||
|
||||
// add cache busting
|
||||
@ -56,8 +68,13 @@ exposeToPlugin('rxjs/Subject', Subject);
|
||||
exposeToPlugin('rxjs/Observable', Observable);
|
||||
exposeToPlugin('d3', d3);
|
||||
|
||||
exposeToPlugin('app/plugins/sdk', sdk);
|
||||
exposeToPlugin('app/features/dashboard/impression_store', {
|
||||
impressions: impressions,
|
||||
__esModule: true
|
||||
});
|
||||
|
||||
|
||||
exposeToPlugin('app/plugins/sdk', sdk);
|
||||
exposeToPlugin('app/core/utils/datemath', datemath);
|
||||
exposeToPlugin('app/core/utils/file_export', fileExport);
|
||||
exposeToPlugin('app/core/utils/flatten', flatten);
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import {Variable, assignModelProperties, variableTypes} from './variable';
|
||||
|
||||
|
@ -1,15 +1,19 @@
|
||||
import './templateSrv';
|
||||
import './editor_ctrl';
|
||||
import coreModule from 'app/core/core_module';
|
||||
|
||||
import {VariableSrv} from './variable_srv';
|
||||
import {IntervalVariable} from './interval_variable';
|
||||
import {QueryVariable} from './query_variable';
|
||||
import {DatasourceVariable} from './datasource_variable';
|
||||
import {CustomVariable} from './custom_variable';
|
||||
import {ConstantVariable} from './constant_variable';
|
||||
import {AdhocVariable} from './adhoc_variable';
|
||||
import { TemplateSrv } from './template_srv';
|
||||
import { VariableSrv } from './variable_srv';
|
||||
import { IntervalVariable } from './interval_variable';
|
||||
import { QueryVariable } from './query_variable';
|
||||
import { DatasourceVariable } from './datasource_variable';
|
||||
import { CustomVariable } from './custom_variable';
|
||||
import { ConstantVariable } from './constant_variable';
|
||||
import { AdhocVariable } from './adhoc_variable';
|
||||
|
||||
coreModule.service('templateSrv', TemplateSrv);
|
||||
|
||||
export {
|
||||
TemplateSrv,
|
||||
VariableSrv,
|
||||
IntervalVariable,
|
||||
QueryVariable,
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {Variable, containsVariable, assignModelProperties, variableTypes} from './variable';
|
||||
|
@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import {AdhocVariable} from '../adhoc_variable';
|
||||
|
||||
describe('AdhocVariable', function() {
|
||||
@ -15,7 +13,7 @@ describe('AdhocVariable', function() {
|
||||
]
|
||||
});
|
||||
var urlValue = variable.getValueForUrl();
|
||||
expect(urlValue).to.eql(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]);
|
||||
expect(urlValue).toMatchObject(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -26,17 +24,17 @@ describe('AdhocVariable', function() {
|
||||
var variable = new AdhocVariable({});
|
||||
variable.setValueFromUrl(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]);
|
||||
|
||||
expect(variable.filters[0].key).to.be('key1');
|
||||
expect(variable.filters[0].operator).to.be('=');
|
||||
expect(variable.filters[0].value).to.be('value1');
|
||||
expect(variable.filters[0].key).toBe('key1');
|
||||
expect(variable.filters[0].operator).toBe('=');
|
||||
expect(variable.filters[0].value).toBe('value1');
|
||||
|
||||
expect(variable.filters[1].key).to.be('key2');
|
||||
expect(variable.filters[1].operator).to.be('!=');
|
||||
expect(variable.filters[1].value).to.be('value2');
|
||||
expect(variable.filters[1].key).toBe('key2');
|
||||
expect(variable.filters[1].operator).toBe('!=');
|
||||
expect(variable.filters[1].value).toBe('value2');
|
||||
|
||||
expect(variable.filters[2].key).to.be('key3');
|
||||
expect(variable.filters[2].operator).to.be('=');
|
||||
expect(variable.filters[2].value).to.be('value3a|value3b|value3c');
|
||||
expect(variable.filters[2].key).toBe('key3');
|
||||
expect(variable.filters[2].operator).toBe('=');
|
||||
expect(variable.filters[2].value).toBe('value3a|value3b|value3c');
|
||||
});
|
||||
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import {QueryVariable} from '../query_variable';
|
||||
|
||||
describe('QueryVariable', () => {
|
||||
@ -8,14 +6,14 @@ describe('QueryVariable', () => {
|
||||
|
||||
it('should set defaults', () => {
|
||||
var variable = new QueryVariable({}, null, null, null, null);
|
||||
expect(variable.datasource).to.be(null);
|
||||
expect(variable.refresh).to.be(0);
|
||||
expect(variable.sort).to.be(0);
|
||||
expect(variable.name).to.be('');
|
||||
expect(variable.hide).to.be(0);
|
||||
expect(variable.options.length).to.be(0);
|
||||
expect(variable.multi).to.be(false);
|
||||
expect(variable.includeAll).to.be(false);
|
||||
expect(variable.datasource).toBe(null);
|
||||
expect(variable.refresh).toBe(0);
|
||||
expect(variable.sort).toBe(0);
|
||||
expect(variable.name).toBe('');
|
||||
expect(variable.hide).toBe(0);
|
||||
expect(variable.options.length).toBe(0);
|
||||
expect(variable.multi).toBe(false);
|
||||
expect(variable.includeAll).toBe(false);
|
||||
});
|
||||
|
||||
it('get model should copy changes back to model', () => {
|
||||
@ -26,11 +24,11 @@ describe('QueryVariable', () => {
|
||||
variable.sort = 50;
|
||||
|
||||
var model = variable.getSaveModel();
|
||||
expect(model.options.length).to.be(1);
|
||||
expect(model.options[0].text).to.be('test');
|
||||
expect(model.datasource).to.be('google');
|
||||
expect(model.regex).to.be('asd');
|
||||
expect(model.sort).to.be(50);
|
||||
expect(model.options.length).toBe(1);
|
||||
expect(model.options[0].text).toBe('test');
|
||||
expect(model.datasource).toBe('google');
|
||||
expect(model.regex).toBe('asd');
|
||||
expect(model.sort).toBe(50);
|
||||
});
|
||||
|
||||
it('if refresh != 0 then remove options in presisted mode', () => {
|
||||
@ -39,7 +37,7 @@ describe('QueryVariable', () => {
|
||||
variable.refresh = 1;
|
||||
|
||||
var model = variable.getSaveModel();
|
||||
expect(model.options.length).to.be(0);
|
||||
expect(model.options.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -67,14 +65,14 @@ describe('QueryVariable', () => {
|
||||
it('should return in same order', () => {
|
||||
var i = 0;
|
||||
|
||||
expect(result.length).to.be(11);
|
||||
expect(result[i++].text).to.be('');
|
||||
expect(result[i++].text).to.be('0');
|
||||
expect(result[i++].text).to.be('1');
|
||||
expect(result[i++].text).to.be('3');
|
||||
expect(result[i++].text).to.be('4');
|
||||
expect(result[i++].text).to.be('5');
|
||||
expect(result[i++].text).to.be('6');
|
||||
expect(result.length).toBe(11);
|
||||
expect(result[i++].text).toBe('');
|
||||
expect(result[i++].text).toBe('0');
|
||||
expect(result[i++].text).toBe('1');
|
||||
expect(result[i++].text).toBe('3');
|
||||
expect(result[i++].text).toBe('4');
|
||||
expect(result[i++].text).toBe('5');
|
||||
expect(result[i++].text).toBe('6');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,28 +1,11 @@
|
||||
import {describe, beforeEach, it, expect, angularMocks} from 'test/lib/common';
|
||||
|
||||
import '../all';
|
||||
import {Emitter} from 'app/core/core';
|
||||
import { TemplateSrv } from '../template_srv';
|
||||
|
||||
describe('templateSrv', function() {
|
||||
var _templateSrv, _variableSrv;
|
||||
|
||||
beforeEach(angularMocks.module('grafana.core'));
|
||||
beforeEach(angularMocks.module('grafana.services'));
|
||||
beforeEach(angularMocks.module($provide => {
|
||||
$provide.value('timeSrv', {});
|
||||
$provide.value('datasourceSrv', {});
|
||||
}));
|
||||
|
||||
beforeEach(angularMocks.inject(function(variableSrv, templateSrv) {
|
||||
_templateSrv = templateSrv;
|
||||
_variableSrv = variableSrv;
|
||||
}));
|
||||
var _templateSrv;
|
||||
|
||||
function initTemplateSrv(variables) {
|
||||
_variableSrv.init({
|
||||
templating: {list: variables},
|
||||
events: new Emitter(),
|
||||
});
|
||||
_templateSrv = new TemplateSrv();
|
||||
_templateSrv.init(variables);
|
||||
}
|
||||
|
||||
describe('init', function() {
|
||||
@ -32,7 +15,7 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should initialize template data', function() {
|
||||
var target = _templateSrv.replace('this.[[test]].filters');
|
||||
expect(target).to.be('this.oogle.filters');
|
||||
expect(target).toBe('this.oogle.filters');
|
||||
});
|
||||
});
|
||||
|
||||
@ -43,12 +26,12 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace $test with scoped value', function() {
|
||||
var target = _templateSrv.replace('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
|
||||
expect(target).to.be('this.mupp.filters');
|
||||
expect(target).toBe('this.mupp.filters');
|
||||
});
|
||||
|
||||
it('should replace $test with scoped text', function() {
|
||||
var target = _templateSrv.replaceWithText('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
|
||||
expect(target).to.be('this.asd.filters');
|
||||
expect(target).toBe('this.asd.filters');
|
||||
});
|
||||
});
|
||||
|
||||
@ -63,17 +46,17 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should return filters if datasourceName match', function() {
|
||||
var filters = _templateSrv.getAdhocFilters('oogle');
|
||||
expect(filters).to.eql([1]);
|
||||
expect(filters).toMatchObject([1]);
|
||||
});
|
||||
|
||||
it('should return empty array if datasourceName does not match', function() {
|
||||
var filters = _templateSrv.getAdhocFilters('oogleasdasd');
|
||||
expect(filters).to.eql([]);
|
||||
expect(filters).toMatchObject([]);
|
||||
});
|
||||
|
||||
it('should return filters when datasourceName match via data source variable', function() {
|
||||
var filters = _templateSrv.getAdhocFilters('logstash');
|
||||
expect(filters).to.eql([2]);
|
||||
expect(filters).toMatchObject([2]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,17 +67,17 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace $test with globbed value', function() {
|
||||
var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
|
||||
expect(target).to.be('this.{value1,value2}.filters');
|
||||
expect(target).toBe('this.{value1,value2}.filters');
|
||||
});
|
||||
|
||||
it('should replace $test with piped value', function() {
|
||||
var target = _templateSrv.replace('this=$test', {}, 'pipe');
|
||||
expect(target).to.be('this=value1|value2');
|
||||
expect(target).toBe('this=value1|value2');
|
||||
});
|
||||
|
||||
it('should replace $test with piped value', function() {
|
||||
var target = _templateSrv.replace('this=$test', {}, 'pipe');
|
||||
expect(target).to.be('this=value1|value2');
|
||||
expect(target).toBe('this=value1|value2');
|
||||
});
|
||||
});
|
||||
|
||||
@ -112,7 +95,7 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace $test with formatted all value', function() {
|
||||
var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
|
||||
expect(target).to.be('this.{value1,value2}.filters');
|
||||
expect(target).toBe('this.{value1,value2}.filters');
|
||||
});
|
||||
});
|
||||
|
||||
@ -131,12 +114,12 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace $test with formatted all value', function() {
|
||||
var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
|
||||
expect(target).to.be('this.*.filters');
|
||||
expect(target).toBe('this.*.filters');
|
||||
});
|
||||
|
||||
it('should not escape custom all value', function() {
|
||||
var target = _templateSrv.replace('this.$test', {}, 'regex');
|
||||
expect(target).to.be('this.*');
|
||||
expect(target).toBe('this.*');
|
||||
});
|
||||
});
|
||||
|
||||
@ -144,49 +127,49 @@ describe('templateSrv', function() {
|
||||
it('should properly escape $test with lucene escape sequences', function() {
|
||||
initTemplateSrv([{type: 'query', name: 'test', current: {value: 'value/4' }}]);
|
||||
var target = _templateSrv.replace('this:$test', {}, 'lucene');
|
||||
expect(target).to.be("this:value\\\/4");
|
||||
expect(target).toBe("this:value\\\/4");
|
||||
});
|
||||
});
|
||||
|
||||
describe('format variable to string values', function() {
|
||||
it('single value should return value', function() {
|
||||
var result = _templateSrv.formatValue('test');
|
||||
expect(result).to.be('test');
|
||||
expect(result).toBe('test');
|
||||
});
|
||||
|
||||
it('multi value and glob format should render glob string', function() {
|
||||
var result = _templateSrv.formatValue(['test','test2'], 'glob');
|
||||
expect(result).to.be('{test,test2}');
|
||||
expect(result).toBe('{test,test2}');
|
||||
});
|
||||
|
||||
it('multi value and lucene should render as lucene expr', function() {
|
||||
var result = _templateSrv.formatValue(['test','test2'], 'lucene');
|
||||
expect(result).to.be('("test" OR "test2")');
|
||||
expect(result).toBe('("test" OR "test2")');
|
||||
});
|
||||
|
||||
it('multi value and regex format should render regex string', function() {
|
||||
var result = _templateSrv.formatValue(['test.','test2'], 'regex');
|
||||
expect(result).to.be('(test\\.|test2)');
|
||||
expect(result).toBe('(test\\.|test2)');
|
||||
});
|
||||
|
||||
it('multi value and pipe should render pipe string', function() {
|
||||
var result = _templateSrv.formatValue(['test','test2'], 'pipe');
|
||||
expect(result).to.be('test|test2');
|
||||
expect(result).toBe('test|test2');
|
||||
});
|
||||
|
||||
it('multi value and distributed should render distributed string', function() {
|
||||
var result = _templateSrv.formatValue(['test','test2'], 'distributed', { name: 'build' });
|
||||
expect(result).to.be('test,build=test2');
|
||||
expect(result).toBe('test,build=test2');
|
||||
});
|
||||
|
||||
it('multi value and distributed should render when not string', function() {
|
||||
var result = _templateSrv.formatValue(['test'], 'distributed', { name: 'build' });
|
||||
expect(result).to.be('test');
|
||||
expect(result).toBe('test');
|
||||
});
|
||||
|
||||
it('slash should be properly escaped in regex format', function() {
|
||||
var result = _templateSrv.formatValue('Gi3/14', 'regex');
|
||||
expect(result).to.be('Gi3\\/14');
|
||||
expect(result).toBe('Gi3\\/14');
|
||||
});
|
||||
|
||||
});
|
||||
@ -198,7 +181,7 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should return true if exists', function() {
|
||||
var result = _templateSrv.variableExists('$test');
|
||||
expect(result).to.be(true);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -209,17 +192,17 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should insert html', function() {
|
||||
var result = _templateSrv.highlightVariablesAsHtml('$test');
|
||||
expect(result).to.be('<span class="template-variable">$test</span>');
|
||||
expect(result).toBe('<span class="template-variable">$test</span>');
|
||||
});
|
||||
|
||||
it('should insert html anywhere in string', function() {
|
||||
var result = _templateSrv.highlightVariablesAsHtml('this $test ok');
|
||||
expect(result).to.be('this <span class="template-variable">$test</span> ok');
|
||||
expect(result).toBe('this <span class="template-variable">$test</span> ok');
|
||||
});
|
||||
|
||||
it('should ignore if variables does not exist', function() {
|
||||
var result = _templateSrv.highlightVariablesAsHtml('this $google ok');
|
||||
expect(result).to.be('this $google ok');
|
||||
expect(result).toBe('this $google ok');
|
||||
});
|
||||
});
|
||||
|
||||
@ -230,19 +213,28 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should set current value and update template data', function() {
|
||||
var target = _templateSrv.replace('this.[[test]].filters');
|
||||
expect(target).to.be('this.muuuu.filters');
|
||||
expect(target).toBe('this.muuuu.filters');
|
||||
});
|
||||
});
|
||||
|
||||
describe('fillVariableValuesForUrl with multi value', function() {
|
||||
beforeEach(function() {
|
||||
initTemplateSrv([{type: 'query', name: 'test', current: { value: ['val1', 'val2'] }}]);
|
||||
initTemplateSrv([
|
||||
{
|
||||
type: 'query',
|
||||
name: 'test',
|
||||
current: { value: ['val1', 'val2'] },
|
||||
getValueForUrl: function() {
|
||||
return this.current.value;
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it('should set multiple url params', function() {
|
||||
var params = {};
|
||||
_templateSrv.fillVariableValuesForUrl(params);
|
||||
expect(params['var-test']).to.eql(['val1', 'val2']);
|
||||
expect(params['var-test']).toMatchObject(['val1', 'val2']);
|
||||
});
|
||||
});
|
||||
|
||||
@ -254,7 +246,7 @@ describe('templateSrv', function() {
|
||||
it('should set scoped value as url params', function() {
|
||||
var params = {};
|
||||
_templateSrv.fillVariableValuesForUrl(params, {'test': {value: 'val1'}});
|
||||
expect(params['var-test']).to.eql('val1');
|
||||
expect(params['var-test']).toBe('val1');
|
||||
});
|
||||
});
|
||||
|
||||
@ -270,7 +262,7 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace with text except for grafanaVariables', function() {
|
||||
var target = _templateSrv.replaceWithText('Server: $server, period: $period');
|
||||
expect(target).to.be('Server: All, period: 13m');
|
||||
expect(target).toBe('Server: All, period: 13m');
|
||||
});
|
||||
});
|
||||
|
||||
@ -281,7 +273,7 @@ describe('templateSrv', function() {
|
||||
|
||||
it('should replace $__interval_ms with interval milliseconds', function() {
|
||||
var target = _templateSrv.replace('10 * $__interval_ms', {"__interval_ms": {text: "100", value: "100"}});
|
||||
expect(target).to.be('10 * 100');
|
||||
expect(target).toBe('10 * 100');
|
||||
});
|
||||
|
||||
});
|
@ -1,253 +0,0 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash',
|
||||
'app/core/utils/kbn',
|
||||
],
|
||||
function (angular, _, kbn) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.services');
|
||||
|
||||
module.service('templateSrv', function() {
|
||||
var self = this;
|
||||
|
||||
this._regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g;
|
||||
this._index = {};
|
||||
this._texts = {};
|
||||
this._grafanaVariables = {};
|
||||
|
||||
// default built ins
|
||||
this._builtIns = {};
|
||||
this._builtIns['__interval'] = {text: '1s', value: '1s'};
|
||||
this._builtIns['__interval_ms'] = {text: '100', value: '100'};
|
||||
|
||||
this.init = function(variables) {
|
||||
this.variables = variables;
|
||||
this.updateTemplateData();
|
||||
};
|
||||
|
||||
this.updateTemplateData = function() {
|
||||
this._index = {};
|
||||
this._filters = {};
|
||||
|
||||
for (var i = 0; i < this.variables.length; i++) {
|
||||
var variable = this.variables[i];
|
||||
|
||||
if (!variable.current || !variable.current.isNone && !variable.current.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this._index[variable.name] = variable;
|
||||
}
|
||||
};
|
||||
|
||||
this.variableInitialized = function(variable) {
|
||||
this._index[variable.name] = variable;
|
||||
};
|
||||
|
||||
this.getAdhocFilters = function(datasourceName) {
|
||||
var filters = [];
|
||||
|
||||
for (var i = 0; i < this.variables.length; i++) {
|
||||
var variable = this.variables[i];
|
||||
if (variable.type !== 'adhoc') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variable.datasource === datasourceName) {
|
||||
filters = filters.concat(variable.filters);
|
||||
}
|
||||
|
||||
if (variable.datasource.indexOf('$') === 0) {
|
||||
if (this.replace(variable.datasource) === datasourceName) {
|
||||
filters = filters.concat(variable.filters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
};
|
||||
|
||||
function luceneEscape(value) {
|
||||
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, "\\$1");
|
||||
}
|
||||
|
||||
this.luceneFormat = function(value) {
|
||||
if (typeof value === 'string') {
|
||||
return luceneEscape(value);
|
||||
}
|
||||
var quotedValues = _.map(value, function(val) {
|
||||
return '\"' + luceneEscape(val) + '\"';
|
||||
});
|
||||
return '(' + quotedValues.join(' OR ') + ')';
|
||||
};
|
||||
|
||||
this.formatValue = function(value, format, variable) {
|
||||
// for some scopedVars there is no variable
|
||||
variable = variable || {};
|
||||
|
||||
if (typeof format === 'function') {
|
||||
return format(value, variable, this.formatValue);
|
||||
}
|
||||
|
||||
switch(format) {
|
||||
case "regex": {
|
||||
if (typeof value === 'string') {
|
||||
return kbn.regexEscape(value);
|
||||
}
|
||||
|
||||
var escapedValues = _.map(value, kbn.regexEscape);
|
||||
return '(' + escapedValues.join('|') + ')';
|
||||
}
|
||||
case "lucene": {
|
||||
return this.luceneFormat(value, format, variable);
|
||||
}
|
||||
case "pipe": {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return value.join('|');
|
||||
}
|
||||
case "distributed": {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return this.distributeVariable(value, variable.name);
|
||||
}
|
||||
default: {
|
||||
if (_.isArray(value)) {
|
||||
return '{' + value.join(',') + '}';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.setGrafanaVariable = function (name, value) {
|
||||
this._grafanaVariables[name] = value;
|
||||
};
|
||||
|
||||
this.getVariableName = function(expression) {
|
||||
this._regex.lastIndex = 0;
|
||||
var match = this._regex.exec(expression);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return match[1] || match[2];
|
||||
};
|
||||
|
||||
this.variableExists = function(expression) {
|
||||
var name = this.getVariableName(expression);
|
||||
return name && (self._index[name] !== void 0);
|
||||
};
|
||||
|
||||
this.highlightVariablesAsHtml = function(str) {
|
||||
if (!str || !_.isString(str)) { return str; }
|
||||
|
||||
str = _.escape(str);
|
||||
this._regex.lastIndex = 0;
|
||||
return str.replace(this._regex, function(match, g1, g2) {
|
||||
if (self._index[g1 || g2] || self._builtIns[g1 || g2]) {
|
||||
return '<span class="template-variable">' + match + '</span>';
|
||||
}
|
||||
return match;
|
||||
});
|
||||
};
|
||||
|
||||
this.getAllValue = function(variable) {
|
||||
if (variable.allValue) {
|
||||
return variable.allValue;
|
||||
}
|
||||
var values = [];
|
||||
for (var i = 1; i < variable.options.length; i++) {
|
||||
values.push(variable.options[i].value);
|
||||
}
|
||||
return values;
|
||||
};
|
||||
|
||||
this.replace = function(target, scopedVars, format) {
|
||||
if (!target) { return target; }
|
||||
|
||||
var variable, systemValue, value;
|
||||
this._regex.lastIndex = 0;
|
||||
|
||||
return target.replace(this._regex, function(match, g1, g2) {
|
||||
variable = self._index[g1 || g2];
|
||||
|
||||
if (scopedVars) {
|
||||
value = scopedVars[g1 || g2];
|
||||
if (value) {
|
||||
return self.formatValue(value.value, format, variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!variable) {
|
||||
return match;
|
||||
}
|
||||
|
||||
systemValue = self._grafanaVariables[variable.current.value];
|
||||
if (systemValue) {
|
||||
return self.formatValue(systemValue, format, variable);
|
||||
}
|
||||
|
||||
value = variable.current.value;
|
||||
if (self.isAllValue(value)) {
|
||||
value = self.getAllValue(variable);
|
||||
// skip formating of custom all values
|
||||
if (variable.allValue) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
var res = self.formatValue(value, format, variable);
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
this.isAllValue = function(value) {
|
||||
return value === '$__all' || Array.isArray(value) && value[0] === '$__all';
|
||||
};
|
||||
|
||||
this.replaceWithText = function(target, scopedVars) {
|
||||
if (!target) { return target; }
|
||||
|
||||
var variable;
|
||||
this._regex.lastIndex = 0;
|
||||
|
||||
return target.replace(this._regex, function(match, g1, g2) {
|
||||
if (scopedVars) {
|
||||
var option = scopedVars[g1 || g2];
|
||||
if (option) { return option.text; }
|
||||
}
|
||||
|
||||
variable = self._index[g1 || g2];
|
||||
if (!variable) { return match; }
|
||||
|
||||
return self._grafanaVariables[variable.current.value] || variable.current.text;
|
||||
});
|
||||
};
|
||||
|
||||
this.fillVariableValuesForUrl = function(params, scopedVars) {
|
||||
_.each(this.variables, function(variable) {
|
||||
if (scopedVars && scopedVars[variable.name] !== void 0) {
|
||||
params['var-' + variable.name] = scopedVars[variable.name].value;
|
||||
} else {
|
||||
params['var-' + variable.name] = variable.getValueForUrl();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.distributeVariable = function(value, variable) {
|
||||
value = _.map(value, function(val, index) {
|
||||
if (index !== 0) {
|
||||
return variable + "=" + val;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
});
|
||||
return value.join(',');
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
244
public/app/features/templating/template_srv.ts
Normal file
244
public/app/features/templating/template_srv.ts
Normal file
@ -0,0 +1,244 @@
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import _ from 'lodash';
|
||||
|
||||
function luceneEscape(value) {
|
||||
return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, "\\$1");
|
||||
}
|
||||
|
||||
export class TemplateSrv {
|
||||
variables: any[];
|
||||
|
||||
private regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g;
|
||||
private index = {};
|
||||
private grafanaVariables = {};
|
||||
private builtIns = {};
|
||||
private filters = {};
|
||||
|
||||
constructor() {
|
||||
this.builtIns['__interval'] = {text: '1s', value: '1s'};
|
||||
this.builtIns['__interval_ms'] = {text: '100', value: '100'};
|
||||
}
|
||||
|
||||
init(variables) {
|
||||
this.variables = variables;
|
||||
this.updateTemplateData();
|
||||
}
|
||||
|
||||
updateTemplateData() {
|
||||
this.index = {};
|
||||
this.filters = {};
|
||||
|
||||
for (var i = 0; i < this.variables.length; i++) {
|
||||
var variable = this.variables[i];
|
||||
|
||||
if (!variable.current || !variable.current.isNone && !variable.current.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.index[variable.name] = variable;
|
||||
}
|
||||
}
|
||||
|
||||
variableInitialized(variable) {
|
||||
this.index[variable.name] = variable;
|
||||
}
|
||||
|
||||
getAdhocFilters(datasourceName) {
|
||||
var filters = [];
|
||||
|
||||
for (var i = 0; i < this.variables.length; i++) {
|
||||
var variable = this.variables[i];
|
||||
if (variable.type !== 'adhoc') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variable.datasource === datasourceName) {
|
||||
filters = filters.concat(variable.filters);
|
||||
}
|
||||
|
||||
if (variable.datasource.indexOf('$') === 0) {
|
||||
if (this.replace(variable.datasource) === datasourceName) {
|
||||
filters = filters.concat(variable.filters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
luceneFormat(value) {
|
||||
if (typeof value === 'string') {
|
||||
return luceneEscape(value);
|
||||
}
|
||||
var quotedValues = _.map(value, function(val) {
|
||||
return '\"' + luceneEscape(val) + '\"';
|
||||
});
|
||||
return '(' + quotedValues.join(' OR ') + ')';
|
||||
}
|
||||
|
||||
formatValue(value, format, variable) {
|
||||
// for some scopedVars there is no variable
|
||||
variable = variable || {};
|
||||
|
||||
if (typeof format === 'function') {
|
||||
return format(value, variable, this.formatValue);
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case "regex": {
|
||||
if (typeof value === 'string') {
|
||||
return kbn.regexEscape(value);
|
||||
}
|
||||
|
||||
var escapedValues = _.map(value, kbn.regexEscape);
|
||||
return '(' + escapedValues.join('|') + ')';
|
||||
}
|
||||
case "lucene": {
|
||||
return this.luceneFormat(value);
|
||||
}
|
||||
case "pipe": {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return value.join('|');
|
||||
}
|
||||
case "distributed": {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return this.distributeVariable(value, variable.name);
|
||||
}
|
||||
default: {
|
||||
if (_.isArray(value)) {
|
||||
return '{' + value.join(',') + '}';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setGrafanaVariable(name, value) {
|
||||
this.grafanaVariables[name] = value;
|
||||
}
|
||||
|
||||
getVariableName(expression) {
|
||||
this.regex.lastIndex = 0;
|
||||
var match = this.regex.exec(expression);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return match[1] || match[2];
|
||||
}
|
||||
|
||||
variableExists(expression) {
|
||||
var name = this.getVariableName(expression);
|
||||
return name && (this.index[name] !== void 0);
|
||||
}
|
||||
|
||||
highlightVariablesAsHtml(str) {
|
||||
if (!str || !_.isString(str)) { return str; }
|
||||
|
||||
str = _.escape(str);
|
||||
this.regex.lastIndex = 0;
|
||||
return str.replace(this.regex, (match, g1, g2) => {
|
||||
if (this.index[g1 || g2] || this.builtIns[g1 || g2]) {
|
||||
return '<span class="template-variable">' + match + '</span>';
|
||||
}
|
||||
return match;
|
||||
});
|
||||
}
|
||||
|
||||
getAllValue(variable) {
|
||||
if (variable.allValue) {
|
||||
return variable.allValue;
|
||||
}
|
||||
var values = [];
|
||||
for (var i = 1; i < variable.options.length; i++) {
|
||||
values.push(variable.options[i].value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
replace(target, scopedVars?, format?) {
|
||||
if (!target) { return target; }
|
||||
|
||||
var variable, systemValue, value;
|
||||
this.regex.lastIndex = 0;
|
||||
|
||||
return target.replace(this.regex, (match, g1, g2) => {
|
||||
variable = this.index[g1 || g2];
|
||||
|
||||
if (scopedVars) {
|
||||
value = scopedVars[g1 || g2];
|
||||
if (value) {
|
||||
return this.formatValue(value.value, format, variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!variable) {
|
||||
return match;
|
||||
}
|
||||
|
||||
systemValue = this.grafanaVariables[variable.current.value];
|
||||
if (systemValue) {
|
||||
return this.formatValue(systemValue, format, variable);
|
||||
}
|
||||
|
||||
value = variable.current.value;
|
||||
if (this.isAllValue(value)) {
|
||||
value = this.getAllValue(variable);
|
||||
// skip formating of custom all values
|
||||
if (variable.allValue) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
var res = this.formatValue(value, format, variable);
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
isAllValue(value) {
|
||||
return value === '$__all' || Array.isArray(value) && value[0] === '$__all';
|
||||
}
|
||||
|
||||
replaceWithText(target, scopedVars) {
|
||||
if (!target) { return target; }
|
||||
|
||||
var variable;
|
||||
this.regex.lastIndex = 0;
|
||||
|
||||
return target.replace(this.regex, (match, g1, g2) => {
|
||||
if (scopedVars) {
|
||||
var option = scopedVars[g1 || g2];
|
||||
if (option) { return option.text; }
|
||||
}
|
||||
|
||||
variable = this.index[g1 || g2];
|
||||
if (!variable) { return match; }
|
||||
|
||||
return this.grafanaVariables[variable.current.value] || variable.current.text;
|
||||
});
|
||||
}
|
||||
|
||||
fillVariableValuesForUrl(params, scopedVars) {
|
||||
_.each(this.variables, function(variable) {
|
||||
if (scopedVars && scopedVars[variable.name] !== void 0) {
|
||||
params['var-' + variable.name] = scopedVars[variable.name].value;
|
||||
} else {
|
||||
params['var-' + variable.name] = variable.getValueForUrl();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
distributeVariable(value, variable) {
|
||||
value = _.map(value, function(val, index) {
|
||||
if (index !== 0) {
|
||||
return variable + "=" + val;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
});
|
||||
return value.join(',');
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {assignModelProperties} from 'app/core/core';
|
||||
import {assignModelProperties} from 'app/core/utils/model_utils';
|
||||
|
||||
export interface Variable {
|
||||
setValue(option);
|
||||
|
@ -9,6 +9,8 @@ define([
|
||||
function (angular, _, moment, dateMath, kbn, templatingVariable) {
|
||||
'use strict';
|
||||
|
||||
kbn = kbn.default;
|
||||
|
||||
/** @ngInject */
|
||||
function CloudWatchDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) {
|
||||
this.type = 'cloudwatch';
|
||||
@ -354,6 +356,7 @@ function (angular, _, moment, dateMath, kbn, templatingVariable) {
|
||||
var t = angular.copy(target);
|
||||
var scopedVar = {};
|
||||
scopedVar[variable.name] = v;
|
||||
t.refId = target.refId + '_' + v.value;
|
||||
t.dimensions[dimensionKey] = templateSrv.replace(t.dimensions[dimensionKey], scopedVar);
|
||||
return t;
|
||||
}).value();
|
||||
|
@ -75,6 +75,12 @@ export class ElasticDatasource {
|
||||
return this.request('POST', url, data).then(function(results) {
|
||||
results.data.$$config = results.config;
|
||||
return results.data;
|
||||
}).catch(err => {
|
||||
if (err.data && err.data.error) {
|
||||
throw {message: 'Elasticsearch error: ' + err.data.error.reason, error: err.data.error};
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@ define([
|
||||
function (angular, _, $, gfunc) {
|
||||
'use strict';
|
||||
|
||||
gfunc = gfunc.default;
|
||||
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('graphiteAddFunc', function($compile) {
|
||||
|
@ -1,2 +0,0 @@
|
||||
declare var test: any;
|
||||
export default test;
|
@ -1,986 +0,0 @@
|
||||
define([
|
||||
'lodash',
|
||||
'jquery'
|
||||
],
|
||||
function (_, $) {
|
||||
'use strict';
|
||||
|
||||
var index = [];
|
||||
var categories = {
|
||||
Combine: [],
|
||||
Transform: [],
|
||||
Calculate: [],
|
||||
Filter: [],
|
||||
Special: []
|
||||
};
|
||||
|
||||
function addFuncDef(funcDef) {
|
||||
funcDef.params = funcDef.params || [];
|
||||
funcDef.defaultParams = funcDef.defaultParams || [];
|
||||
|
||||
if (funcDef.category) {
|
||||
funcDef.category.push(funcDef);
|
||||
}
|
||||
index[funcDef.name] = funcDef;
|
||||
index[funcDef.shortName || funcDef.name] = funcDef;
|
||||
}
|
||||
|
||||
var optionalSeriesRefArgs = [
|
||||
{ name: 'other', type: 'value_or_series', optional: true },
|
||||
{ name: 'other', type: 'value_or_series', optional: true },
|
||||
{ name: 'other', type: 'value_or_series', optional: true },
|
||||
{ name: 'other', type: 'value_or_series', optional: true },
|
||||
{ name: 'other', type: 'value_or_series', optional: true }
|
||||
];
|
||||
|
||||
addFuncDef({
|
||||
name: 'scaleToSeconds',
|
||||
category: categories.Transform,
|
||||
params: [{ name: 'seconds', type: 'int' }],
|
||||
defaultParams: [1],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'perSecond',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "max value", type: "int", optional: true }],
|
||||
defaultParams: [],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "holtWintersForecast",
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "holtWintersConfidenceBands",
|
||||
category: categories.Calculate,
|
||||
params: [{ name: "delta", type: 'int' }],
|
||||
defaultParams: [3]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "holtWintersAberration",
|
||||
category: categories.Calculate,
|
||||
params: [{ name: "delta", type: 'int' }],
|
||||
defaultParams: [3]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "nPercentile",
|
||||
category: categories.Calculate,
|
||||
params: [{ name: "Nth percentile", type: 'int' }],
|
||||
defaultParams: [95]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'diffSeries',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: ['#A'],
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'stddevSeries',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: [''],
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'divideSeries',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: ['#A'],
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'multiplySeries',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: ['#A'],
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'asPercent',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: ['#A'],
|
||||
category: categories.Calculate,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'group',
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: ['#A', '#B'],
|
||||
category: categories.Combine,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sumSeries',
|
||||
shortName: 'sum',
|
||||
category: categories.Combine,
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: [''],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageSeries',
|
||||
shortName: 'avg',
|
||||
category: categories.Combine,
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: [''],
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'rangeOfSeries',
|
||||
category: categories.Combine
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'percentileOfSeries',
|
||||
category: categories.Combine,
|
||||
params: [{ name: 'n', type: 'int' }, { name: 'interpolate', type: 'boolean', options: ['true', 'false'] }],
|
||||
defaultParams: [95, 'false']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sumSeriesWithWildcards',
|
||||
category: categories.Combine,
|
||||
params: [
|
||||
{ name: "node", type: "int" },
|
||||
{ name: "node", type: "int", optional: true },
|
||||
{ name: "node", type: "int", optional: true },
|
||||
{ name: "node", type: "int", optional: true }
|
||||
],
|
||||
defaultParams: [3]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'maxSeries',
|
||||
shortName: 'max',
|
||||
category: categories.Combine,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'minSeries',
|
||||
shortName: 'min',
|
||||
category: categories.Combine,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageSeriesWithWildcards',
|
||||
category: categories.Combine,
|
||||
params: [
|
||||
{ name: "node", type: "int" },
|
||||
{ name: "node", type: "int", optional: true },
|
||||
],
|
||||
defaultParams: [3]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "alias",
|
||||
category: categories.Special,
|
||||
params: [{ name: "alias", type: 'string' }],
|
||||
defaultParams: ['alias']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "aliasSub",
|
||||
category: categories.Special,
|
||||
params: [{ name: "search", type: 'string' }, { name: "replace", type: 'string' }],
|
||||
defaultParams: ['', '\\1']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "stacked",
|
||||
category: categories.Special,
|
||||
params: [{ name: "stack", type: 'string' }],
|
||||
defaultParams: ['stacked']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "consolidateBy",
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{
|
||||
name: 'function',
|
||||
type: 'string',
|
||||
options: ['sum', 'average', 'min', 'max']
|
||||
}
|
||||
],
|
||||
defaultParams: ['max']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "cumulative",
|
||||
category: categories.Special,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "groupByNode",
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{
|
||||
name: "node",
|
||||
type: "int",
|
||||
options: [0,1,2,3,4,5,6,7,8,9,10,12]
|
||||
},
|
||||
{
|
||||
name: "function",
|
||||
type: "string",
|
||||
options: ['sum', 'avg', 'maxSeries']
|
||||
}
|
||||
],
|
||||
defaultParams: [3, "sum"]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'aliasByNode',
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{ name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
],
|
||||
defaultParams: [3]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'substr',
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{ name: "start", type: "int", options: [-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
{ name: "stop", type: "int", options: [-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
],
|
||||
defaultParams: [0, 0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sortByName',
|
||||
category: categories.Special,
|
||||
params: [{ name: 'natural', type: 'boolean', options: ['true', 'false'], optional: true }],
|
||||
defaultParams: ['false']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sortByMaxima',
|
||||
category: categories.Special
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sortByMinima',
|
||||
category: categories.Special
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'sortByTotal',
|
||||
category: categories.Special
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'aliasByMetric',
|
||||
category: categories.Special,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'randomWalk',
|
||||
fake: true,
|
||||
category: categories.Special,
|
||||
params: [{ name: "name", type: "string", }],
|
||||
defaultParams: ['randomWalk']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'countSeries',
|
||||
category: categories.Special
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'constantLine',
|
||||
category: categories.Special,
|
||||
params: [{ name: "value", type: "int", }],
|
||||
defaultParams: [10]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'cactiStyle',
|
||||
category: categories.Special,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'keepLastValue',
|
||||
category: categories.Special,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [100]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "changed",
|
||||
category: categories.Special,
|
||||
params: [],
|
||||
defaultParams: []
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'scale',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "factor", type: "int", }],
|
||||
defaultParams: [1]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'offset',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "amount", type: "int", }],
|
||||
defaultParams: [10]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'transformNull',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "amount", type: "int", }],
|
||||
defaultParams: [0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'integral',
|
||||
category: categories.Transform,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'derivative',
|
||||
category: categories.Transform,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'nonNegativeDerivative',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "max value or 0", type: "int", optional: true }],
|
||||
defaultParams: ['']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'timeShift',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "amount", type: "select", options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'] }],
|
||||
defaultParams: ['1d']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'timeStack',
|
||||
category: categories.Transform,
|
||||
params: [
|
||||
{ name: "timeShiftUnit", type: "select", options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'] },
|
||||
{ name: "timeShiftStart", type: "int" },
|
||||
{ name: "timeShiftEnd", type: "int" }
|
||||
],
|
||||
defaultParams: ['1d', 0, 7]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'summarize',
|
||||
category: categories.Transform,
|
||||
params: [
|
||||
{ name: "interval", type: "string" },
|
||||
{ name: "func", type: "select", options: ['sum', 'avg', 'min', 'max', 'last'] },
|
||||
{ name: "alignToFrom", type: "boolean", optional: true, options: ['false', 'true'] },
|
||||
],
|
||||
defaultParams: ['1h', 'sum', 'false']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'smartSummarize',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "interval", type: "string" }, { name: "func", type: "select", options: ['sum', 'avg', 'min', 'max', 'last'] }],
|
||||
defaultParams: ['1h', 'sum']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'absolute',
|
||||
category: categories.Transform,
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'hitcount',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "interval", type: "string" }],
|
||||
defaultParams: ['10s']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'log',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "base", type: "int" }],
|
||||
defaultParams: ['10']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageAbove',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [25]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageBelow',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [25]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'currentAbove',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [25]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'currentBelow',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [25]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'maximumAbove',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "value", type: "int" }],
|
||||
defaultParams: [0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'maximumBelow',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "value", type: "int" }],
|
||||
defaultParams: [0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'minimumAbove',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "value", type: "int" }],
|
||||
defaultParams: [0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'minimumBelow',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "value", type: "int" }],
|
||||
defaultParams: [0]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'limit',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'mostDeviant',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [10]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "exclude",
|
||||
category: categories.Filter,
|
||||
params: [{ name: "exclude", type: 'string' }],
|
||||
defaultParams: ['exclude']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'highestCurrent',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "count", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'highestMax',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "count", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'lowestCurrent',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "count", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'movingAverage',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: [10]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'movingMedian',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: ['5']
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'stdev',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }, { name: "tolerance", type: "int" }],
|
||||
defaultParams: [5,0.1]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'highestAverage',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "count", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'lowestAverage',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "count", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeAbovePercentile',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeAboveValue',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeBelowPercentile',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeBelowValue',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int" }],
|
||||
defaultParams: [5]
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'useSeriesAbove',
|
||||
category: categories.Filter,
|
||||
params: [
|
||||
{ name: "value", type: "int" },
|
||||
{ name: "search", type: "string" },
|
||||
{ name: "replace", type: "string" }
|
||||
],
|
||||
defaultParams: [0, 'search', 'replace']
|
||||
});
|
||||
|
||||
////////////////////
|
||||
// Graphite 1.0.x //
|
||||
////////////////////
|
||||
|
||||
addFuncDef({
|
||||
name: 'aggregateLine',
|
||||
category: categories.Combine,
|
||||
params: [{ name: "func", type: "select", options: ['sum', 'avg', 'min', 'max', 'last']}],
|
||||
defaultParams: ['avg'],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'averageOutsidePercentile',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [95],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'delay',
|
||||
category: categories.Transform,
|
||||
params: [{ name: 'steps', type: 'int', }],
|
||||
defaultParams: [1],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'exponentialMovingAverage',
|
||||
category: categories.Calculate,
|
||||
params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: [10],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'fallbackSeries',
|
||||
category: categories.Special,
|
||||
params: [{ name: 'fallback', type: 'string' }],
|
||||
defaultParams: ['constantLine(0)'],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "grep",
|
||||
category: categories.Filter,
|
||||
params: [{ name: "grep", type: 'string' }],
|
||||
defaultParams: ['grep'],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "groupByNodes",
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{
|
||||
name: "function",
|
||||
type: "string",
|
||||
options: ['sum', 'avg', 'maxSeries']
|
||||
},
|
||||
{ name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
],
|
||||
defaultParams: ["sum", 3],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'integralByInterval',
|
||||
category: categories.Transform,
|
||||
params: [{ name: "intervalUnit", type: "select", options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'] }],
|
||||
defaultParams: ['1d'],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'interpolate',
|
||||
category: categories.Transform,
|
||||
params: [{ name: 'limit', type: 'int', optional: true}],
|
||||
defaultParams: [],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'invert',
|
||||
category: categories.Transform,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'isNonNull',
|
||||
category: categories.Combine,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'linearRegression',
|
||||
category: categories.Calculate,
|
||||
params: [
|
||||
{ name: "startSourceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true },
|
||||
{ name: "endSourceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true }
|
||||
],
|
||||
defaultParams: [],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'mapSeries',
|
||||
shortName: 'map',
|
||||
params: [{ name: "node", type: 'int' }],
|
||||
defaultParams: [3],
|
||||
category: categories.Combine,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'movingMin',
|
||||
category: categories.Calculate,
|
||||
params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: [10],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'movingMax',
|
||||
category: categories.Calculate,
|
||||
params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: [10],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'movingSum',
|
||||
category: categories.Calculate,
|
||||
params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
|
||||
defaultParams: [10],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "multiplySeriesWithWildcards",
|
||||
category: categories.Calculate,
|
||||
params: [
|
||||
{ name: "position", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
{ name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
{ name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true },
|
||||
],
|
||||
defaultParams: [2],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'offsetToZero',
|
||||
category: categories.Transform,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'pow',
|
||||
category: categories.Transform,
|
||||
params: [{ name: 'factor', type: 'int' }],
|
||||
defaultParams: [10],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'powSeries',
|
||||
category: categories.Transform,
|
||||
params: optionalSeriesRefArgs,
|
||||
defaultParams: [''],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'reduceSeries',
|
||||
shortName: 'reduce',
|
||||
params: [
|
||||
{ name: "function", type: 'string', options: ['asPercent', 'diffSeries', 'divideSeries'] },
|
||||
{ name: "reduceNode", type: 'int', options: [0,1,2,3,4,5,6,7,8,9,10,11,12,13] },
|
||||
{ name: "reduceMatchers", type: 'string' },
|
||||
{ name: "reduceMatchers", type: 'string' },
|
||||
],
|
||||
defaultParams: ['asPercent', 2, 'used_bytes', 'total_bytes'],
|
||||
category: categories.Combine,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeBetweenPercentile',
|
||||
category: categories.Filter,
|
||||
params: [{ name: "n", type: "int", }],
|
||||
defaultParams: [95],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'removeEmptySeries',
|
||||
category: categories.Filter,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'squareRoot',
|
||||
category: categories.Transform,
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'timeSlice',
|
||||
category: categories.Transform,
|
||||
params: [
|
||||
{ name: "startSliceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d']},
|
||||
{ name: "endSliceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true }
|
||||
],
|
||||
defaultParams: ['-1h'],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'weightedAverage',
|
||||
category: categories.Filter,
|
||||
params: [
|
||||
{ name: 'other', type: 'value_or_series', optional: true },
|
||||
{ name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] },
|
||||
],
|
||||
defaultParams: ['#A', 4],
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: 'seriesByTag',
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{ name: "tagExpression", type: "string" },
|
||||
{ name: "tagExpression", type: "string", optional: true },
|
||||
{ name: "tagExpression", type: "string", optional: true },
|
||||
{ name: "tagExpression", type: "string", optional: true },
|
||||
],
|
||||
version: '1.1'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "groupByTags",
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{
|
||||
name: "function",
|
||||
type: "string",
|
||||
options: ['sum', 'avg', 'maxSeries']
|
||||
},
|
||||
{ name: "tag", type: "string" },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
],
|
||||
defaultParams: ["sum", "tag"],
|
||||
version: '1.1'
|
||||
});
|
||||
|
||||
addFuncDef({
|
||||
name: "aliasByTags",
|
||||
category: categories.Special,
|
||||
params: [
|
||||
{ name: "tag", type: "string" },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
{ name: "tag", type: "string", optional: true },
|
||||
],
|
||||
defaultParams: ["tag"],
|
||||
version: '1.1'
|
||||
});
|
||||
|
||||
_.each(categories, function(funcList, catName) {
|
||||
categories[catName] = _.sortBy(funcList, 'name');
|
||||
});
|
||||
|
||||
function FuncInstance(funcDef, options) {
|
||||
this.def = funcDef;
|
||||
this.params = [];
|
||||
|
||||
if (options && options.withDefaultParams) {
|
||||
this.params = funcDef.defaultParams.slice(0);
|
||||
}
|
||||
|
||||
this.updateText();
|
||||
}
|
||||
|
||||
FuncInstance.prototype.render = function(metricExp) {
|
||||
var str = this.def.name + '(';
|
||||
var parameters = _.map(this.params, function(value, index) {
|
||||
|
||||
var paramType = this.def.params[index].type;
|
||||
if (paramType === 'int' || paramType === 'value_or_series' || paramType === 'boolean') {
|
||||
return value;
|
||||
}
|
||||
else if (paramType === 'int_or_interval' && $.isNumeric(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return "'" + value + "'";
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if (metricExp) {
|
||||
parameters.unshift(metricExp);
|
||||
}
|
||||
|
||||
return str + parameters.join(', ') + ')';
|
||||
};
|
||||
|
||||
FuncInstance.prototype._hasMultipleParamsInString = function(strValue, index) {
|
||||
if (strValue.indexOf(',') === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.def.params[index + 1] && this.def.params[index + 1].optional;
|
||||
};
|
||||
|
||||
FuncInstance.prototype.updateParam = function(strValue, index) {
|
||||
// handle optional parameters
|
||||
// if string contains ',' and next param is optional, split and update both
|
||||
if (this._hasMultipleParamsInString(strValue, index)) {
|
||||
_.each(strValue.split(','), function(partVal, idx) {
|
||||
this.updateParam(partVal.trim(), index + idx);
|
||||
}.bind(this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (strValue === '' && this.def.params[index].optional) {
|
||||
this.params.splice(index, 1);
|
||||
}
|
||||
else {
|
||||
this.params[index] = strValue;
|
||||
}
|
||||
|
||||
this.updateText();
|
||||
};
|
||||
|
||||
FuncInstance.prototype.updateText = function () {
|
||||
if (this.params.length === 0) {
|
||||
this.text = this.def.name + '()';
|
||||
return;
|
||||
}
|
||||
|
||||
var text = this.def.name + '(';
|
||||
text += this.params.join(', ');
|
||||
text += ')';
|
||||
this.text = text;
|
||||
};
|
||||
|
||||
function isVersionRelatedFunction(func, graphiteVersion) {
|
||||
return isVersionGreaterOrEqual(graphiteVersion, func.version) || !func.version;
|
||||
}
|
||||
|
||||
function isVersionGreaterOrEqual(a, b) {
|
||||
var a_num = Number(a);
|
||||
var b_num = Number(b);
|
||||
return a_num >= b_num;
|
||||
}
|
||||
|
||||
return {
|
||||
createFuncInstance: function(funcDef, options) {
|
||||
if (_.isString(funcDef)) {
|
||||
if (!index[funcDef]) {
|
||||
throw { message: 'Method not found ' + name };
|
||||
}
|
||||
funcDef = index[funcDef];
|
||||
}
|
||||
return new FuncInstance(funcDef, options);
|
||||
},
|
||||
|
||||
getFuncDef: function(name) {
|
||||
return index[name];
|
||||
},
|
||||
|
||||
getCategories: function(graphiteVersion) {
|
||||
var filteredCategories = {};
|
||||
_.each(categories, function(functions, category) {
|
||||
var filteredFuncs = _.filter(functions, function(func) {
|
||||
return isVersionRelatedFunction(func, graphiteVersion);
|
||||
});
|
||||
if (filteredFuncs.length) {
|
||||
filteredCategories[category] = filteredFuncs;
|
||||
}
|
||||
});
|
||||
|
||||
return filteredCategories;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
1008
public/app/plugins/datasource/graphite/gfunc.ts
Normal file
1008
public/app/plugins/datasource/graphite/gfunc.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,23 @@
|
||||
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
import gfunc from '../gfunc';
|
||||
|
||||
describe('when creating func instance from func names', function() {
|
||||
it('should return func instance', function() {
|
||||
var func = gfunc.createFuncInstance('sumSeries');
|
||||
expect(func).to.be.ok();
|
||||
expect(func.def.name).to.equal('sumSeries');
|
||||
expect(func.def.params.length).to.equal(5);
|
||||
expect(func.def.defaultParams.length).to.equal(1);
|
||||
expect(func).toBeTruthy();
|
||||
expect(func.def.name).toEqual('sumSeries');
|
||||
expect(func.def.params.length).toEqual(5);
|
||||
expect(func.def.defaultParams.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should return func instance with shortName', function() {
|
||||
var func = gfunc.createFuncInstance('sum');
|
||||
expect(func).to.be.ok();
|
||||
expect(func).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return func instance from funcDef', function() {
|
||||
var func = gfunc.createFuncInstance('sum');
|
||||
var func2 = gfunc.createFuncInstance(func.def);
|
||||
expect(func2).to.be.ok();
|
||||
expect(func2).toBeTruthy();
|
||||
});
|
||||
|
||||
it('func instance should have text representation', function() {
|
||||
@ -27,7 +25,7 @@ describe('when creating func instance from func names', function() {
|
||||
func.params[0] = 5;
|
||||
func.params[1] = 'avg';
|
||||
func.updateText();
|
||||
expect(func.text).to.equal("groupByNode(5, avg)");
|
||||
expect(func.text).toEqual("groupByNode(5, avg)");
|
||||
});
|
||||
});
|
||||
|
||||
@ -35,51 +33,51 @@ describe('when rendering func instance', function() {
|
||||
|
||||
it('should handle single metric param', function() {
|
||||
var func = gfunc.createFuncInstance('sumSeries');
|
||||
expect(func.render('hello.metric')).to.equal("sumSeries(hello.metric)");
|
||||
expect(func.render('hello.metric')).toEqual("sumSeries(hello.metric)");
|
||||
});
|
||||
|
||||
it('should include default params if options enable it', function() {
|
||||
var func = gfunc.createFuncInstance('scaleToSeconds', { withDefaultParams: true });
|
||||
expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)");
|
||||
expect(func.render('hello')).toEqual("scaleToSeconds(hello, 1)");
|
||||
});
|
||||
|
||||
it('should handle int or interval params with number', function() {
|
||||
var func = gfunc.createFuncInstance('movingMedian');
|
||||
func.params[0] = '5';
|
||||
expect(func.render('hello')).to.equal("movingMedian(hello, 5)");
|
||||
expect(func.render('hello')).toEqual("movingMedian(hello, 5)");
|
||||
});
|
||||
|
||||
it('should handle int or interval params with interval string', function() {
|
||||
var func = gfunc.createFuncInstance('movingMedian');
|
||||
func.params[0] = '5min';
|
||||
expect(func.render('hello')).to.equal("movingMedian(hello, '5min')");
|
||||
expect(func.render('hello')).toEqual("movingMedian(hello, '5min')");
|
||||
});
|
||||
|
||||
it('should handle metric param and int param and string param', function() {
|
||||
var func = gfunc.createFuncInstance('groupByNode');
|
||||
func.params[0] = 5;
|
||||
func.params[1] = 'avg';
|
||||
expect(func.render('hello.metric')).to.equal("groupByNode(hello.metric, 5, 'avg')");
|
||||
expect(func.render('hello.metric')).toEqual("groupByNode(hello.metric, 5, 'avg')");
|
||||
});
|
||||
|
||||
it('should handle function with no metric param', function() {
|
||||
var func = gfunc.createFuncInstance('randomWalk');
|
||||
func.params[0] = 'test';
|
||||
expect(func.render(undefined)).to.equal("randomWalk('test')");
|
||||
expect(func.render(undefined)).toEqual("randomWalk('test')");
|
||||
});
|
||||
|
||||
it('should handle function multiple series params', function() {
|
||||
var func = gfunc.createFuncInstance('asPercent');
|
||||
func.params[0] = '#B';
|
||||
expect(func.render('#A')).to.equal("asPercent(#A, #B)");
|
||||
expect(func.render('#A')).toEqual("asPercent(#A, #B)");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('when requesting function categories', function() {
|
||||
it('should return function categories', function() {
|
||||
var catIndex = gfunc.getCategories();
|
||||
expect(catIndex.Special.length).to.be.greaterThan(8);
|
||||
var catIndex = gfunc.getCategories('1.0');
|
||||
expect(catIndex.Special.length).toBeGreaterThan(8);
|
||||
});
|
||||
});
|
||||
|
||||
@ -87,14 +85,14 @@ describe('when updating func param', function() {
|
||||
it('should update param value and update text representation', function() {
|
||||
var func = gfunc.createFuncInstance('summarize', { withDefaultParams: true });
|
||||
func.updateParam('1h', 0);
|
||||
expect(func.params[0]).to.be('1h');
|
||||
expect(func.text).to.be('summarize(1h, sum, false)');
|
||||
expect(func.params[0]).toBe('1h');
|
||||
expect(func.text).toBe('summarize(1h, sum, false)');
|
||||
});
|
||||
|
||||
it('should parse numbers as float', function() {
|
||||
var func = gfunc.createFuncInstance('scale');
|
||||
func.updateParam('0.001', 0);
|
||||
expect(func.params[0]).to.be('0.001');
|
||||
expect(func.params[0]).toBe('0.001');
|
||||
});
|
||||
});
|
||||
|
||||
@ -102,24 +100,24 @@ describe('when updating func param with optional second parameter', function() {
|
||||
it('should update value and text', function() {
|
||||
var func = gfunc.createFuncInstance('aliasByNode');
|
||||
func.updateParam('1', 0);
|
||||
expect(func.params[0]).to.be('1');
|
||||
expect(func.params[0]).toBe('1');
|
||||
});
|
||||
|
||||
it('should slit text and put value in second param', function() {
|
||||
var func = gfunc.createFuncInstance('aliasByNode');
|
||||
func.updateParam('4,-5', 0);
|
||||
expect(func.params[0]).to.be('4');
|
||||
expect(func.params[1]).to.be('-5');
|
||||
expect(func.text).to.be('aliasByNode(4, -5)');
|
||||
expect(func.params[0]).toBe('4');
|
||||
expect(func.params[1]).toBe('-5');
|
||||
expect(func.text).toBe('aliasByNode(4, -5)');
|
||||
});
|
||||
|
||||
it('should remove second param when empty string is set', function() {
|
||||
var func = gfunc.createFuncInstance('aliasByNode');
|
||||
func.updateParam('4,-5', 0);
|
||||
func.updateParam('', 1);
|
||||
expect(func.params[0]).to.be('4');
|
||||
expect(func.params[1]).to.be(undefined);
|
||||
expect(func.text).to.be('aliasByNode(4)');
|
||||
expect(func.params[0]).toBe('4');
|
||||
expect(func.params[1]).toBe(undefined);
|
||||
expect(func.text).toBe('aliasByNode(4)');
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
import {Lexer} from '../lexer';
|
||||
|
||||
describe('when lexing graphite expression', function() {
|
||||
@ -7,120 +5,120 @@ describe('when lexing graphite expression', function() {
|
||||
it('should tokenize metric expression', function() {
|
||||
var lexer = new Lexer('metric.test.*.asd.count');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].value).to.be('metric');
|
||||
expect(tokens[1].value).to.be('.');
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[4].pos).to.be(13);
|
||||
expect(tokens[0].value).toBe('metric');
|
||||
expect(tokens[1].value).toBe('.');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
expect(tokens[4].pos).toBe(13);
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with dash', function() {
|
||||
var lexer = new Lexer('metric.test.se1-server-*.asd.count');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[4].value).to.be('se1-server-*');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
expect(tokens[4].value).toBe('se1-server-*');
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with dash2', function() {
|
||||
var lexer = new Lexer('net.192-168-1-1.192-168-1-9.ping_value.*');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].value).to.be('net');
|
||||
expect(tokens[2].value).to.be('192-168-1-1');
|
||||
expect(tokens[0].value).toBe('net');
|
||||
expect(tokens[2].value).toBe('192-168-1-1');
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with equal sign', function() {
|
||||
var lexer = new Lexer('apps=test');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].value).to.be('apps=test');
|
||||
expect(tokens[0].value).toBe('apps=test');
|
||||
});
|
||||
|
||||
it('simple function2', function() {
|
||||
var lexer = new Lexer('offset(test.metric, -100)');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[6].type).to.be('number');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
expect(tokens[6].type).toBe('number');
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with curly braces', function() {
|
||||
var lexer = new Lexer('metric.se1-{first, second}.count');
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens.length).to.be(10);
|
||||
expect(tokens[3].type).to.be('{');
|
||||
expect(tokens[4].value).to.be('first');
|
||||
expect(tokens[5].value).to.be(',');
|
||||
expect(tokens[6].value).to.be('second');
|
||||
expect(tokens.length).toBe(10);
|
||||
expect(tokens[3].type).toBe('{');
|
||||
expect(tokens[4].value).toBe('first');
|
||||
expect(tokens[5].value).toBe(',');
|
||||
expect(tokens[6].value).toBe('second');
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with number segments', function() {
|
||||
var lexer = new Lexer("metric.10.12_10.test");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].type).to.be('identifier');
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[2].value).to.be('10');
|
||||
expect(tokens[4].value).to.be('12_10');
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[0].type).toBe('identifier');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[2].value).toBe('10');
|
||||
expect(tokens[4].value).toBe('12_10');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
});
|
||||
|
||||
it('should tokenize metric expression with segment that start with number', function() {
|
||||
var lexer = new Lexer("metric.001-server");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].type).to.be('identifier');
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens.length).to.be(3);
|
||||
expect(tokens[0].type).toBe('identifier');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should tokenize func call with numbered metric and number arg', function() {
|
||||
var lexer = new Lexer("scale(metric.10, 15)");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].type).to.be('identifier');
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[2].value).to.be('metric');
|
||||
expect(tokens[4].value).to.be('10');
|
||||
expect(tokens[4].type).to.be('number');
|
||||
expect(tokens[6].type).to.be('number');
|
||||
expect(tokens[0].type).toBe('identifier');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[2].value).toBe('metric');
|
||||
expect(tokens[4].value).toBe('10');
|
||||
expect(tokens[4].type).toBe('number');
|
||||
expect(tokens[6].type).toBe('number');
|
||||
});
|
||||
|
||||
it('should tokenize metric with template parameter', function() {
|
||||
var lexer = new Lexer("metric.[[server]].test");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[2].value).to.be('[[server]]');
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[2].value).toBe('[[server]]');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
});
|
||||
|
||||
it('should tokenize metric with question mark', function() {
|
||||
var lexer = new Lexer("metric.server_??.test");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[2].type).to.be('identifier');
|
||||
expect(tokens[2].value).to.be('server_??');
|
||||
expect(tokens[4].type).to.be('identifier');
|
||||
expect(tokens[2].type).toBe('identifier');
|
||||
expect(tokens[2].value).toBe('server_??');
|
||||
expect(tokens[4].type).toBe('identifier');
|
||||
});
|
||||
|
||||
it('should handle error with unterminated string', function() {
|
||||
var lexer = new Lexer("alias(metric, 'asd)");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[0].value).to.be('alias');
|
||||
expect(tokens[1].value).to.be('(');
|
||||
expect(tokens[2].value).to.be('metric');
|
||||
expect(tokens[3].value).to.be(',');
|
||||
expect(tokens[4].type).to.be('string');
|
||||
expect(tokens[4].isUnclosed).to.be(true);
|
||||
expect(tokens[4].pos).to.be(20);
|
||||
expect(tokens[0].value).toBe('alias');
|
||||
expect(tokens[1].value).toBe('(');
|
||||
expect(tokens[2].value).toBe('metric');
|
||||
expect(tokens[3].value).toBe(',');
|
||||
expect(tokens[4].type).toBe('string');
|
||||
expect(tokens[4].isUnclosed).toBe(true);
|
||||
expect(tokens[4].pos).toBe(20);
|
||||
});
|
||||
|
||||
it('should handle float parameters', function() {
|
||||
var lexer = new Lexer("alias(metric, 0.002)");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[4].type).to.be('number');
|
||||
expect(tokens[4].value).to.be('0.002');
|
||||
expect(tokens[4].type).toBe('number');
|
||||
expect(tokens[4].value).toBe('0.002');
|
||||
});
|
||||
|
||||
it('should handle bool parameters', function() {
|
||||
var lexer = new Lexer("alias(metric, true, false)");
|
||||
var tokens = lexer.tokenize();
|
||||
expect(tokens[4].type).to.be('bool');
|
||||
expect(tokens[4].value).to.be('true');
|
||||
expect(tokens[6].type).to.be('bool');
|
||||
expect(tokens[4].type).toBe('bool');
|
||||
expect(tokens[4].value).toBe('true');
|
||||
expect(tokens[6].type).toBe('bool');
|
||||
});
|
||||
});
|
182
public/app/plugins/datasource/graphite/specs/parser.jest.ts
Normal file
182
public/app/plugins/datasource/graphite/specs/parser.jest.ts
Normal file
@ -0,0 +1,182 @@
|
||||
import {Parser} from '../parser';
|
||||
|
||||
describe('when parsing', function() {
|
||||
|
||||
it('simple metric expression', function() {
|
||||
var parser = new Parser('metric.test.*.asd.count');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('metric');
|
||||
expect(rootNode.segments.length).toBe(5);
|
||||
expect(rootNode.segments[0].value).toBe('metric');
|
||||
});
|
||||
|
||||
it('simple metric expression with numbers in segments', function() {
|
||||
var parser = new Parser('metric.10.15_20.5');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('metric');
|
||||
expect(rootNode.segments.length).toBe(4);
|
||||
expect(rootNode.segments[1].value).toBe('10');
|
||||
expect(rootNode.segments[2].value).toBe('15_20');
|
||||
expect(rootNode.segments[3].value).toBe('5');
|
||||
});
|
||||
|
||||
it('simple metric expression with curly braces', function() {
|
||||
var parser = new Parser('metric.se1-{count, max}');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('metric');
|
||||
expect(rootNode.segments.length).toBe(2);
|
||||
expect(rootNode.segments[1].value).toBe('se1-{count,max}');
|
||||
});
|
||||
|
||||
it('simple metric expression with curly braces at start of segment and with post chars', function() {
|
||||
var parser = new Parser('metric.{count, max}-something.count');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('metric');
|
||||
expect(rootNode.segments.length).toBe(3);
|
||||
expect(rootNode.segments[1].value).toBe('{count,max}-something');
|
||||
});
|
||||
|
||||
it('simple function', function() {
|
||||
var parser = new Parser('sum(test)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params.length).toBe(1);
|
||||
});
|
||||
|
||||
it('simple function2', function() {
|
||||
var parser = new Parser('offset(test.metric, -100)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params[0].type).toBe('metric');
|
||||
expect(rootNode.params[1].type).toBe('number');
|
||||
});
|
||||
|
||||
it('simple function with string arg', function() {
|
||||
var parser = new Parser("randomWalk('test')");
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params.length).toBe(1);
|
||||
expect(rootNode.params[0].type).toBe('string');
|
||||
});
|
||||
|
||||
it('function with multiple args', function() {
|
||||
var parser = new Parser("sum(test, 1, 'test')");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params.length).toBe(3);
|
||||
expect(rootNode.params[0].type).toBe('metric');
|
||||
expect(rootNode.params[1].type).toBe('number');
|
||||
expect(rootNode.params[2].type).toBe('string');
|
||||
});
|
||||
|
||||
it('function with nested function', function() {
|
||||
var parser = new Parser("sum(scaleToSeconds(test, 1))");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params.length).toBe(1);
|
||||
expect(rootNode.params[0].type).toBe('function');
|
||||
expect(rootNode.params[0].name).toBe('scaleToSeconds');
|
||||
expect(rootNode.params[0].params.length).toBe(2);
|
||||
expect(rootNode.params[0].params[0].type).toBe('metric');
|
||||
expect(rootNode.params[0].params[1].type).toBe('number');
|
||||
});
|
||||
|
||||
it('function with multiple series', function() {
|
||||
var parser = new Parser("sum(test.test.*.count, test.timers.*.count)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params.length).toBe(2);
|
||||
expect(rootNode.params[0].type).toBe('metric');
|
||||
expect(rootNode.params[1].type).toBe('metric');
|
||||
});
|
||||
|
||||
it('function with templated series', function() {
|
||||
var parser = new Parser("sum(test.[[server]].count)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).toBe(undefined);
|
||||
expect(rootNode.params[0].type).toBe('metric');
|
||||
expect(rootNode.params[0].segments[1].type).toBe('segment');
|
||||
expect(rootNode.params[0].segments[1].value).toBe('[[server]]');
|
||||
});
|
||||
|
||||
it('invalid metric expression', function() {
|
||||
var parser = new Parser('metric.test.*.asd.');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).toBe('Expected metric identifier instead found end of string');
|
||||
expect(rootNode.pos).toBe(19);
|
||||
});
|
||||
|
||||
it('invalid function expression missing closing parenthesis', function() {
|
||||
var parser = new Parser('sum(test');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).toBe('Expected closing parenthesis instead found end of string');
|
||||
expect(rootNode.pos).toBe(9);
|
||||
});
|
||||
|
||||
it('unclosed string in function', function() {
|
||||
var parser = new Parser("sum('test)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).toBe('Unclosed string parameter');
|
||||
expect(rootNode.pos).toBe(11);
|
||||
});
|
||||
|
||||
it('handle issue #69', function() {
|
||||
var parser = new Parser('cactiStyle(offset(scale(net.192-168-1-1.192-168-1-9.ping_value.*,0.001),-100))');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
});
|
||||
|
||||
it('handle float function arguments', function() {
|
||||
var parser = new Parser('scale(test, 0.002)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params[1].type).toBe('number');
|
||||
expect(rootNode.params[1].value).toBe(0.002);
|
||||
});
|
||||
|
||||
it('handle curly brace pattern at start', function() {
|
||||
var parser = new Parser('{apps}.test');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('metric');
|
||||
expect(rootNode.segments[0].value).toBe('{apps}');
|
||||
expect(rootNode.segments[1].value).toBe('test');
|
||||
});
|
||||
|
||||
it('series parameters', function() {
|
||||
var parser = new Parser('asPercent(#A, #B)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params[0].type).toBe('series-ref');
|
||||
expect(rootNode.params[0].value).toBe('#A');
|
||||
expect(rootNode.params[1].value).toBe('#B');
|
||||
});
|
||||
|
||||
it('series parameters, issue 2788', function() {
|
||||
var parser = new Parser("summarize(diffSeries(#A, #B), '10m', 'sum', false)");
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).toBe('function');
|
||||
expect(rootNode.params[0].type).toBe('function');
|
||||
expect(rootNode.params[1].value).toBe('10m');
|
||||
expect(rootNode.params[3].type).toBe('bool');
|
||||
});
|
||||
|
||||
it('should parse metric expression with ip number segments', function() {
|
||||
var parser = new Parser('5.10.123.5');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.segments[0].value).toBe('5');
|
||||
expect(rootNode.segments[1].value).toBe('10');
|
||||
expect(rootNode.segments[2].value).toBe('123');
|
||||
expect(rootNode.segments[3].value).toBe('5');
|
||||
});
|
||||
});
|
@ -1,183 +0,0 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
import {Parser} from '../parser';
|
||||
|
||||
describe('when parsing', function() {
|
||||
|
||||
it('simple metric expression', function() {
|
||||
var parser = new Parser('metric.test.*.asd.count');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('metric');
|
||||
expect(rootNode.segments.length).to.be(5);
|
||||
expect(rootNode.segments[0].value).to.be('metric');
|
||||
});
|
||||
|
||||
it('simple metric expression with numbers in segments', function() {
|
||||
var parser = new Parser('metric.10.15_20.5');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('metric');
|
||||
expect(rootNode.segments.length).to.be(4);
|
||||
expect(rootNode.segments[1].value).to.be('10');
|
||||
expect(rootNode.segments[2].value).to.be('15_20');
|
||||
expect(rootNode.segments[3].value).to.be('5');
|
||||
});
|
||||
|
||||
it('simple metric expression with curly braces', function() {
|
||||
var parser = new Parser('metric.se1-{count, max}');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('metric');
|
||||
expect(rootNode.segments.length).to.be(2);
|
||||
expect(rootNode.segments[1].value).to.be('se1-{count,max}');
|
||||
});
|
||||
|
||||
it('simple metric expression with curly braces at start of segment and with post chars', function() {
|
||||
var parser = new Parser('metric.{count, max}-something.count');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('metric');
|
||||
expect(rootNode.segments.length).to.be(3);
|
||||
expect(rootNode.segments[1].value).to.be('{count,max}-something');
|
||||
});
|
||||
|
||||
it('simple function', function() {
|
||||
var parser = new Parser('sum(test)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params.length).to.be(1);
|
||||
});
|
||||
|
||||
it('simple function2', function() {
|
||||
var parser = new Parser('offset(test.metric, -100)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params[0].type).to.be('metric');
|
||||
expect(rootNode.params[1].type).to.be('number');
|
||||
});
|
||||
|
||||
it('simple function with string arg', function() {
|
||||
var parser = new Parser("randomWalk('test')");
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params.length).to.be(1);
|
||||
expect(rootNode.params[0].type).to.be('string');
|
||||
});
|
||||
|
||||
it('function with multiple args', function() {
|
||||
var parser = new Parser("sum(test, 1, 'test')");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params.length).to.be(3);
|
||||
expect(rootNode.params[0].type).to.be('metric');
|
||||
expect(rootNode.params[1].type).to.be('number');
|
||||
expect(rootNode.params[2].type).to.be('string');
|
||||
});
|
||||
|
||||
it('function with nested function', function() {
|
||||
var parser = new Parser("sum(scaleToSeconds(test, 1))");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params.length).to.be(1);
|
||||
expect(rootNode.params[0].type).to.be('function');
|
||||
expect(rootNode.params[0].name).to.be('scaleToSeconds');
|
||||
expect(rootNode.params[0].params.length).to.be(2);
|
||||
expect(rootNode.params[0].params[0].type).to.be('metric');
|
||||
expect(rootNode.params[0].params[1].type).to.be('number');
|
||||
});
|
||||
|
||||
it('function with multiple series', function() {
|
||||
var parser = new Parser("sum(test.test.*.count, test.timers.*.count)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params.length).to.be(2);
|
||||
expect(rootNode.params[0].type).to.be('metric');
|
||||
expect(rootNode.params[1].type).to.be('metric');
|
||||
});
|
||||
|
||||
it('function with templated series', function() {
|
||||
var parser = new Parser("sum(test.[[server]].count)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).to.be(undefined);
|
||||
expect(rootNode.params[0].type).to.be('metric');
|
||||
expect(rootNode.params[0].segments[1].type).to.be('segment');
|
||||
expect(rootNode.params[0].segments[1].value).to.be('[[server]]');
|
||||
});
|
||||
|
||||
it('invalid metric expression', function() {
|
||||
var parser = new Parser('metric.test.*.asd.');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).to.be('Expected metric identifier instead found end of string');
|
||||
expect(rootNode.pos).to.be(19);
|
||||
});
|
||||
|
||||
it('invalid function expression missing closing parenthesis', function() {
|
||||
var parser = new Parser('sum(test');
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).to.be('Expected closing parenthesis instead found end of string');
|
||||
expect(rootNode.pos).to.be(9);
|
||||
});
|
||||
|
||||
it('unclosed string in function', function() {
|
||||
var parser = new Parser("sum('test)");
|
||||
var rootNode = parser.getAst();
|
||||
|
||||
expect(rootNode.message).to.be('Unclosed string parameter');
|
||||
expect(rootNode.pos).to.be(11);
|
||||
});
|
||||
|
||||
it('handle issue #69', function() {
|
||||
var parser = new Parser('cactiStyle(offset(scale(net.192-168-1-1.192-168-1-9.ping_value.*,0.001),-100))');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
});
|
||||
|
||||
it('handle float function arguments', function() {
|
||||
var parser = new Parser('scale(test, 0.002)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params[1].type).to.be('number');
|
||||
expect(rootNode.params[1].value).to.be(0.002);
|
||||
});
|
||||
|
||||
it('handle curly brace pattern at start', function() {
|
||||
var parser = new Parser('{apps}.test');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('metric');
|
||||
expect(rootNode.segments[0].value).to.be('{apps}');
|
||||
expect(rootNode.segments[1].value).to.be('test');
|
||||
});
|
||||
|
||||
it('series parameters', function() {
|
||||
var parser = new Parser('asPercent(#A, #B)');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params[0].type).to.be('series-ref');
|
||||
expect(rootNode.params[0].value).to.be('#A');
|
||||
expect(rootNode.params[1].value).to.be('#B');
|
||||
});
|
||||
|
||||
it('series parameters, issue 2788', function() {
|
||||
var parser = new Parser("summarize(diffSeries(#A, #B), '10m', 'sum', false)");
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.type).to.be('function');
|
||||
expect(rootNode.params[0].type).to.be('function');
|
||||
expect(rootNode.params[1].value).to.be('10m');
|
||||
expect(rootNode.params[3].type).to.be('bool');
|
||||
});
|
||||
|
||||
it('should parse metric expression with ip number segments', function() {
|
||||
var parser = new Parser('5.10.123.5');
|
||||
var rootNode = parser.getAst();
|
||||
expect(rootNode.segments[0].value).to.be('5');
|
||||
expect(rootNode.segments[1].value).to.be('10');
|
||||
expect(rootNode.segments[2].value).to.be('123');
|
||||
expect(rootNode.segments[3].value).to.be('5');
|
||||
});
|
||||
});
|
@ -20,6 +20,10 @@ export class PostgresDatasource {
|
||||
return '\'' + value + '\'';
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
var quotedValues = _.map(value, function(val) {
|
||||
return '\'' + val + '\'';
|
||||
});
|
||||
|
@ -16,8 +16,8 @@ class PostgresConfigCtrl {
|
||||
|
||||
const defaultQuery = `SELECT
|
||||
extract(epoch from time_column) AS time,
|
||||
title_column as title,
|
||||
description_column as text
|
||||
text_column as text,
|
||||
tags_column as tags
|
||||
FROM
|
||||
metric_table
|
||||
WHERE
|
||||
|
@ -8,7 +8,7 @@ export class PromCompleter {
|
||||
labelNameCache: any;
|
||||
labelValueCache: any;
|
||||
|
||||
identifierRegexps = [/[\[\]a-zA-Z_0-9=]/];
|
||||
identifierRegexps = [/\[/, /[a-zA-Z0-9_:]/];
|
||||
|
||||
constructor(private datasource: PrometheusDatasource) {
|
||||
this.labelQueryCache = {};
|
||||
@ -73,13 +73,15 @@ export class PromCompleter {
|
||||
});
|
||||
}
|
||||
|
||||
if (prefix === '[') {
|
||||
if (token.type === 'paren.lparen' && token.value === '[') {
|
||||
var vectors = [];
|
||||
for (let unit of ['s', 'm', 'h']) {
|
||||
for (let value of [1,5,10,30]) {
|
||||
vectors.push({caption: value+unit, value: '['+value+unit, meta: 'range vector'});
|
||||
}
|
||||
}
|
||||
vectors.push({caption: '$__interval', value: '[$__interval', meta: 'range vector'});
|
||||
vectors.push({caption: '$__interval_ms', value: '[$__interval_ms', meta: 'range vector'});
|
||||
callback(null, vectors);
|
||||
return;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ export class PrometheusDatasource {
|
||||
if (interval !== 0 && range / intervalFactor / interval > 11000) {
|
||||
interval = Math.ceil(range / intervalFactor / 11000);
|
||||
}
|
||||
return Math.max(interval * intervalFactor, minInterval);
|
||||
return Math.max(interval * intervalFactor, minInterval, 1);
|
||||
}
|
||||
|
||||
performTimeSeriesQuery(query, start, end) {
|
||||
|
@ -43,10 +43,10 @@ var PrometheusHighlightRules = function() {
|
||||
regex : "\\d+[smhdwy]"
|
||||
}, {
|
||||
token : keywordMapper,
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
regex : "[a-zA-Z_:][a-zA-Z0-9_:]*"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\+|\\-|\\*|\\/|%|\\^|=|==|!=|<=|>=|<|>|=\\~|!\\~"
|
||||
regex : "\\+|\\-|\\*|\\/|%|\\^|==|!=|<=|>=|<|>"
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "[[(]"
|
||||
@ -75,8 +75,7 @@ var PrometheusHighlightRules = function() {
|
||||
regex : '"[^"]*"|\'[^\']*\''
|
||||
}, {
|
||||
token : "punctuation.operator",
|
||||
regex : ",",
|
||||
push : 'start-label-matcher'
|
||||
regex : ","
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : "}",
|
||||
@ -112,11 +111,6 @@ var keyWordsCompletions = prometheusKeyWords.map(function(word) {
|
||||
});
|
||||
|
||||
var prometheusFunctions = [
|
||||
{
|
||||
name: 'abs()', value: 'abs',
|
||||
def: 'abs(v instant-vector)',
|
||||
docText: 'Returns the input vector with all sample values converted to their absolute value.'
|
||||
},
|
||||
{
|
||||
name: 'abs()', value: 'abs',
|
||||
def: 'abs(v instant-vector)',
|
||||
|
@ -44,12 +44,18 @@ describe('Prometheus editor completer', function() {
|
||||
describe('When inside brackets', () => {
|
||||
it('Should return range vectors', () => {
|
||||
const session = getSessionStub({
|
||||
currentToken: {},
|
||||
tokens: [],
|
||||
line: '',
|
||||
currentToken: {type: 'paren.lparen', value: '[', index: 2, start: 9},
|
||||
tokens: [
|
||||
{type: 'identifier', value: 'node_cpu'},
|
||||
{type: 'paren.lparen', value: '['}
|
||||
],
|
||||
line: 'node_cpu[',
|
||||
});
|
||||
completer.getCompletions(editor, session, {row: 0, column: 10}, '[', (s, res) => {
|
||||
expect(res[0]).to.eql({caption: '1s', value: '[1s', meta: 'range vector'});
|
||||
|
||||
return completer.getCompletions(editor, session, {row: 0, column: 10}, '[', (s, res) => {
|
||||
expect(res[0].caption).to.eql('1s');
|
||||
expect(res[0].value).to.eql('[1s');
|
||||
expect(res[0].meta).to.eql('range vector');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -294,6 +294,20 @@ describe('PrometheusDatasource', function() {
|
||||
ctx.ds.query(query);
|
||||
ctx.$httpBackend.verifyNoOutstandingExpectation();
|
||||
});
|
||||
|
||||
it('step should never go below 1', function() {
|
||||
var query = {
|
||||
// 6 hour range
|
||||
range: { from: moment(1508318768202), to: moment(1508318770118) },
|
||||
targets: [{expr: 'test'}],
|
||||
interval: '100ms'
|
||||
};
|
||||
var urlExpected = 'proxied/api/v1/query_range?query=test&start=1508318769&end=1508318771&step=1';
|
||||
ctx.$httpBackend.expect('GET', urlExpected).respond(response);
|
||||
ctx.ds.query(query);
|
||||
ctx.$httpBackend.verifyNoOutstandingExpectation();
|
||||
});
|
||||
|
||||
it('should be auto interval when greater than min interval', function() {
|
||||
var query = {
|
||||
// 6 hour range
|
||||
|
@ -34,7 +34,7 @@ class GettingStartedPanelCtrl extends PanelCtrl {
|
||||
check: () => {
|
||||
return $q.when(
|
||||
datasourceSrv.getMetricSources().filter(item => {
|
||||
return item.meta.builtIn === false;
|
||||
return item.meta.builtIn !== true;
|
||||
}).length > 0
|
||||
);
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ function graphDirective($rootScope, timeSrv, popoverSrv, contextSrv) {
|
||||
eventManager.addFlotEvents(annotations, options);
|
||||
configureAxisOptions(data, options);
|
||||
|
||||
sortedSeries = _.sortBy(data, function(series) { return series.zindex; });
|
||||
sortedSeries = sortSeries(data, ctrl.panel);
|
||||
|
||||
function callPlot(incrementRenderCounter) {
|
||||
try {
|
||||
@ -374,6 +374,41 @@ function graphDirective($rootScope, timeSrv, popoverSrv, contextSrv) {
|
||||
}
|
||||
}
|
||||
|
||||
function sortSeries(series, panel) {
|
||||
var sortBy = panel.legend.sort;
|
||||
var sortOrder = panel.legend.sortDesc;
|
||||
var haveSortBy = sortBy !== null || sortBy !== undefined;
|
||||
var haveSortOrder = sortOrder !== null || sortOrder !== undefined;
|
||||
|
||||
if (panel.stack && haveSortBy && haveSortOrder) {
|
||||
var desc = desc = panel.legend.sortDesc === true ? 1 : -1;
|
||||
series.sort((x, y) => {
|
||||
if (x.stats[sortBy] > y.stats[sortBy]) {
|
||||
return 1 * desc;
|
||||
}
|
||||
if (x.stats[sortBy] < y.stats[sortBy]) {
|
||||
return -1 * desc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
series.sort((x, y) => {
|
||||
if (x.zindex > y.zindex) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (x.zindex < y.zindex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
function translateFillOption(fill) {
|
||||
if (panel.percentage && panel.stack) {
|
||||
return fill === 0 ? 0.001 : fill/10;
|
||||
|
@ -80,13 +80,13 @@ function (angular, _, $) {
|
||||
if (panel.legend.sortDesc === false) {
|
||||
panel.legend.sort = null;
|
||||
panel.legend.sortDesc = null;
|
||||
render();
|
||||
ctrl.render();
|
||||
return;
|
||||
}
|
||||
|
||||
panel.legend.sortDesc = !panel.legend.sortDesc;
|
||||
panel.legend.sort = stat;
|
||||
render();
|
||||
ctrl.render();
|
||||
}
|
||||
|
||||
function getTableHeaderHtml(statName) {
|
||||
|
@ -15,16 +15,16 @@ describe('grafanaGraph', function() {
|
||||
beforeEach(angularMocks.module('grafana.core'));
|
||||
|
||||
function graphScenario(desc, func, elementWidth = 500) {
|
||||
describe(desc, function() {
|
||||
describe(desc, () => {
|
||||
var ctx: any = {};
|
||||
|
||||
ctx.setup = function(setupFunc) {
|
||||
ctx.setup = (setupFunc) => {
|
||||
|
||||
beforeEach(angularMocks.module(function($provide) {
|
||||
beforeEach(angularMocks.module(($provide) => {
|
||||
$provide.value("timeSrv", new helpers.TimeSrvStub());
|
||||
}));
|
||||
|
||||
beforeEach(angularMocks.inject(function($rootScope, $compile) {
|
||||
beforeEach(angularMocks.inject(($rootScope, $compile) => {
|
||||
var ctrl: any = {
|
||||
height: 200,
|
||||
panel: {
|
||||
@ -75,7 +75,7 @@ describe('grafanaGraph', function() {
|
||||
alias: 'series1'
|
||||
}));
|
||||
ctx.data.push(new TimeSeries({
|
||||
datapoints: [[1,1],[2,2]],
|
||||
datapoints: [[1,10],[2,20]],
|
||||
alias: 'series2'
|
||||
}));
|
||||
|
||||
@ -96,15 +96,15 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
}
|
||||
|
||||
graphScenario('simple lines options', function(ctx) {
|
||||
ctx.setup(function(ctrl) {
|
||||
graphScenario('simple lines options', (ctx) => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.lines = true;
|
||||
ctrl.panel.fill = 5;
|
||||
ctrl.panel.linewidth = 3;
|
||||
ctrl.panel.steppedLine = true;
|
||||
});
|
||||
|
||||
it('should configure plot with correct options', function() {
|
||||
it('should configure plot with correct options', () => {
|
||||
expect(ctx.plotOptions.series.lines.show).to.be(true);
|
||||
expect(ctx.plotOptions.series.lines.fill).to.be(0.5);
|
||||
expect(ctx.plotOptions.series.lines.lineWidth).to.be(3);
|
||||
@ -112,6 +112,55 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
graphScenario('sort series as legend', (ctx) => {
|
||||
describe("with sort as legend undefined", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = undefined;
|
||||
});
|
||||
|
||||
it("should not modify order of time series", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
});
|
||||
|
||||
describe("with sort as legend set to min. descending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
});
|
||||
|
||||
it("highest value should be first", () => {
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
});
|
||||
});
|
||||
|
||||
describe("with sort as legend set to min. ascending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'min';
|
||||
ctrl.panel.legend.sortDesc = true;
|
||||
});
|
||||
|
||||
it("lowest value should be first", () => {
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
});
|
||||
});
|
||||
|
||||
describe("with sort as legend set to current. ascending order", () => {
|
||||
ctx.setup((ctrl) => {
|
||||
ctrl.panel.legend.sort = 'current';
|
||||
ctrl.panel.legend.sortDesc = false;
|
||||
});
|
||||
|
||||
it("highest last value should be first", () => {
|
||||
expect(ctx.plotData[1].alias).to.be('series2');
|
||||
expect(ctx.plotData[0].alias).to.be('series1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
graphScenario('when logBase is log 10', function(ctx) {
|
||||
ctx.setup(function(ctrl, data) {
|
||||
ctrl.panel.yaxes[0].logBase = 10;
|
||||
@ -251,7 +300,7 @@ describe('grafanaGraph', function() {
|
||||
});
|
||||
|
||||
it('should set barWidth', function() {
|
||||
expect(ctx.plotOptions.series.bars.barWidth).to.be(1/1.5);
|
||||
expect(ctx.plotOptions.series.bars.barWidth).to.be(10/1.5);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -152,7 +152,7 @@ function drawLegendValues(elem, colorScale, rangeFrom, rangeTo, maxValue, minVal
|
||||
.tickSize(2);
|
||||
|
||||
let colorRect = legendElem.find(":first-child");
|
||||
let posY = colorRect.height() + 2;
|
||||
let posY = getSvgElemHeight(legendElem) + 2;
|
||||
let posX = getSvgElemX(colorRect);
|
||||
|
||||
d3.select(legendElem.get(0)).append("g")
|
||||
@ -256,7 +256,16 @@ function getOpacityScale(options, maxValue, minValue = 0) {
|
||||
function getSvgElemX(elem) {
|
||||
let svgElem = elem.get(0);
|
||||
if (svgElem && svgElem.x && svgElem.x.baseVal) {
|
||||
return elem.get(0).x.baseVal.value;
|
||||
return svgElem.x.baseVal.value;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function getSvgElemHeight(elem) {
|
||||
let svgElem = elem.get(0);
|
||||
if (svgElem && svgElem.height && svgElem.height.baseVal) {
|
||||
return svgElem.height.baseVal.value;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import {MetricsPanelCtrl} from 'app/plugins/sdk';
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import TimeSeries from 'app/core/time_series';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import {axesEditor} from './axes_editor';
|
||||
import {heatmapDisplayEditor} from './display_editor';
|
||||
import rendering from './rendering';
|
||||
import {convertToHeatMap, convertToCards, elasticHistogramToHeatmap, calculateBucketSize, getMinLog} from './heatmap_data_converter';
|
||||
import {convertToHeatMap, convertToCards, elasticHistogramToHeatmap, calculateBucketSize } from './heatmap_data_converter';
|
||||
|
||||
let X_BUCKET_NUMBER_DEFAULT = 30;
|
||||
let Y_BUCKET_NUMBER_DEFAULT = 10;
|
||||
@ -250,7 +248,6 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
|
||||
});
|
||||
|
||||
series.flotpairs = series.getFlotPairs(this.panel.nullPointMode);
|
||||
series.minLog = getMinLog(series);
|
||||
|
||||
let datapoints = seriesData.datapoints || [];
|
||||
if (datapoints && datapoints.length > 0) {
|
||||
@ -266,7 +263,7 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
|
||||
|
||||
parseSeries(series) {
|
||||
let min = _.min(_.map(series, s => s.stats.min));
|
||||
let minLog = _.min(_.map(series, s => s.minLog));
|
||||
let minLog = _.min(_.map(series, s => s.stats.logmin));
|
||||
let max = _.max(_.map(series, s => s.stats.max));
|
||||
|
||||
return {
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
let VALUE_INDEX = 0;
|
||||
@ -320,12 +318,6 @@ function convertToLogScaleValueBuckets(xBucket, yBucketSplitFactor, logBase) {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
// Get minimum non zero value.
|
||||
function getMinLog(series) {
|
||||
let values = _.compact(_.map(series.datapoints, p => p[0]));
|
||||
return _.min(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logarithm for custom base
|
||||
* @param value
|
||||
@ -432,7 +424,6 @@ export {
|
||||
elasticHistogramToHeatmap,
|
||||
convertToCards,
|
||||
mergeZeroBuckets,
|
||||
getMinLog,
|
||||
getValueBucketBound,
|
||||
isHeatmapDataEqual,
|
||||
calculateBucketSize
|
||||
|
@ -71,9 +71,8 @@ export default function link(scope, elem, attrs, ctrl) {
|
||||
function getYAxisWidth(elem) {
|
||||
let axis_text = elem.selectAll(".axis-y text").nodes();
|
||||
let max_text_width = _.max(_.map(axis_text, text => {
|
||||
let el = $(text);
|
||||
// Use JQuery outerWidth() to compute full element width
|
||||
return el.outerWidth();
|
||||
// Use SVG getBBox method
|
||||
return text.getBBox().width;
|
||||
}));
|
||||
|
||||
return max_text_width;
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import { describe, beforeEach, it, expect } from '../../../../../test/lib/common';
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
@ -45,23 +43,23 @@ describe('isHeatmapDataEqual', () => {
|
||||
let emptyValues = _.cloneDeep(ctx.heatmapA);
|
||||
emptyValues['1422774000000'].buckets['1'].values = [];
|
||||
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, ctx.heatmapB)).to.be(true);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapB, ctx.heatmapA)).to.be(true);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, ctx.heatmapB)).toBe(true);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapB, ctx.heatmapA)).toBe(true);
|
||||
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapC)).to.be(true);
|
||||
expect(isHeatmapDataEqual(heatmapC, ctx.heatmapA)).to.be(true);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapC)).toBe(true);
|
||||
expect(isHeatmapDataEqual(heatmapC, ctx.heatmapA)).toBe(true);
|
||||
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapD)).to.be(false);
|
||||
expect(isHeatmapDataEqual(heatmapD, ctx.heatmapA)).to.be(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapD)).toBe(false);
|
||||
expect(isHeatmapDataEqual(heatmapD, ctx.heatmapA)).toBe(false);
|
||||
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapE)).to.be(false);
|
||||
expect(isHeatmapDataEqual(heatmapE, ctx.heatmapA)).to.be(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapE)).toBe(false);
|
||||
expect(isHeatmapDataEqual(heatmapE, ctx.heatmapA)).toBe(false);
|
||||
|
||||
expect(isHeatmapDataEqual(empty, ctx.heatmapA)).to.be(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, empty)).to.be(false);
|
||||
expect(isHeatmapDataEqual(empty, ctx.heatmapA)).toBe(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, empty)).toBe(false);
|
||||
|
||||
expect(isHeatmapDataEqual(emptyValues, ctx.heatmapA)).to.be(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, emptyValues)).to.be(false);
|
||||
expect(isHeatmapDataEqual(emptyValues, ctx.heatmapA)).toBe(false);
|
||||
expect(isHeatmapDataEqual(ctx.heatmapA, emptyValues)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -87,7 +85,7 @@ describe('calculateBucketSize', () => {
|
||||
it('should properly calculate bucket size', () => {
|
||||
_.each(ctx.bounds_set, (b) => {
|
||||
let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
|
||||
expect(bucketSize).to.be(b.size);
|
||||
expect(bucketSize).toBe(b.size);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -108,7 +106,7 @@ describe('calculateBucketSize', () => {
|
||||
it('should properly calculate bucket size', () => {
|
||||
_.each(ctx.bounds_set, (b) => {
|
||||
let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
|
||||
expect(isEqual(bucketSize, b.size)).to.be(true);
|
||||
expect(isEqual(bucketSize, b.size)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -162,7 +160,7 @@ describe('HeatmapDataConverter', () => {
|
||||
};
|
||||
|
||||
let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
|
||||
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true);
|
||||
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -190,7 +188,7 @@ describe('HeatmapDataConverter', () => {
|
||||
};
|
||||
|
||||
let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
|
||||
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true);
|
||||
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -240,7 +238,7 @@ describe('ES Histogram converter', () => {
|
||||
};
|
||||
|
||||
let heatmap = elasticHistogramToHeatmap(ctx.series);
|
||||
expect(heatmap).to.eql(expectedHeatmap);
|
||||
expect(heatmap).toMatchObject(expectedHeatmap);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -273,13 +271,13 @@ describe('convertToCards', () => {
|
||||
{x: 1422774060000, y: 2, count: 2, values: [2, 3], yBounds: {}}
|
||||
];
|
||||
let res = convertToCards(buckets);
|
||||
expect(res.cards).to.eql(expectedCards);
|
||||
expect(res.cards).toMatchObject(expectedCards);
|
||||
});
|
||||
|
||||
it('should build proper cards stats', () => {
|
||||
let expectedStats = {min: 1, max: 2};
|
||||
let res = convertToCards(buckets);
|
||||
expect(res.cardStats).to.eql(expectedStats);
|
||||
expect(res.cardStats).toMatchObject(expectedStats);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
|
@ -1,5 +1,3 @@
|
||||
import {describe, it, expect} from 'test/lib/common';
|
||||
|
||||
import _ from 'lodash';
|
||||
import TableModel from 'app/core/table_model';
|
||||
import {TableRenderer} from '../renderer';
|
||||
@ -92,84 +90,84 @@ describe('when rendering table', () => {
|
||||
|
||||
it('time column should be formated', () => {
|
||||
var html = renderer.renderCell(0, 0, 1388556366666);
|
||||
expect(html).to.be('<td>2014-01-01T06:06:06Z</td>');
|
||||
expect(html).toBe('<td>2014-01-01T06:06:06Z</td>');
|
||||
});
|
||||
|
||||
it('undefined time column should be rendered as -', () => {
|
||||
var html = renderer.renderCell(0, 0, undefined);
|
||||
expect(html).to.be('<td>-</td>');
|
||||
expect(html).toBe('<td>-</td>');
|
||||
});
|
||||
|
||||
it('null time column should be rendered as -', () => {
|
||||
var html = renderer.renderCell(0, 0, null);
|
||||
expect(html).to.be('<td>-</td>');
|
||||
expect(html).toBe('<td>-</td>');
|
||||
});
|
||||
|
||||
it('number column with unit specified should ignore style unit', () => {
|
||||
var html = renderer.renderCell(5, 0, 1230);
|
||||
expect(html).to.be('<td>1.23 kbps</td>');
|
||||
expect(html).toBe('<td>1.23 kbps</td>');
|
||||
});
|
||||
|
||||
it('number column should be formated', () => {
|
||||
var html = renderer.renderCell(1, 0, 1230);
|
||||
expect(html).to.be('<td>1.230 s</td>');
|
||||
expect(html).toBe('<td>1.230 s</td>');
|
||||
});
|
||||
|
||||
it('number style should ignore string values', () => {
|
||||
var html = renderer.renderCell(1, 0, 'asd');
|
||||
expect(html).to.be('<td>asd</td>');
|
||||
expect(html).toBe('<td>asd</td>');
|
||||
});
|
||||
|
||||
it('colored cell should have style', () => {
|
||||
var html = renderer.renderCell(2, 0, 40);
|
||||
expect(html).to.be('<td style="color:green">40.0</td>');
|
||||
expect(html).toBe('<td style="color:green">40.0</td>');
|
||||
});
|
||||
|
||||
it('colored cell should have style', () => {
|
||||
var html = renderer.renderCell(2, 0, 55);
|
||||
expect(html).to.be('<td style="color:orange">55.0</td>');
|
||||
expect(html).toBe('<td style="color:orange">55.0</td>');
|
||||
});
|
||||
|
||||
it('colored cell should have style', () => {
|
||||
var html = renderer.renderCell(2, 0, 85);
|
||||
expect(html).to.be('<td style="color:red">85.0</td>');
|
||||
expect(html).toBe('<td style="color:red">85.0</td>');
|
||||
});
|
||||
|
||||
it('unformated undefined should be rendered as string', () => {
|
||||
var html = renderer.renderCell(3, 0, 'value');
|
||||
expect(html).to.be('<td>value</td>');
|
||||
expect(html).toBe('<td>value</td>');
|
||||
});
|
||||
|
||||
it('string style with escape html should return escaped html', () => {
|
||||
var html = renderer.renderCell(4, 0, "&breaking <br /> the <br /> row");
|
||||
expect(html).to.be('<td>&breaking <br /> the <br /> row</td>');
|
||||
expect(html).toBe('<td>&breaking <br /> the <br /> row</td>');
|
||||
});
|
||||
|
||||
it('undefined formater should return escaped html', () => {
|
||||
var html = renderer.renderCell(3, 0, "&breaking <br /> the <br /> row");
|
||||
expect(html).to.be('<td>&breaking <br /> the <br /> row</td>');
|
||||
expect(html).toBe('<td>&breaking <br /> the <br /> row</td>');
|
||||
});
|
||||
|
||||
it('undefined value should render as -', () => {
|
||||
var html = renderer.renderCell(3, 0, undefined);
|
||||
expect(html).to.be('<td></td>');
|
||||
expect(html).toBe('<td></td>');
|
||||
});
|
||||
|
||||
it('sanitized value should render as', () => {
|
||||
var html = renderer.renderCell(6, 0, 'text <a href="http://google.com">link</a>');
|
||||
expect(html).to.be('<td>sanitized</td>');
|
||||
expect(html).toBe('<td>sanitized</td>');
|
||||
});
|
||||
|
||||
it('Time column title should be Timestamp', () => {
|
||||
expect(table.columns[0].title).to.be('Timestamp');
|
||||
expect(table.columns[0].title).toBe('Timestamp');
|
||||
});
|
||||
|
||||
it('Value column title should be Val', () => {
|
||||
expect(table.columns[1].title).to.be('Val');
|
||||
expect(table.columns[1].title).toBe('Val');
|
||||
});
|
||||
|
||||
it('Colored column title should be Colored', () => {
|
||||
expect(table.columns[2].title).to.be('Colored');
|
||||
expect(table.columns[2].title).toBe('Colored');
|
||||
});
|
||||
|
||||
it('link should render as', () => {
|
||||
@ -182,7 +180,7 @@ describe('when rendering table', () => {
|
||||
</a>
|
||||
</td>
|
||||
`;
|
||||
expect(normalize(html)).to.be(normalize(expectedHtml));
|
||||
expect(normalize(html)).toBe(normalize(expectedHtml));
|
||||
});
|
||||
});
|
||||
});
|
@ -1,5 +1,3 @@
|
||||
import {describe, beforeEach, it, expect} from 'test/lib/common';
|
||||
|
||||
import {transformers, transformDataToTable} from '../transformers';
|
||||
|
||||
describe('when transforming time series table', () => {
|
||||
@ -29,18 +27,18 @@ describe('when transforming time series table', () => {
|
||||
});
|
||||
|
||||
it('should return 3 rows', () => {
|
||||
expect(table.rows.length).to.be(3);
|
||||
expect(table.rows[0][1]).to.be('series1');
|
||||
expect(table.rows[1][1]).to.be('series1');
|
||||
expect(table.rows[2][1]).to.be('series2');
|
||||
expect(table.rows[0][2]).to.be(12.12);
|
||||
expect(table.rows.length).toBe(3);
|
||||
expect(table.rows[0][1]).toBe('series1');
|
||||
expect(table.rows[1][1]).toBe('series1');
|
||||
expect(table.rows[2][1]).toBe('series2');
|
||||
expect(table.rows[0][2]).toBe(12.12);
|
||||
});
|
||||
|
||||
it('should return 3 rows', () => {
|
||||
expect(table.columns.length).to.be(3);
|
||||
expect(table.columns[0].text).to.be('Time');
|
||||
expect(table.columns[1].text).to.be('Metric');
|
||||
expect(table.columns[2].text).to.be('Value');
|
||||
expect(table.columns.length).toBe(3);
|
||||
expect(table.columns[0].text).toBe('Time');
|
||||
expect(table.columns[1].text).toBe('Metric');
|
||||
expect(table.columns[2].text).toBe('Value');
|
||||
});
|
||||
});
|
||||
|
||||
@ -54,20 +52,20 @@ describe('when transforming time series table', () => {
|
||||
});
|
||||
|
||||
it ('should return 3 columns', () => {
|
||||
expect(table.columns.length).to.be(3);
|
||||
expect(table.columns[0].text).to.be('Time');
|
||||
expect(table.columns[1].text).to.be('series1');
|
||||
expect(table.columns[2].text).to.be('series2');
|
||||
expect(table.columns.length).toBe(3);
|
||||
expect(table.columns[0].text).toBe('Time');
|
||||
expect(table.columns[1].text).toBe('series1');
|
||||
expect(table.columns[2].text).toBe('series2');
|
||||
});
|
||||
|
||||
it ('should return 2 rows', () => {
|
||||
expect(table.rows.length).to.be(2);
|
||||
expect(table.rows[0][1]).to.be(12.12);
|
||||
expect(table.rows[0][2]).to.be(16.12);
|
||||
expect(table.rows.length).toBe(2);
|
||||
expect(table.rows[0][1]).toBe(12.12);
|
||||
expect(table.rows[0][2]).toBe(16.12);
|
||||
});
|
||||
|
||||
it ('should be undefined when no value for timestamp', () => {
|
||||
expect(table.rows[1][2]).to.be(undefined);
|
||||
expect(table.rows[1][2]).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@ -83,17 +81,17 @@ describe('when transforming time series table', () => {
|
||||
});
|
||||
|
||||
it('should return 2 rows', () => {
|
||||
expect(table.rows.length).to.be(2);
|
||||
expect(table.rows[0][0]).to.be('series1');
|
||||
expect(table.rows[0][1]).to.be(14.44);
|
||||
expect(table.rows[0][2]).to.be(12.12);
|
||||
expect(table.rows.length).toBe(2);
|
||||
expect(table.rows[0][0]).toBe('series1');
|
||||
expect(table.rows[0][1]).toBe(14.44);
|
||||
expect(table.rows[0][2]).toBe(12.12);
|
||||
});
|
||||
|
||||
it('should return 2 columns', () => {
|
||||
expect(table.columns.length).to.be(3);
|
||||
expect(table.columns[0].text).to.be('Metric');
|
||||
expect(table.columns[1].text).to.be('Max');
|
||||
expect(table.columns[2].text).to.be('Min');
|
||||
expect(table.columns.length).toBe(3);
|
||||
expect(table.columns[0].text).toBe('Metric');
|
||||
expect(table.columns[1].text).toBe('Max');
|
||||
expect(table.columns[2].text).toBe('Min');
|
||||
});
|
||||
});
|
||||
|
||||
@ -124,9 +122,9 @@ describe('when transforming time series table', () => {
|
||||
describe('getColumns', function() {
|
||||
it('should return nested properties', function() {
|
||||
var columns = transformers['json'].getColumns(rawData);
|
||||
expect(columns[0].text).to.be('timestamp');
|
||||
expect(columns[1].text).to.be('message');
|
||||
expect(columns[2].text).to.be('nested.level2');
|
||||
expect(columns[0].text).toBe('timestamp');
|
||||
expect(columns[1].text).toBe('message');
|
||||
expect(columns[2].text).toBe('nested.level2');
|
||||
});
|
||||
});
|
||||
|
||||
@ -136,17 +134,17 @@ describe('when transforming time series table', () => {
|
||||
});
|
||||
|
||||
it ('should return 2 columns', () => {
|
||||
expect(table.columns.length).to.be(3);
|
||||
expect(table.columns[0].text).to.be('Timestamp');
|
||||
expect(table.columns[1].text).to.be('Message');
|
||||
expect(table.columns[2].text).to.be('nested.level2');
|
||||
expect(table.columns.length).toBe(3);
|
||||
expect(table.columns[0].text).toBe('Timestamp');
|
||||
expect(table.columns[1].text).toBe('Message');
|
||||
expect(table.columns[2].text).toBe('nested.level2');
|
||||
});
|
||||
|
||||
it ('should return 2 rows', () => {
|
||||
expect(table.rows.length).to.be(1);
|
||||
expect(table.rows[0][0]).to.be('time');
|
||||
expect(table.rows[0][1]).to.be('message');
|
||||
expect(table.rows[0][2]).to.be('level2-value');
|
||||
expect(table.rows.length).toBe(1);
|
||||
expect(table.rows[0][0]).toBe('time');
|
||||
expect(table.rows[0][1]).toBe('message');
|
||||
expect(table.rows[0][2]).toBe('level2-value');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -169,16 +167,16 @@ describe('when transforming time series table', () => {
|
||||
});
|
||||
|
||||
it ('should return 4 columns', () => {
|
||||
expect(table.columns.length).to.be(4);
|
||||
expect(table.columns[0].text).to.be('Time');
|
||||
expect(table.columns[1].text).to.be('Title');
|
||||
expect(table.columns[2].text).to.be('Text');
|
||||
expect(table.columns[3].text).to.be('Tags');
|
||||
expect(table.columns.length).toBe(4);
|
||||
expect(table.columns[0].text).toBe('Time');
|
||||
expect(table.columns[1].text).toBe('Title');
|
||||
expect(table.columns[2].text).toBe('Text');
|
||||
expect(table.columns[3].text).toBe('Tags');
|
||||
});
|
||||
|
||||
it ('should return 1 rows', () => {
|
||||
expect(table.rows.length).to.be(1);
|
||||
expect(table.rows[0][0]).to.be(1000);
|
||||
expect(table.rows.length).toBe(1);
|
||||
expect(table.rows[0][0]).toBe(1000);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import flatten from '../../../core/utils/flatten';
|
||||
import TimeSeries from '../../../core/time_series2';
|
||||
|
@ -1,339 +0,0 @@
|
||||
define([
|
||||
'app/core/utils/kbn',
|
||||
'app/core/utils/datemath',
|
||||
'moment'
|
||||
], function(kbn, dateMath, moment) {
|
||||
'use strict';
|
||||
|
||||
describe('unit format menu', function() {
|
||||
var menu = kbn.getUnitFormats();
|
||||
menu.map(function(submenu) {
|
||||
describe('submenu ' + submenu.text, function() {
|
||||
it('should have a title', function() { expect(submenu.text).to.be.a('string'); });
|
||||
it('should have a submenu', function() { expect(submenu.submenu).to.be.an('array'); });
|
||||
submenu.submenu.map(function(entry) {
|
||||
describe('entry ' + entry.text, function() {
|
||||
it('should have a title', function() { expect(entry.text).to.be.a('string'); });
|
||||
it('should have a format', function() { expect(entry.value).to.be.a('string'); });
|
||||
it('should have a valid format', function() {
|
||||
expect(kbn.valueFormats[entry.value]).to.be.a('function');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function describeValueFormat(desc, value, tickSize, tickDecimals, result) {
|
||||
|
||||
describe('value format: ' + desc, function() {
|
||||
it('should translate ' + value + ' as ' + result, function() {
|
||||
var scaledDecimals = tickDecimals - Math.floor(Math.log(tickSize) / Math.LN10);
|
||||
var str = kbn.valueFormats[desc](value, tickDecimals, scaledDecimals);
|
||||
expect(str).to.be(result);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
describeValueFormat('ms', 0.0024, 0.0005, 4, '0.0024 ms');
|
||||
describeValueFormat('ms', 100, 1, 0, '100 ms');
|
||||
describeValueFormat('ms', 1250, 10, 0, '1.25 s');
|
||||
describeValueFormat('ms', 1250, 300, 0, '1.3 s');
|
||||
describeValueFormat('ms', 65150, 10000, 0, '1.1 min');
|
||||
describeValueFormat('ms', 6515000, 1500000, 0, '1.8 hour');
|
||||
describeValueFormat('ms', 651500000, 150000000, 0, '8 day');
|
||||
|
||||
describeValueFormat('none', 2.75e-10, 0, 10, '3e-10');
|
||||
describeValueFormat('none', 0, 0, 2, '0');
|
||||
describeValueFormat('dB', 10, 1000, 2, '10.00 dB');
|
||||
|
||||
describeValueFormat('percent', 0, 0, 0, '0%');
|
||||
describeValueFormat('percent', 53, 0, 1, '53.0%');
|
||||
describeValueFormat('percentunit', 0.0, 0, 0, '0%');
|
||||
describeValueFormat('percentunit', 0.278, 0, 1, '27.8%');
|
||||
describeValueFormat('percentunit', 1.0, 0, 0, '100%');
|
||||
|
||||
describeValueFormat('currencyUSD', 7.42, 10000, 2, '$7.42');
|
||||
describeValueFormat('currencyUSD', 1532.82, 1000, 1, '$1.53K');
|
||||
describeValueFormat('currencyUSD', 18520408.7, 10000000, 0, '$19M');
|
||||
|
||||
describeValueFormat('bytes', -1.57e+308, -1.57e+308, 2, 'NA');
|
||||
|
||||
describeValueFormat('ns', 25, 1, 0, '25 ns');
|
||||
describeValueFormat('ns', 2558, 50, 0, '2.56 µs');
|
||||
|
||||
describeValueFormat('ops', 123, 1, 0, '123 ops');
|
||||
describeValueFormat('rps', 456000, 1000, -1, '456K rps');
|
||||
describeValueFormat('rps', 123456789, 1000000, 2, '123.457M rps');
|
||||
describeValueFormat('wps', 789000000, 1000000, -1, '789M wps');
|
||||
describeValueFormat('iops', 11000000000, 1000000000, -1, '11B iops');
|
||||
|
||||
describeValueFormat('s', 1.23456789e-7, 1e-10, 8, '123.5 ns');
|
||||
describeValueFormat('s', 1.23456789e-4, 1e-7, 5, '123.5 µs');
|
||||
describeValueFormat('s', 1.23456789e-3, 1e-6, 4, '1.235 ms');
|
||||
describeValueFormat('s', 1.23456789e-2, 1e-5, 3, '12.35 ms');
|
||||
describeValueFormat('s', 1.23456789e-1, 1e-4, 2, '123.5 ms');
|
||||
describeValueFormat('s', 24, 1, 0, '24 s');
|
||||
describeValueFormat('s', 246, 1, 0, '4.1 min');
|
||||
describeValueFormat('s', 24567, 100, 0, '6.82 hour');
|
||||
describeValueFormat('s', 24567890, 10000, 0, '40.62 week');
|
||||
describeValueFormat('s', 24567890000, 1000000, 0, '778.53 year');
|
||||
|
||||
describeValueFormat('m', 24, 1, 0, '24 min');
|
||||
describeValueFormat('m', 246, 10, 0, '4.1 hour');
|
||||
describeValueFormat('m', 6545, 10, 0, '4.55 day');
|
||||
describeValueFormat('m', 24567, 100, 0, '2.44 week');
|
||||
describeValueFormat('m', 24567892, 10000, 0, '46.7 year');
|
||||
|
||||
describeValueFormat('h', 21, 1, 0, '21 hour');
|
||||
describeValueFormat('h', 145, 1, 0, '6.04 day');
|
||||
describeValueFormat('h', 1234, 100, 0, '7.3 week');
|
||||
describeValueFormat('h', 9458, 1000, 0, '1.08 year');
|
||||
|
||||
describeValueFormat('d', 3, 1, 0, '3 day');
|
||||
describeValueFormat('d', 245, 100, 0, '35 week');
|
||||
describeValueFormat('d', 2456, 10, 0, '6.73 year');
|
||||
|
||||
describe('date time formats', function() {
|
||||
it('should format as iso date', function() {
|
||||
var str = kbn.valueFormats.dateTimeAsIso(1505634997920, 1);
|
||||
expect(str).to.be(moment(1505634997920).format('YYYY-MM-DD HH:mm:ss'));
|
||||
});
|
||||
|
||||
it('should format as iso date and skip date when today', function() {
|
||||
var now = moment();
|
||||
var str = kbn.valueFormats.dateTimeAsIso(now.valueOf(), 1);
|
||||
expect(str).to.be(now.format("HH:mm:ss"));
|
||||
});
|
||||
|
||||
it('should format as US date', function() {
|
||||
var str = kbn.valueFormats.dateTimeAsUS(1505634997920, 1);
|
||||
expect(str).to.be(moment(1505634997920).format('MM/DD/YYYY H:mm:ss a'));
|
||||
});
|
||||
|
||||
it('should format as US date and skip date when today', function() {
|
||||
var now = moment();
|
||||
var str = kbn.valueFormats.dateTimeAsUS(now.valueOf(), 1);
|
||||
expect(str).to.be(now.format("h:mm:ss a"));
|
||||
});
|
||||
|
||||
it('should format as from now with days', function() {
|
||||
var daysAgo = moment().add(-7, 'd');
|
||||
var str = kbn.valueFormats.dateTimeFromNow(daysAgo.valueOf(), 1);
|
||||
expect(str).to.be('7 days ago');
|
||||
});
|
||||
|
||||
it('should format as from now with minutes', function() {
|
||||
var daysAgo = moment().add(-2, 'm');
|
||||
var str = kbn.valueFormats.dateTimeFromNow(daysAgo.valueOf(), 1);
|
||||
expect(str).to.be('2 minutes ago');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn.toFixed and negative decimals', function() {
|
||||
it('should treat as zero decimals', function() {
|
||||
var str = kbn.toFixed(186.123, -2);
|
||||
expect(str).to.be('186');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn ms format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['ms'](10000086.123, 1, null);
|
||||
expect(str).to.be('2.8 hour');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn kbytes format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['kbytes'](10000000, 3, null);
|
||||
expect(str).to.be('9.537 GiB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn deckbytes format when scaled decimals is null do not use it', function() {
|
||||
it('should use specified decimals', function() {
|
||||
var str = kbn.valueFormats['deckbytes'](10000000, 3, null);
|
||||
expect(str).to.be('10.000 GB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('kbn roundValue', function() {
|
||||
it('should should handle null value', function() {
|
||||
var str = kbn.roundValue(null, 2);
|
||||
expect(str).to.be(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calculateInterval', function() {
|
||||
it('1h 100 resultion', function() {
|
||||
var range = { from: dateMath.parse('now-1h'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 100, null);
|
||||
expect(res.interval).to.be('30s');
|
||||
});
|
||||
|
||||
it('10m 1600 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-10m'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1600, null);
|
||||
expect(res.interval).to.be('500ms');
|
||||
expect(res.intervalMs).to.be(500);
|
||||
});
|
||||
|
||||
it('fixed user min interval', function() {
|
||||
var range = {from: dateMath.parse('now-10m'), to: dateMath.parse('now')};
|
||||
var res = kbn.calculateInterval(range, 1600, '10s');
|
||||
expect(res.interval).to.be('10s');
|
||||
expect(res.intervalMs).to.be(10000);
|
||||
});
|
||||
|
||||
it('short time range and user low limit', function() {
|
||||
var range = { from: dateMath.parse('now-10m'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1600, '>10s');
|
||||
expect(res.interval).to.be('10s');
|
||||
});
|
||||
|
||||
it('large time range and user low limit', function() {
|
||||
var range = {from: dateMath.parse('now-14d'), to: dateMath.parse('now')};
|
||||
var res = kbn.calculateInterval(range, 1000, '>10s');
|
||||
expect(res.interval).to.be('20m');
|
||||
});
|
||||
|
||||
it('10s 900 resolution and user low limit in ms', function() {
|
||||
var range = { from: dateMath.parse('now-10s'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 900, '>15ms');
|
||||
expect(res.interval).to.be('15ms');
|
||||
});
|
||||
|
||||
it('1d 1 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-1d'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1, null);
|
||||
expect(res.interval).to.be('1d');
|
||||
expect(res.intervalMs).to.be(86400000);
|
||||
});
|
||||
|
||||
it('86399s 1 resolution', function() {
|
||||
var range = { from: dateMath.parse('now-86390s'), to: dateMath.parse('now') };
|
||||
var res = kbn.calculateInterval(range, 1, null);
|
||||
expect(res.interval).to.be('12h');
|
||||
expect(res.intervalMs).to.be(43200000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hex', function() {
|
||||
it('positive integer', function() {
|
||||
var str = kbn.valueFormats.hex(100, 0);
|
||||
expect(str).to.be('64');
|
||||
});
|
||||
it('negative integer', function() {
|
||||
var str = kbn.valueFormats.hex(-100, 0);
|
||||
expect(str).to.be('-64');
|
||||
});
|
||||
it('null', function() {
|
||||
var str = kbn.valueFormats.hex(null, 0);
|
||||
expect(str).to.be('');
|
||||
});
|
||||
it('positive float', function() {
|
||||
var str = kbn.valueFormats.hex(50.52, 1);
|
||||
expect(str).to.be('32.8');
|
||||
});
|
||||
it('negative float', function() {
|
||||
var str = kbn.valueFormats.hex(-50.333, 2);
|
||||
expect(str).to.be('-32.547AE147AE14');
|
||||
});
|
||||
});
|
||||
|
||||
describe('hex 0x', function() {
|
||||
it('positive integeter', function() {
|
||||
var str = kbn.valueFormats.hex0x(7999,0);
|
||||
expect(str).to.be('0x1F3F');
|
||||
});
|
||||
it('negative integer', function() {
|
||||
var str = kbn.valueFormats.hex0x(-584,0);
|
||||
expect(str).to.be('-0x248');
|
||||
});
|
||||
it('null', function() {
|
||||
var str = kbn.valueFormats.hex0x(null, 0);
|
||||
expect(str).to.be('');
|
||||
});
|
||||
it('positive float', function() {
|
||||
var str = kbn.valueFormats.hex0x(74.443, 3);
|
||||
expect(str).to.be('0x4A.716872B020C4');
|
||||
});
|
||||
it('negative float', function() {
|
||||
var str = kbn.valueFormats.hex0x(-65.458, 1);
|
||||
expect(str).to.be('-0x41.8');
|
||||
});
|
||||
});
|
||||
|
||||
describe('duration', function() {
|
||||
it('null', function() {
|
||||
var str = kbn.toDuration(null, 0, "millisecond");
|
||||
expect(str).to.be('');
|
||||
});
|
||||
it('0 milliseconds', function() {
|
||||
var str = kbn.toDuration(0, 0, "millisecond");
|
||||
expect(str).to.be('0 milliseconds');
|
||||
});
|
||||
it('1 millisecond', function() {
|
||||
var str = kbn.toDuration(1, 0, "millisecond");
|
||||
expect(str).to.be('1 millisecond');
|
||||
});
|
||||
it('-1 millisecond', function() {
|
||||
var str = kbn.toDuration(-1, 0, "millisecond");
|
||||
expect(str).to.be('1 millisecond ago');
|
||||
});
|
||||
it('seconds', function() {
|
||||
var str = kbn.toDuration(1, 0, "second");
|
||||
expect(str).to.be('1 second');
|
||||
});
|
||||
it('minutes', function() {
|
||||
var str = kbn.toDuration(1, 0, "minute");
|
||||
expect(str).to.be('1 minute');
|
||||
});
|
||||
it('hours', function() {
|
||||
var str = kbn.toDuration(1, 0, "hour");
|
||||
expect(str).to.be('1 hour');
|
||||
});
|
||||
it('days', function() {
|
||||
var str = kbn.toDuration(1, 0, "day");
|
||||
expect(str).to.be('1 day');
|
||||
});
|
||||
it('weeks', function() {
|
||||
var str = kbn.toDuration(1, 0, "week");
|
||||
expect(str).to.be('1 week');
|
||||
});
|
||||
it('months', function() {
|
||||
var str = kbn.toDuration(1, 0, "month");
|
||||
expect(str).to.be('1 month');
|
||||
});
|
||||
it('years', function() {
|
||||
var str = kbn.toDuration(1, 0, "year");
|
||||
expect(str).to.be('1 year');
|
||||
});
|
||||
it('decimal days', function() {
|
||||
var str = kbn.toDuration(1.5, 2, "day");
|
||||
expect(str).to.be('1 day, 12 hours, 0 minutes');
|
||||
});
|
||||
it('decimal months', function() {
|
||||
var str = kbn.toDuration(1.5, 3, "month");
|
||||
expect(str).to.be('1 month, 2 weeks, 1 day, 0 hours');
|
||||
});
|
||||
it('no decimals', function() {
|
||||
var str = kbn.toDuration(38898367008, 0, "millisecond");
|
||||
expect(str).to.be('1 year');
|
||||
});
|
||||
it('1 decimal', function() {
|
||||
var str = kbn.toDuration(38898367008, 1, "millisecond");
|
||||
expect(str).to.be('1 year, 2 months');
|
||||
});
|
||||
it('too many decimals', function() {
|
||||
var str = kbn.toDuration(38898367008, 20, "millisecond");
|
||||
expect(str).to.be('1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, 7 seconds, 8 milliseconds');
|
||||
});
|
||||
it('floating point error', function() {
|
||||
var str = kbn.toDuration(36993906007, 8, "millisecond");
|
||||
expect(str).to.be('1 year, 2 months, 0 weeks, 3 days, 4 hours, 5 minutes, 6 seconds, 7 milliseconds');
|
||||
});
|
||||
});
|
||||
});
|
4
public/test/jest-setup.ts
Normal file
4
public/test/jest-setup.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
configure({ adapter: new Adapter() });
|
6
public/test/jest-shim.ts
Normal file
6
public/test/jest-shim.ts
Normal file
@ -0,0 +1,6 @@
|
||||
declare var global: NodeJS.Global;
|
||||
|
||||
(<any>global).requestAnimationFrame = (callback) => {
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
|
@ -16,8 +16,16 @@ rm -rf node_modules
|
||||
npm install -g yarn --quiet
|
||||
yarn install --pure-lockfile --no-progress
|
||||
|
||||
exit_if_fail npm test
|
||||
exit_if_fail npm build
|
||||
exit_if_fail npm run test-ci
|
||||
exit_if_fail npm run build
|
||||
|
||||
# publish code coverage
|
||||
echo "Publishing javascript code coverage"
|
||||
bash <(curl -s https://codecov.io/bash) -cF javascript
|
||||
rm -rf coverage
|
||||
# npm install -g codecov
|
||||
# codecov
|
||||
# cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
echo "running go fmt"
|
||||
exit_if_fail test -z "$(gofmt -s -l ./pkg | tee /dev/stderr)"
|
||||
@ -29,4 +37,17 @@ echo "building binaries"
|
||||
exit_if_fail go run build.go build
|
||||
|
||||
echo "running go test"
|
||||
exit_if_fail go test -v ./pkg/...
|
||||
|
||||
set -e
|
||||
echo "" > coverage.txt
|
||||
|
||||
for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -race -coverprofile=profile.out -covermode=atomic $d
|
||||
if [ -f profile.out ]; then
|
||||
cat profile.out >> coverage.txt
|
||||
rm profile.out
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Publishing go code coverage"
|
||||
bash <(curl -s https://codecov.io/bash) -cF go
|
||||
|
@ -14,6 +14,7 @@ module.exports = function(grunt) {
|
||||
'jshint',
|
||||
'sasslint',
|
||||
'exec:tslint',
|
||||
"exec:jest",
|
||||
'karma:test',
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
@ -1,6 +1,13 @@
|
||||
module.exports = function(config, grunt) {
|
||||
'use strict'
|
||||
|
||||
var coverage = '';
|
||||
if (config.coverage) {
|
||||
coverage = '--coverage';
|
||||
}
|
||||
|
||||
return {
|
||||
tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json --type-check",
|
||||
tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json",
|
||||
jest : "node ./node_modules/jest-cli/bin/jest.js " + coverage,
|
||||
};
|
||||
};
|
||||
|
@ -26,6 +26,10 @@ module.exports = merge(common, {
|
||||
]
|
||||
},
|
||||
|
||||
devServer: {
|
||||
stats: 'errors-only',
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new ExtractTextPlugin({
|
||||
filename: 'grafana.[name].css',
|
||||
|
@ -2,7 +2,8 @@
|
||||
"rules": {
|
||||
"no-string-throw": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-variable": true,
|
||||
"no-unused-variable": false,
|
||||
"no-use-before-declare": false,
|
||||
"no-duplicate-variable": true,
|
||||
"curly": true,
|
||||
"class-name": true,
|
||||
@ -33,7 +34,6 @@
|
||||
"no-string-literal": false,
|
||||
"no-switch-case-fall-through": false,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [true,
|
||||
|
Loading…
Reference in New Issue
Block a user