mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'master' into react-panels-step1
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -69,7 +69,6 @@ debug.test
|
|||||||
/vendor/**/*.yml
|
/vendor/**/*.yml
|
||||||
/vendor/**/*_test.go
|
/vendor/**/*_test.go
|
||||||
/vendor/**/.editorconfig
|
/vendor/**/.editorconfig
|
||||||
/vendor/**/appengine*
|
|
||||||
*.orig
|
*.orig
|
||||||
|
|
||||||
/devenv/bulk-dashboards/*.json
|
/devenv/bulk-dashboards/*.json
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
* **Datasource Proxy**: Keep trailing slash for datasource proxy requests [#13326](https://github.com/grafana/grafana/pull/13326), thx [@ryantxu](https://github.com/ryantxu)
|
* **Datasource Proxy**: Keep trailing slash for datasource proxy requests [#13326](https://github.com/grafana/grafana/pull/13326), thx [@ryantxu](https://github.com/ryantxu)
|
||||||
* **Elasticsearch**: Fix no limit size in terms aggregation for alerting queries [#13172](https://github.com/grafana/grafana/issues/13172), thx [@Yukinoshita-Yukino](https://github.com/Yukinoshita-Yukino)
|
* **Elasticsearch**: Fix no limit size in terms aggregation for alerting queries [#13172](https://github.com/grafana/grafana/issues/13172), thx [@Yukinoshita-Yukino](https://github.com/Yukinoshita-Yukino)
|
||||||
|
* **Units**: New clock time format, to format ms or second values as for example `01h:59m`, [#13635](https://github.com/grafana/grafana/issues/13635), thx [@franciscocpg](https://github.com/franciscocpg)
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
# 5.3.1 (unreleased)
|
# 5.3.1 (unreleased)
|
||||||
|
|
||||||
* **Render**: Fix PhantomJS render of graph panel when legend displayed as table to the right [#13616](https://github.com/grafana/grafana/issues/13616)
|
* **Render**: Fix PhantomJS render of graph panel when legend displayed as table to the right [#13616](https://github.com/grafana/grafana/issues/13616)
|
||||||
|
* **Stackdriver**: Filter option disappears after removing initial filter [#13607](https://github.com/grafana/grafana/issues/13607)
|
||||||
|
|
||||||
# 5.3.0 (2018-10-10)
|
# 5.3.0 (2018-10-10)
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@
|
|||||||
* **Profile**: List teams that the user is member of in current/active organization [#12476](https://github.com/grafana/grafana/issues/12476)
|
* **Profile**: List teams that the user is member of in current/active organization [#12476](https://github.com/grafana/grafana/issues/12476)
|
||||||
* **Configuration**: Allow auto-assigning users to specific organization (other than Main. Org) [#1823](https://github.com/grafana/grafana/issues/1823) [#12801](https://github.com/grafana/grafana/issues/12801), thx [@gzzo](https://github.com/gzzo) and [@ofosos](https://github.com/ofosos)
|
* **Configuration**: Allow auto-assigning users to specific organization (other than Main. Org) [#1823](https://github.com/grafana/grafana/issues/1823) [#12801](https://github.com/grafana/grafana/issues/12801), thx [@gzzo](https://github.com/gzzo) and [@ofosos](https://github.com/ofosos)
|
||||||
* **Dataproxy**: Pass configured/auth headers to a Datasource [#10971](https://github.com/grafana/grafana/issues/10971), thx [@mrsiano](https://github.com/mrsiano)
|
* **Dataproxy**: Pass configured/auth headers to a Datasource [#10971](https://github.com/grafana/grafana/issues/10971), thx [@mrsiano](https://github.com/mrsiano)
|
||||||
* ****: **: CloudWatch GetMetricData support [#11487](https://github.com/grafana/grafana/issues/11487), thx [@mtanda](https://github.com/mtanda)
|
* **CloudWatch**: GetMetricData support [#11487](https://github.com/grafana/grafana/issues/11487), thx [@mtanda](https://github.com/mtanda)
|
||||||
* **Postgres**: TimescaleDB support, e.g. use `time_bucket` for grouping by time when option enabled [#12680](https://github.com/grafana/grafana/pull/12680), thx [svenklemm](https://github.com/svenklemm)
|
* **Postgres**: TimescaleDB support, e.g. use `time_bucket` for grouping by time when option enabled [#12680](https://github.com/grafana/grafana/pull/12680), thx [svenklemm](https://github.com/svenklemm)
|
||||||
* **Cleanup**: Make temp file time to live configurable [#11607](https://github.com/grafana/grafana/issues/11607), thx [@xapon](https://github.com/xapon)
|
* **Cleanup**: Make temp file time to live configurable [#11607](https://github.com/grafana/grafana/issues/11607), thx [@xapon](https://github.com/xapon)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ weight = 1
|
|||||||
|
|
||||||
# Developer Guide
|
# Developer Guide
|
||||||
|
|
||||||
You can extend Grafana by writing your own plugins and then share then with other users in [our plugin repository](https://grafana.com/plugins).
|
You can extend Grafana by writing your own plugins and then share them with other users in [our plugin repository](https://grafana.com/plugins).
|
||||||
|
|
||||||
## Short version
|
## Short version
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ There are two blog posts about authoring a plugin that might also be of interest
|
|||||||
## What languages?
|
## What languages?
|
||||||
|
|
||||||
Since everything turns into javascript it's up to you to choose which language you want. That said it's probably a good idea to choose es6 or typescript since
|
Since everything turns into javascript it's up to you to choose which language you want. That said it's probably a good idea to choose es6 or typescript since
|
||||||
we use es6 classes in Grafana. So it's easier to get inspiration from the Grafana repo is you choose one of those languages.
|
we use es6 classes in Grafana. So it's easier to get inspiration from the Grafana repo if you choose one of those languages.
|
||||||
|
|
||||||
## Buildscript
|
## Buildscript
|
||||||
|
|
||||||
@@ -60,7 +60,6 @@ and [apps]({{< relref "apps.md" >}}) plugins in the documentation.
|
|||||||
The Grafana SDK is quite small so far and can be found here:
|
The Grafana SDK is quite small so far and can be found here:
|
||||||
|
|
||||||
- [SDK file in Grafana](https://github.com/grafana/grafana/blob/master/public/app/plugins/sdk.ts)
|
- [SDK file in Grafana](https://github.com/grafana/grafana/blob/master/public/app/plugins/sdk.ts)
|
||||||
- [SDK Readme](https://github.com/grafana/grafana/blob/master/public/app/plugins/plugin_api.md)
|
|
||||||
|
|
||||||
The SDK contains three different plugin classes: PanelCtrl, MetricsPanelCtrl and QueryCtrl. For plugins of the panel type, the module.js file should export one of these. There are some extra classes for [data sources]({{< relref "datasources.md" >}}).
|
The SDK contains three different plugin classes: PanelCtrl, MetricsPanelCtrl and QueryCtrl. For plugins of the panel type, the module.js file should export one of these. There are some extra classes for [data sources]({{< relref "datasources.md" >}}).
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
"style-loader": "^0.21.0",
|
"style-loader": "^0.21.0",
|
||||||
"systemjs": "0.20.19",
|
"systemjs": "0.20.19",
|
||||||
"systemjs-plugin-css": "^0.1.36",
|
"systemjs-plugin-css": "^0.1.36",
|
||||||
"ts-jest": "^23.1.4",
|
"ts-jest": "^23.10.4",
|
||||||
"ts-loader": "^5.1.0",
|
"ts-loader": "^5.1.0",
|
||||||
"tslib": "^1.9.3",
|
"tslib": "^1.9.3",
|
||||||
"tslint": "^5.8.0",
|
"tslint": "^5.8.0",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/registry"
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
|
"github.com/grafana/grafana/pkg/services/hooks"
|
||||||
"github.com/grafana/grafana/pkg/services/rendering"
|
"github.com/grafana/grafana/pkg/services/rendering"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
@@ -52,6 +53,7 @@ type HTTPServer struct {
|
|||||||
Bus bus.Bus `inject:""`
|
Bus bus.Bus `inject:""`
|
||||||
RenderService rendering.Service `inject:""`
|
RenderService rendering.Service `inject:""`
|
||||||
Cfg *setting.Cfg `inject:""`
|
Cfg *setting.Cfg `inject:""`
|
||||||
|
HooksService *hooks.HooksService `inject:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *HTTPServer) Init() error {
|
func (hs *HTTPServer) Init() error {
|
||||||
|
|||||||
@@ -316,19 +316,6 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.IsGrafanaAdmin {
|
if c.IsGrafanaAdmin {
|
||||||
children := []*dtos.NavLink{
|
|
||||||
{Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users", Icon: "gicon gicon-user"},
|
|
||||||
{Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs", Icon: "gicon gicon-org"},
|
|
||||||
{Text: "Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings", Icon: "gicon gicon-preferences"},
|
|
||||||
{Text: "Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats", Icon: "fa fa-fw fa-bar-chart"},
|
|
||||||
}
|
|
||||||
|
|
||||||
if setting.IsEnterprise {
|
|
||||||
children = append(children, &dtos.NavLink{Text: "Licensing", Id: "licensing", Url: setting.AppSubUrl + "/admin/licensing", Icon: "fa fa-fw fa-unlock-alt"})
|
|
||||||
}
|
|
||||||
|
|
||||||
children = append(children, &dtos.NavLink{Text: "Style Guide", Id: "styleguide", Url: setting.AppSubUrl + "/styleguide", Icon: "fa fa-fw fa-eyedropper"})
|
|
||||||
|
|
||||||
cfgNode.Children = append(cfgNode.Children, &dtos.NavLink{
|
cfgNode.Children = append(cfgNode.Children, &dtos.NavLink{
|
||||||
Text: "Server Admin",
|
Text: "Server Admin",
|
||||||
HideFromTabs: true,
|
HideFromTabs: true,
|
||||||
@@ -336,7 +323,13 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
|||||||
Id: "admin",
|
Id: "admin",
|
||||||
Icon: "gicon gicon-shield",
|
Icon: "gicon gicon-shield",
|
||||||
Url: setting.AppSubUrl + "/admin/users",
|
Url: setting.AppSubUrl + "/admin/users",
|
||||||
Children: children,
|
Children: []*dtos.NavLink{
|
||||||
|
{Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users", Icon: "gicon gicon-user"},
|
||||||
|
{Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs", Icon: "gicon gicon-org"},
|
||||||
|
{Text: "Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings", Icon: "gicon gicon-preferences"},
|
||||||
|
{Text: "Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats", Icon: "fa fa-fw fa-bar-chart"},
|
||||||
|
{Text: "Style Guide", Id: "styleguide", Url: setting.AppSubUrl + "/styleguide", Icon: "fa fa-fw fa-eyedropper"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,6 +350,7 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
hs.HooksService.RunIndexDataHooks(&data)
|
||||||
return &data, nil
|
return &data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,13 @@ func (this *TelegramNotifier) buildMessageInlineImage(evalContext *alerting.Eval
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
imageFile, err = os.Open(evalContext.ImageOnDiskPath)
|
imageFile, err = os.Open(evalContext.ImageOnDiskPath)
|
||||||
defer imageFile.Close()
|
defer func() {
|
||||||
|
err := imageFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error2("Could not close Telegram inline image.", "err", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
30
pkg/services/hooks/hooks.go
Normal file
30
pkg/services/hooks/hooks.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package hooks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexDataHook func(indexData *dtos.IndexViewData)
|
||||||
|
|
||||||
|
type HooksService struct {
|
||||||
|
indexDataHooks []IndexDataHook
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.RegisterService(&HooksService{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *HooksService) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *HooksService) AddIndexDataHook(hook IndexDataHook) {
|
||||||
|
srv.indexDataHooks = append(srv.indexDataHooks, hook)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *HooksService) RunIndexDataHooks(indexData *dtos.IndexViewData) {
|
||||||
|
for _, hook := range srv.indexDataHooks {
|
||||||
|
hook(indexData)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ func TestUserAuth(t *testing.T) {
|
|||||||
Convey("Given 5 users", t, func() {
|
Convey("Given 5 users", t, func() {
|
||||||
var err error
|
var err error
|
||||||
var cmd *m.CreateUserCommand
|
var cmd *m.CreateUserCommand
|
||||||
users := []m.User{}
|
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
cmd = &m.CreateUserCommand{
|
cmd = &m.CreateUserCommand{
|
||||||
Email: fmt.Sprint("user", i, "@test.com"),
|
Email: fmt.Sprint("user", i, "@test.com"),
|
||||||
@@ -25,7 +24,6 @@ func TestUserAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
err = CreateUser(context.Background(), cmd)
|
err = CreateUser(context.Background(), cmd)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
users = append(users, cmd.Result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Reset(func() {
|
Reset(func() {
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ func TestMSSQL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := endpoint.Query(nil, nil, query)
|
resp, err := endpoint.Query(context.Background(), nil, query)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
queryResult := resp.Results["A"]
|
queryResult := resp.Results["A"]
|
||||||
So(queryResult.Error, ShouldBeNil)
|
So(queryResult.Error, ShouldBeNil)
|
||||||
|
|||||||
@@ -769,7 +769,7 @@ func TestMySQL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := endpoint.Query(nil, nil, query)
|
resp, err := endpoint.Query(context.Background(), nil, query)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
queryResult := resp.Results["A"]
|
queryResult := resp.Results["A"]
|
||||||
So(queryResult.Error, ShouldBeNil)
|
So(queryResult.Error, ShouldBeNil)
|
||||||
|
|||||||
@@ -701,7 +701,7 @@ func TestPostgres(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := endpoint.Query(nil, nil, query)
|
resp, err := endpoint.Query(context.Background(), nil, query)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
queryResult := resp.Results["A"]
|
queryResult := resp.Results["A"]
|
||||||
So(queryResult.Error, ShouldBeNil)
|
So(queryResult.Error, ShouldBeNil)
|
||||||
|
|||||||
@@ -399,6 +399,77 @@ describe('duration', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('clock', () => {
|
||||||
|
it('null', () => {
|
||||||
|
const str = kbn.toClock(null, 0);
|
||||||
|
expect(str).toBe('');
|
||||||
|
});
|
||||||
|
it('size less than 1 second', () => {
|
||||||
|
const str = kbn.toClock(999, 0);
|
||||||
|
expect(str).toBe('999ms');
|
||||||
|
});
|
||||||
|
describe('size less than 1 minute', () => {
|
||||||
|
it('default', () => {
|
||||||
|
const str = kbn.toClock(59999);
|
||||||
|
expect(str).toBe('59s:999ms');
|
||||||
|
});
|
||||||
|
it('decimals equals 0', () => {
|
||||||
|
const str = kbn.toClock(59999, 0);
|
||||||
|
expect(str).toBe('59s');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('size less than 1 hour', () => {
|
||||||
|
it('default', () => {
|
||||||
|
const str = kbn.toClock(3599999);
|
||||||
|
expect(str).toBe('59m:59s:999ms');
|
||||||
|
});
|
||||||
|
it('decimals equals 0', () => {
|
||||||
|
const str = kbn.toClock(3599999, 0);
|
||||||
|
expect(str).toBe('59m');
|
||||||
|
});
|
||||||
|
it('decimals equals 1', () => {
|
||||||
|
const str = kbn.toClock(3599999, 1);
|
||||||
|
expect(str).toBe('59m:59s');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('size greater than or equal 1 hour', () => {
|
||||||
|
it('default', () => {
|
||||||
|
const str = kbn.toClock(7199999);
|
||||||
|
expect(str).toBe('01h:59m:59s:999ms');
|
||||||
|
});
|
||||||
|
it('decimals equals 0', () => {
|
||||||
|
const str = kbn.toClock(7199999, 0);
|
||||||
|
expect(str).toBe('01h');
|
||||||
|
});
|
||||||
|
it('decimals equals 1', () => {
|
||||||
|
const str = kbn.toClock(7199999, 1);
|
||||||
|
expect(str).toBe('01h:59m');
|
||||||
|
});
|
||||||
|
it('decimals equals 2', () => {
|
||||||
|
const str = kbn.toClock(7199999, 2);
|
||||||
|
expect(str).toBe('01h:59m:59s');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('size greater than or equal 1 day', () => {
|
||||||
|
it('default', () => {
|
||||||
|
const str = kbn.toClock(89999999);
|
||||||
|
expect(str).toBe('24h:59m:59s:999ms');
|
||||||
|
});
|
||||||
|
it('decimals equals 0', () => {
|
||||||
|
const str = kbn.toClock(89999999, 0);
|
||||||
|
expect(str).toBe('24h');
|
||||||
|
});
|
||||||
|
it('decimals equals 1', () => {
|
||||||
|
const str = kbn.toClock(89999999, 1);
|
||||||
|
expect(str).toBe('24h:59m');
|
||||||
|
});
|
||||||
|
it('decimals equals 2', () => {
|
||||||
|
const str = kbn.toClock(89999999, 2);
|
||||||
|
expect(str).toBe('24h:59m:59s');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('volume', () => {
|
describe('volume', () => {
|
||||||
it('1000m3', () => {
|
it('1000m3', () => {
|
||||||
const str = kbn.valueFormats['m3'](1000, 1, null);
|
const str = kbn.valueFormats['m3'](1000, 1, null);
|
||||||
|
|||||||
@@ -808,6 +808,51 @@ kbn.toDuration = (size, decimals, timeScale) => {
|
|||||||
return strings.join(', ');
|
return strings.join(', ');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
kbn.toClock = (size, decimals) => {
|
||||||
|
if (size === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// < 1 second
|
||||||
|
if (size < 1000) {
|
||||||
|
return moment.utc(size).format('SSS\\m\\s');
|
||||||
|
}
|
||||||
|
|
||||||
|
// < 1 minute
|
||||||
|
if (size < 60000) {
|
||||||
|
let format = 'ss\\s:SSS\\m\\s';
|
||||||
|
if (decimals === 0) {
|
||||||
|
format = 'ss\\s';
|
||||||
|
}
|
||||||
|
return moment.utc(size).format(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
// < 1 hour
|
||||||
|
if (size < 3600000) {
|
||||||
|
let format = 'mm\\m:ss\\s:SSS\\m\\s';
|
||||||
|
if (decimals === 0) {
|
||||||
|
format = 'mm\\m';
|
||||||
|
} else if (decimals === 1) {
|
||||||
|
format = 'mm\\m:ss\\s';
|
||||||
|
}
|
||||||
|
return moment.utc(size).format(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
let format = 'mm\\m:ss\\s:SSS\\m\\s';
|
||||||
|
|
||||||
|
const hours = `${('0' + Math.floor(moment.duration(size, 'milliseconds').asHours())).slice(-2)}h`;
|
||||||
|
|
||||||
|
if (decimals === 0) {
|
||||||
|
format = '';
|
||||||
|
} else if (decimals === 1) {
|
||||||
|
format = 'mm\\m';
|
||||||
|
} else if (decimals === 2) {
|
||||||
|
format = 'mm\\m:ss\\s';
|
||||||
|
}
|
||||||
|
|
||||||
|
return format ? `${hours}:${moment.utc(size).format(format)}` : hours;
|
||||||
|
};
|
||||||
|
|
||||||
kbn.valueFormats.dtdurationms = (size, decimals) => {
|
kbn.valueFormats.dtdurationms = (size, decimals) => {
|
||||||
return kbn.toDuration(size, decimals, 'millisecond');
|
return kbn.toDuration(size, decimals, 'millisecond');
|
||||||
};
|
};
|
||||||
@@ -824,6 +869,14 @@ kbn.valueFormats.timeticks = (size, decimals, scaledDecimals) => {
|
|||||||
return kbn.valueFormats.s(size / 100, decimals, scaledDecimals);
|
return kbn.valueFormats.s(size / 100, decimals, scaledDecimals);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
kbn.valueFormats.clockms = (size, decimals) => {
|
||||||
|
return kbn.toClock(size, decimals);
|
||||||
|
};
|
||||||
|
|
||||||
|
kbn.valueFormats.clocks = (size, decimals) => {
|
||||||
|
return kbn.toClock(size * 1000, decimals);
|
||||||
|
};
|
||||||
|
|
||||||
kbn.valueFormats.dateTimeAsIso = (epoch, isUtc) => {
|
kbn.valueFormats.dateTimeAsIso = (epoch, isUtc) => {
|
||||||
const time = isUtc ? moment.utc(epoch) : moment(epoch);
|
const time = isUtc ? moment.utc(epoch) : moment(epoch);
|
||||||
|
|
||||||
@@ -901,6 +954,8 @@ kbn.getUnitFormats = () => {
|
|||||||
{ text: 'duration (s)', value: 'dtdurations' },
|
{ text: 'duration (s)', value: 'dtdurations' },
|
||||||
{ text: 'duration (hh:mm:ss)', value: 'dthms' },
|
{ text: 'duration (hh:mm:ss)', value: 'dthms' },
|
||||||
{ text: 'Timeticks (s/100)', value: 'timeticks' },
|
{ text: 'Timeticks (s/100)', value: 'timeticks' },
|
||||||
|
{ text: 'clock (ms)', value: 'clockms' },
|
||||||
|
{ text: 'clock (s)', value: 'clocks' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default class PrometheusMetricFindQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process() {
|
process() {
|
||||||
const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]+)\)\s*$/;
|
const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]*)\)\s*$/;
|
||||||
const metricNamesRegex = /^metrics\((.+)\)\s*$/;
|
const metricNamesRegex = /^metrics\((.+)\)\s*$/;
|
||||||
const queryResultRegex = /^query_result\((.+)\)\s*$/;
|
const queryResultRegex = /^query_result\((.+)\)\s*$/;
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export class FilterSegments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove condition if it is first segment
|
// remove condition if it is first segment
|
||||||
if (index === 0 && this.filterSegments[0].type === 'condition') {
|
if (index === 0 && this.filterSegments.length > 0 && this.filterSegments[0].type === 'condition') {
|
||||||
this.filterSegments.splice(0, 1);
|
this.filterSegments.splice(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -714,7 +714,9 @@ class GraphElement {
|
|||||||
if (min && max && ticks) {
|
if (min && max && ticks) {
|
||||||
const range = max - min;
|
const range = max - min;
|
||||||
const secPerTick = range / ticks / 1000;
|
const secPerTick = range / ticks / 1000;
|
||||||
const oneDay = 86400000;
|
// Need have 10 milisecond margin on the day range
|
||||||
|
// As sometimes last 24 hour dashboard evaluates to more than 86400000
|
||||||
|
const oneDay = 86400010;
|
||||||
const oneYear = 31536000000;
|
const oneYear = 31536000000;
|
||||||
|
|
||||||
if (secPerTick <= 45) {
|
if (secPerTick <= 45) {
|
||||||
|
|||||||
Reference in New Issue
Block a user