Merge branch 'master' into alerting

Conflicts:
	conf/sample.ini
This commit is contained in:
Torkel Ödegaard
2016-08-17 10:03:33 +02:00
14 changed files with 119 additions and 69 deletions

View File

@@ -10,7 +10,8 @@
# 3.1.2 (unreleased) # 3.1.2 (unreleased)
* **Templating**: Fixed issue when combining row & panel repeats, fixes [#5790](https://github.com/grafana/grafana/issues/5790) * **Templating**: Fixed issue when combining row & panel repeats, fixes [#5790](https://github.com/grafana/grafana/issues/5790)
* **Drag&Drop**: Fixed issue with drag and drop in latest Chrome(51+), fixes [#5767](https://github.com/grafana/grafana/issues/5767) * **Drag&Drop**: Fixed issue with drag and drop in latest Chrome(51+), fixes [#5767](https://github.com/grafana/grafana/issues/5767)
* **Internal Metrics**: Fixed issue with dots in instance_name when sending internal metrics to Graphitge, fixes [#5739](https://github.com/grafana/grafana/issues/5739) * **Internal Metrics**: Fixed issue with dots in instance_name when sending internal metrics to Graphite, fixes [#5739](https://github.com/grafana/grafana/issues/5739)
* **Grafana-CLI**: Add default plugin path for MAC OS, fixes [#5806](https://github.com/grafana/grafana/issues/5806)
# 3.1.1 (2016-08-01) # 3.1.1 (2016-08-01)
* **IFrame embedding**: Fixed issue of using full iframe height, fixes [#5605](https://github.com/grafana/grafana/issues/5606) * **IFrame embedding**: Fixed issue of using full iframe height, fixes [#5605](https://github.com/grafana/grafana/issues/5606)

View File

@@ -373,12 +373,13 @@ enabled = false
# Metrics available at HTTP API Url /api/metrics # Metrics available at HTTP API Url /api/metrics
[metrics] [metrics]
enabled = true enabled = true
interval_seconds = 60 interval_seconds = 10
# Send internal Grafana metrics to graphite # Send internal Grafana metrics to graphite
; [metrics.graphite] [metrics.graphite]
; address = localhost:2003 # Enable by setting the address setting (ex localhost:2003)
; prefix = service.grafana.%(instance_name)s. address =
prefix = prod.grafana.%(instance_name)s.
[grafana_net] [grafana_net]
url = https://grafana.net url = https://grafana.net

View File

@@ -298,33 +298,34 @@ check_for_updates = true
# Metrics available at HTTP API Url /api/metrics # Metrics available at HTTP API Url /api/metrics
[metrics] [metrics]
# Disable / Enable internal metrics # Disable / Enable internal metrics
enabled = true ;enabled = true
# Publish interval # Publish interval
;interval_seconds = 10 ;interval_seconds = 10
# Send internal metrics to Graphite # Send internal metrics to Graphite
; [metrics.graphite] [metrics.graphite]
; address = localhost:2003 # Enable by setting the address setting (ex localhost:2003)
; prefix = service.grafana.%(instance_name)s. ;address =
;prefix = prod.grafana.%(instance_name)s.
#################################### Internal Grafana Metrics ########################## #################################### Internal Grafana Metrics ##########################
# Url used to to import dashboards directly from Grafana.net # Url used to to import dashboards directly from Grafana.net
[grafana_net] [grafana_net]
url = https://grafana.net ;url = https://grafana.net
#################################### External image storage ########################## #################################### External image storage ##########################
[external_image_storage] [external_image_storage]
# Used for uploading images to public servers so they can be included in slack/email messages. # Used for uploading images to public servers so they can be included in slack/email messages.
# you can choose between (s3, webdav or internal) # you can choose between (s3, webdav or internal)
provider = s3 ;provider = s3
[external_image_storage.s3] [external_image_storage.s3]
bucket_url = ;bucket_url =
access_key = ;access_key =
secret_key = ;secret_key =
[external_image_storage.webdav] [external_image_storage.webdav]
url = ;url =
username = ;username =
password = ;password =

View File

@@ -3,5 +3,6 @@ postgrestest:
environment: environment:
POSTGRES_USER: grafana POSTGRES_USER: grafana
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: password
POSTGRES_DATABASE: grafana
ports: ports:
- "5432:5432" - "5432:5432"

View File

@@ -466,7 +466,7 @@ Enable metrics reporting. defaults true. Available via HTTP API `/api/metrics`.
### interval_seconds ### interval_seconds
Flush/Write interval when sending metrics to external TSDB. Defaults to 60s. Flush/Write interval when sending metrics to external TSDB. Defaults to 10s.
## [metrics.graphite] ## [metrics.graphite]
Include this section if you want to send internal Grafana metrics to Graphite. Include this section if you want to send internal Grafana metrics to Graphite.

View File

@@ -8,39 +8,11 @@ import (
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/commands" "github.com/grafana/grafana/pkg/cmd/grafana-cli/commands"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
) )
var version = "master" var version = "master"
func getGrafanaPluginDir() string {
currentOS := runtime.GOOS
defaultNix := "/var/lib/grafana/plugins"
if currentOS == "windows" {
return "../data/plugins"
}
pwd, err := os.Getwd()
if err != nil {
logger.Error("Could not get current path. using default")
return defaultNix
}
if isDevenvironment(pwd) {
return "../data/plugins"
}
return defaultNix
}
func isDevenvironment(pwd string) bool {
// if ../conf/defaults.ini exists, grafana is not installed as package
// that its in development environment.
_, err := os.Stat("../conf/defaults.ini")
return err == nil
}
func main() { func main() {
setupLogging() setupLogging()
@@ -54,7 +26,7 @@ func main() {
cli.StringFlag{ cli.StringFlag{
Name: "pluginsDir", Name: "pluginsDir",
Usage: "path to the grafana plugin directory", Usage: "path to the grafana plugin directory",
Value: getGrafanaPluginDir(), Value: utils.GetGrafanaPluginDir(runtime.GOOS),
EnvVar: "GF_PLUGIN_DIR", EnvVar: "GF_PLUGIN_DIR",
}, },
cli.StringFlag{ cli.StringFlag{

View File

@@ -0,0 +1,46 @@
package utils
import (
"os"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
)
func GetGrafanaPluginDir(currentOS string) string {
//currentOS := runtime.GOOS
if currentOS == "windows" {
return returnOsDefault(currentOS)
}
pwd, err := os.Getwd()
if err != nil {
logger.Error("Could not get current path. using default")
return returnOsDefault(currentOS)
}
if isDevenvironment(pwd) {
return "../data/plugins"
}
return returnOsDefault(currentOS)
}
func isDevenvironment(pwd string) bool {
// if ../conf/defaults.ini exists, grafana is not installed as package
// that its in development environment.
_, err := os.Stat("../conf/defaults.ini")
return err == nil
}
func returnOsDefault(currentOs string) string {
switch currentOs {
case "windows":
return "../data/plugins"
case "darwin":
return "/usr/local/var/lib/grafana/plugins"
default: //"linux"
return "/var/lib/grafana/plugins"
}
}

View File

@@ -24,20 +24,25 @@ func CreateGraphitePublisher() (*GraphitePublisher, error) {
return nil, nil return nil, nil
} }
address := graphiteSection.Key("address").String()
if address == "" {
return nil, nil
}
publisher := &GraphitePublisher{} publisher := &GraphitePublisher{}
publisher.prevCounts = make(map[string]int64) publisher.prevCounts = make(map[string]int64)
publisher.protocol = "tcp" publisher.protocol = "tcp"
publisher.address = graphiteSection.Key("address").MustString("localhost:2003") publisher.prefix = graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s")
publisher.address = address
safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1) safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1)
prefix := graphiteSection.Key("prefix").Value() prefix := graphiteSection.Key("prefix").Value()
if prefix == "" { if prefix == "" {
prefix = "service.grafana.%(instance_name)s." prefix = "prod.grafana.%(instance_name)s."
} }
publisher.prefix = strings.Replace(prefix, "%(instance_name)s", safeInstanceName, -1) publisher.prefix = strings.Replace(prefix, "%(instance_name)s", safeInstanceName, -1)
return publisher, nil return publisher, nil
} }

View File

@@ -19,7 +19,7 @@ func TestGraphitePublisher(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
sec, err := setting.Cfg.NewSection("metrics.graphite") sec, err := setting.Cfg.NewSection("metrics.graphite")
sec.NewKey("prefix", "service.grafana.%(instance_name)s.") sec.NewKey("prefix", "prod.grafana.%(instance_name)s.")
sec.NewKey("address", "localhost:2001") sec.NewKey("address", "localhost:2001")
So(err, ShouldBeNil) So(err, ShouldBeNil)
@@ -30,7 +30,30 @@ func TestGraphitePublisher(t *testing.T) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(publisher, ShouldNotBeNil) So(publisher, ShouldNotBeNil)
So(publisher.prefix, ShouldEqual, "service.grafana.hostname_with_dots_com.") So(publisher.prefix, ShouldEqual, "prod.grafana.hostname_with_dots_com.")
So(publisher.address, ShouldEqual, "localhost:2001")
})
Convey("Test graphite publisher default prefix", t, func() {
var err error
err = setting.NewConfigContext(&setting.CommandLineArgs{
HomePath: "../../",
})
So(err, ShouldBeNil)
sec, err := setting.Cfg.NewSection("metrics.graphite")
sec.NewKey("address", "localhost:2001")
So(err, ShouldBeNil)
setting.InstanceName = "hostname.with.dots.com"
publisher, err := CreateGraphitePublisher()
So(err, ShouldBeNil)
So(publisher, ShouldNotBeNil)
So(publisher.prefix, ShouldEqual, "prod.grafana.hostname_with_dots_com.")
So(publisher.address, ShouldEqual, "localhost:2001") So(publisher.address, ShouldEqual, "localhost:2001")
}) })
@@ -48,9 +71,6 @@ func TestGraphitePublisher(t *testing.T) {
publisher, err := CreateGraphitePublisher() publisher, err := CreateGraphitePublisher()
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(publisher, ShouldNotBeNil) So(publisher, ShouldBeNil)
So(publisher.prefix, ShouldEqual, "service.grafana.hostname_with_dots_com.")
So(publisher.address, ShouldEqual, "localhost:2003")
}) })
} }

View File

@@ -7,7 +7,7 @@ define([
function (angular, _, $, coreModule) { function (angular, _, $, coreModule) {
'use strict'; 'use strict';
coreModule.default.controller('InspectCtrl', function($scope) { coreModule.default.controller('InspectCtrl', function($scope, $sanitize) {
var model = $scope.inspector; var model = $scope.inspector;
function getParametersFromQueryString(queryString) { function getParametersFromQueryString(queryString) {
@@ -32,7 +32,11 @@ function (angular, _, $, coreModule) {
if (_.isString(model.error.data)) { if (_.isString(model.error.data)) {
$scope.response = $("<div>" + model.error.data + "</div>").text(); $scope.response = $("<div>" + model.error.data + "</div>").text();
} else if (model.error.data) { } else if (model.error.data) {
$scope.response = angular.toJson(model.error.data, true); if (model.error.data.response) {
$scope.response = $sanitize(model.error.data.response);
} else {
$scope.response = angular.toJson(model.error.data, true);
}
} else if (model.error.message) { } else if (model.error.message) {
$scope.message = model.error.message; $scope.message = model.error.message;
} }

View File

@@ -138,7 +138,8 @@ export class BackendSrv {
//populate error obj on Internal Error //populate error obj on Internal Error
if (_.isString(err.data) && err.status === 500) { if (_.isString(err.data) && err.status === 500) {
err.data = { err.data = {
error: err.statusText error: err.statusText,
response: err.data,
}; };
} }

View File

@@ -14,11 +14,11 @@
<div class="gf-form-inline"> <div class="gf-form-inline">
<div class="gf-form max-width-15"> <div class="gf-form max-width-15">
<span class="gf-form-label width-7">User</span> <span class="gf-form-label width-7">User</span>
<input type="text" class="gf-form-input" ng-model='ctrl.current.user' placeholder="" required></input> <input type="text" class="gf-form-input" ng-model='ctrl.current.user' placeholder=""></input>
</div> </div>
<div class="gf-form max-width-15"> <div class="gf-form max-width-15">
<span class="gf-form-label width-7">Password</span> <span class="gf-form-label width-7">Password</span>
<input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder="" required></input> <input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder=""></input>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -129,11 +129,6 @@ function (angular, _, dateMath) {
}; };
this._addCredentialOptions(options); this._addCredentialOptions(options);
// In case the backend is 3rd-party hosted and does not suport OPTIONS, urlencoded requests
// go as POST rather than OPTIONS+POST
options.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
return backendSrv.datasourceRequest(options); return backendSrv.datasourceRequest(options);
}; };

View File

@@ -258,11 +258,14 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
function callPlot(incrementRenderCounter) { function callPlot(incrementRenderCounter) {
try { try {
$.plot(elem, sortedSeries, options); $.plot(elem, sortedSeries, options);
delete ctrl.error; if (ctrl.renderError) {
delete ctrl.inspector; delete ctrl.error;
delete ctrl.inspector;
}
} catch (e) { } catch (e) {
console.log('flotcharts error', e); console.log('flotcharts error', e);
ctrl.error = e.message || "Render Error"; ctrl.error = e.message || "Render Error";
ctrl.renderError = true;
ctrl.inspector = {error: ctrl.error}; ctrl.inspector = {error: ctrl.error};
} }