Skip to content

Commit

Permalink
Merge remote-tracking branch 'grafana/master'
Browse files Browse the repository at this point in the history
* grafana/master: (52 commits)
  changelog: adds note for grafana#11173
  changelog: fix typo
  changelog: notes about closing grafana#11572
  Fix issues with metric reporting (grafana#11518)
  changelog: notes about closing grafana#10747
  fix: Row state is now ignored when looking for dashboard changes (grafana#11608)
  disable codecov comments
  add some more sort order asserts for permissions store tests
  Revert "build: remove code cov"
  Revert "removes codecov from frontend tests"
  tsdb: update query and annotation editor help texts for postgres
  changelog: notes about closing grafana#11578
  calculate datetime for timeFrom and timeTo macro in go
  set default for sslmode to verify-full in postgres datasource editor (grafana#11615)
  add some more sort order asserts for permissions store tests
  fix unconvert issues
  variable: fix binding bug after ts conversion
  add GetFromAsTimeUTC and GetToAsTimeUTC and use them in timeFilter macro
  fix merge conflict
  remove changes to module.ts from this branch
  ...
  • Loading branch information
ryantxu committed Apr 17, 2018
2 parents d3e5c7a + 26bb22b commit fd75d59
Show file tree
Hide file tree
Showing 76 changed files with 2,022 additions and 1,366 deletions.
4 changes: 2 additions & 2 deletions .bra.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[run]
init_cmds = [
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
["go", "run", "build.go", "build"],
["./bin/grafana-server", "cfg:app_mode=development"]
]
watch_all = true
Expand All @@ -12,6 +12,6 @@ watch_dirs = [
watch_exts = [".go", ".ini", ".toml"]
build_delay = 1500
cmds = [
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
["go", "run", "build.go", "build"],
["./bin/grafana-server", "cfg:app_mode=development"]
]
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
* **Table**: Table plugin value mappings [#7119](https://github.com/grafana/grafana/issues/7119), thx [infernix](https://github.com/infernix)
* **IE11**: IE 11 compatibility [#11165](https://github.com/grafana/grafana/issues/11165)
* **Scrolling**: Better scrolling experience [#11053](https://github.com/grafana/grafana/issues/11053), [#11252](https://github.com/grafana/grafana/issues/11252), [#10836](https://github.com/grafana/grafana/issues/10836), [#11185](https://github.com/grafana/grafana/issues/11185), [#11168](https://github.com/grafana/grafana/issues/11168)
* **Docker**: Improved docker image (breaking changes regarding file ownership) [grafana-docker #141](https://github.com/grafana/grafana-docker/issues/141), thx [@Spindel](https://github.com/Spindel), [@ChristianKniep](https://github.com/ChristianKniep), [@brancz](https://github.com/brancz) and [@jangaraj](https://github.com/jangaraj)
* **Folders** A folder admin cannot add user/team permissions for folder/its dashboards [#11173](https://github.com/grafana/grafana/issues/11173)

### Minor

* **OpsGenie**: Add triggered alerts as description [#11046](https://github.com/grafana/grafana/pull/11046), thx [@llamashoes](https://github.com/llamashoes)
* **Cloudwatch**: Support high resolution metrics [#10925](https://github.com/grafana/grafana/pull/10925), thx [@mtanda](https://github.com/mtanda)
* **Cloudwatch**: Add dimension filtering to CloudWatch `dimension_values()` [#10029](https://github.com/grafana/grafana/issues/10029), thx [@willyhutw](https://github.com/willyhutw)
Expand Down Expand Up @@ -45,6 +48,11 @@
* **Heatmap**: Disable log scale when using time time series buckets [#10792](https://github.com/grafana/grafana/issues/10792)
* **Provisioning**: Remove `id` from json when provisioning dashboards, [#11138](https://github.com/grafana/grafana/issues/11138)
* **Prometheus**: tooltip for legend format not showing properly [#11516](https://github.com/grafana/grafana/issues/11516), thx [@svenklemm](https://github.com/svenklemm)
* **Playlist**: Empty playlists cannot be deleted [#11133](https://github.com/grafana/grafana/issues/11133), thx [@kichristensen](https://github.com/kichristensen)
* **Switch Orgs**: Alphabetic order in Switch Organization modal [#11556](https://github.com/grafana/grafana/issues/11556)
* **Postgres**: improve `$__timeFilter` macro [#11578](https://github.com/grafana/grafana/issues/11578), thx [@svenklemm](https://github.com/svenklemm)
* **Permission list**: Improved ux [#10747](https://github.com/grafana/grafana/issues/10747)
* **Dashboard**: Sizing and positioning of settings menu icons [#11572](https://github.com/grafana/grafana/pull/11572)

### Tech
* Migrated JavaScript files to TypeScript
Expand Down
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module.exports = function (grunt) {
}
}

config.coverage = grunt.option('coverage');
config.phjs = grunt.option('phjsToRelease');
config.pkg.version = grunt.option('pkgVer') || config.pkg.version;

Expand Down
11 changes: 11 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
coverage:
precision: 2
round: down
range: "50...100"

status:
project: yes
patch: yes
changes: no

comment: off
16 changes: 16 additions & 0 deletions docs/sources/features/datasources/elasticsearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ a time pattern for the index name or a wildcard.
Be sure to specify your Elasticsearch version in the version selection dropdown. This is very important as there are differences how queries are composed. Currently only 2.x and 5.x
are supported.

### Min time interval
A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example `1m` if your data is written every minute.
This option can also be overridden/configured in a dashboard panel under data source options. It's important to note that this value **needs** to be formated as a
number followed by a valid time identifier, e.g. `1m` (1 minute) or `30s` (30 seconds). The following time identifiers are supported:

Identifier | Description
------------ | -------------
`y` | year
`M` | month
`w` | week
`d` | day
`h` | hour
`m` | minute
`s` | second
`ms` | millisecond

## Metric Query editor

![](/img/docs/elasticsearch/query_editor.png)
Expand Down
16 changes: 16 additions & 0 deletions docs/sources/features/datasources/influxdb.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ Proxy access means that the Grafana backend will proxy all requests from the bro
`grafana-server`. This means that the URL you specify needs to be accessible from the server you are running Grafana on. Proxy access
mode is also more secure as the username & password will never reach the browser.

### Min time interval
A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example `1m` if your data is written every minute.
This option can also be overridden/configured in a dashboard panel under data source options. It's important to note that this value **needs** to be formated as a
number followed by a valid time identifier, e.g. `1m` (1 minute) or `30s` (30 seconds). The following time identifiers are supported:

Identifier | Description
------------ | -------------
`y` | year
`M` | month
`w` | week
`d` | day
`h` | hour
`m` | minute
`s` | second
`ms` | millisecond

## Query Editor

{{< docs-imagebox img="/img/docs/v45/influxdb_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v45/influxdb_query.gif" >}}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"watch": "webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
"build": "grunt build",
"test": "grunt test",
"test:coverage": "grunt test --coverage=true",
"lint": "tslint -c tslint.json --project tsconfig.json --type-check",
"karma": "grunt karma:dev",
"jest": "jest --notify --watch",
Expand Down
14 changes: 11 additions & 3 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ func (hs *HTTPServer) registerRoutes() {

// team (admin permission required)
apiRoute.Group("/teams", func(teamsRoute RouteRegister) {
teamsRoute.Get("/:teamId", wrap(GetTeamByID))
teamsRoute.Get("/search", wrap(SearchTeams))
teamsRoute.Post("/", bind(m.CreateTeamCommand{}), wrap(CreateTeam))
teamsRoute.Put("/:teamId", bind(m.UpdateTeamCommand{}), wrap(UpdateTeam))
teamsRoute.Delete("/:teamId", wrap(DeleteTeamByID))
Expand All @@ -159,6 +157,12 @@ func (hs *HTTPServer) registerRoutes() {
teamsRoute.Delete("/:teamId/members/:userId", wrap(RemoveTeamMember))
}, reqOrgAdmin)

// team without requirement of user to be org admin
apiRoute.Group("/teams", func(teamsRoute RouteRegister) {
teamsRoute.Get("/:teamId", wrap(GetTeamByID))
teamsRoute.Get("/search", wrap(SearchTeams))
})

// org information available to all users.
apiRoute.Group("/org", func(orgRoute RouteRegister) {
orgRoute.Get("/", wrap(GetOrgCurrent))
Expand All @@ -170,7 +174,6 @@ func (hs *HTTPServer) registerRoutes() {
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), wrap(UpdateOrgCurrent))
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), wrap(UpdateOrgAddressCurrent))
orgRoute.Post("/users", quota("user"), bind(m.AddOrgUserCommand{}), wrap(AddOrgUserToCurrentOrg))
orgRoute.Get("/users", wrap(GetOrgUsersForCurrentOrg))
orgRoute.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUserForCurrentOrg))
orgRoute.Delete("/users/:userId", wrap(RemoveOrgUserForCurrentOrg))

Expand All @@ -184,6 +187,11 @@ func (hs *HTTPServer) registerRoutes() {
orgRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), wrap(UpdateOrgPreferences))
}, reqOrgAdmin)

// current org without requirement of user to be org admin
apiRoute.Group("/org", func(orgRoute RouteRegister) {
orgRoute.Get("/users", wrap(GetOrgUsersForCurrentOrg))
})

// create new org
apiRoute.Post("/orgs", quota("org"), bind(m.CreateOrgCommand{}), wrap(CreateOrg))

Expand Down
5 changes: 5 additions & 0 deletions pkg/api/dashboard_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func GetDashboardPermissionList(c *m.ReqContext) Response {
}

for _, perm := range acl {
perm.UserAvatarUrl = dtos.GetGravatarUrl(perm.UserEmail)

if perm.TeamId > 0 {
perm.TeamAvatarUrl = dtos.GetGravatarUrlWithDefault(perm.TeamEmail, perm.Team)
}
if perm.Slug != "" {
perm.Url = m.GetDashboardFolderUrl(perm.IsFolder, perm.Uid, perm.Slug)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/dashboard_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func TestDashboardPermissionApiEndpoint(t *testing.T) {
})
})

Convey("When trying to override inherited permissions with lower presedence", func() {
Convey("When trying to override inherited permissions with lower precedence", func() {
origNewGuardian := guardian.New
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{
CanAdminValue: true,
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/folder_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func GetFolderPermissionList(c *m.ReqContext) Response {
perm.FolderId = folder.Id
perm.DashboardId = 0

perm.UserAvatarUrl = dtos.GetGravatarUrl(perm.UserEmail)

if perm.TeamId > 0 {
perm.TeamAvatarUrl = dtos.GetGravatarUrlWithDefault(perm.TeamEmail, perm.Team)
}

if perm.Slug != "" {
perm.Url = m.GetDashboardFolderUrl(perm.IsFolder, perm.Uid, perm.Slug)
}
Expand Down
8 changes: 7 additions & 1 deletion pkg/api/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,14 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) {
})

if c.IsSignedIn {
// Only set login if it's different from the name
var login string
if c.SignedInUser.Login != c.SignedInUser.NameOrFallback() {
login = c.SignedInUser.Login
}
profileNode := &dtos.NavLink{
Text: c.SignedInUser.NameOrFallback(),
SubTitle: c.SignedInUser.Login,
SubTitle: login,
Id: "profile",
Img: data.User.GravatarUrl,
Url: setting.AppSubUrl + "/profile",
Expand Down Expand Up @@ -284,6 +289,7 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) {

data.NavTree = append(data.NavTree, &dtos.NavLink{
Text: "Help",
SubTitle: fmt.Sprintf(`Grafana v%s (%s)`, setting.BuildVersion, setting.BuildCommit),
Id: "help",
Url: "#",
Icon: "gicon gicon-question",
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func ValidateOrgPlaylist(c *m.ReqContext) {
return
}

if len(items) == 0 {
if len(items) == 0 && c.Context.Req.Method != "DELETE" {
c.JsonApiErr(404, "Playlist is empty", itemsErr)
return
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/grafana-cli/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func Init(version string, skipTLSVerify bool) {
}

HttpClient = http.Client{
Timeout: time.Duration(10 * time.Second),
Timeout: 10 * time.Second,
Transport: tr,
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/components/apikeygen/apikeygen.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func New(orgId int64, name string) KeyGenResult {

jsonString, _ := json.Marshal(jsonKey)

result.ClientSecret = base64.StdEncoding.EncodeToString([]byte(jsonString))
result.ClientSecret = base64.StdEncoding.EncodeToString(jsonString)
return result
}

Expand All @@ -44,7 +44,7 @@ func Decode(keyString string) (*ApiKeyJson, error) {
}

var keyObj ApiKeyJson
err = json.Unmarshal([]byte(jsonString), &keyObj)
err = json.Unmarshal(jsonString, &keyObj)
if err != nil {
return nil, ErrInvalidApiKey
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/components/imguploader/azureblobuploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func (a *Auth) SignRequest(req *http.Request) {
)
decodedKey, _ := base64.StdEncoding.DecodeString(a.Key)

sha256 := hmac.New(sha256.New, []byte(decodedKey))
sha256 := hmac.New(sha256.New, decodedKey)
sha256.Write([]byte(strToSign))

signature := base64.StdEncoding.EncodeToString(sha256.Sum(nil))
Expand Down
2 changes: 1 addition & 1 deletion pkg/components/null/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (f *Float) UnmarshalJSON(data []byte) error {
}
switch x := v.(type) {
case float64:
f.Float64 = float64(x)
f.Float64 = x
case map[string]interface{}:
err = json.Unmarshal(data, &f.NullFloat64)
case nil:
Expand Down
44 changes: 26 additions & 18 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var (
M_Alerting_Active_Alerts prometheus.Gauge
M_StatTotal_Dashboards prometheus.Gauge
M_StatTotal_Users prometheus.Gauge
M_StatActive_Users prometheus.Gauge
M_StatTotal_Orgs prometheus.Gauge
M_StatTotal_Playlists prometheus.Gauge
M_Grafana_Version *prometheus.GaugeVec
Expand Down Expand Up @@ -253,6 +254,12 @@ func init() {
Namespace: exporterName,
})

M_StatActive_Users = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "stat_active_users",
Help: "number of active users",
Namespace: exporterName,
})

M_StatTotal_Orgs = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "stat_total_orgs",
Help: "total amount of orgs",
Expand All @@ -270,7 +277,6 @@ func init() {
Help: "Information about the Grafana",
Namespace: exporterName,
}, []string{"version"})

}

func initMetricVars(settings *MetricSettings) {
Expand Down Expand Up @@ -305,6 +311,7 @@ func initMetricVars(settings *MetricSettings) {
M_Alerting_Active_Alerts,
M_StatTotal_Dashboards,
M_StatTotal_Users,
M_StatActive_Users,
M_StatTotal_Orgs,
M_StatTotal_Playlists,
M_Grafana_Version)
Expand All @@ -315,35 +322,36 @@ func initMetricVars(settings *MetricSettings) {
func instrumentationLoop(settings *MetricSettings) chan struct{} {
M_Instance_Start.Inc()

// set the total stats gauges before we publishing metrics
updateTotalStats()

onceEveryDayTick := time.NewTicker(time.Hour * 24)
secondTicker := time.NewTicker(time.Second * time.Duration(settings.IntervalSeconds))
everyMinuteTicker := time.NewTicker(time.Minute)
defer onceEveryDayTick.Stop()
defer everyMinuteTicker.Stop()

for {
select {
case <-onceEveryDayTick.C:
sendUsageStats()
case <-secondTicker.C:
case <-everyMinuteTicker.C:
updateTotalStats()
}
}
}

var metricPublishCounter int64 = 0

func updateTotalStats() {
metricPublishCounter++
if metricPublishCounter == 1 || metricPublishCounter%10 == 0 {
statsQuery := models.GetSystemStatsQuery{}
if err := bus.Dispatch(&statsQuery); err != nil {
metricsLogger.Error("Failed to get system stats", "error", err)
return
}

M_StatTotal_Dashboards.Set(float64(statsQuery.Result.Dashboards))
M_StatTotal_Users.Set(float64(statsQuery.Result.Users))
M_StatTotal_Playlists.Set(float64(statsQuery.Result.Playlists))
M_StatTotal_Orgs.Set(float64(statsQuery.Result.Orgs))
statsQuery := models.GetSystemStatsQuery{}
if err := bus.Dispatch(&statsQuery); err != nil {
metricsLogger.Error("Failed to get system stats", "error", err)
return
}

M_StatTotal_Dashboards.Set(float64(statsQuery.Result.Dashboards))
M_StatTotal_Users.Set(float64(statsQuery.Result.Users))
M_StatActive_Users.Set(float64(statsQuery.Result.ActiveUsers))
M_StatTotal_Playlists.Set(float64(statsQuery.Result.Playlists))
M_StatTotal_Orgs.Set(float64(statsQuery.Result.Orgs))
}

func sendUsageStats() {
Expand Down Expand Up @@ -403,6 +411,6 @@ func sendUsageStats() {
out, _ := json.MarshalIndent(report, "", " ")
data := bytes.NewBuffer(out)

client := http.Client{Timeout: time.Duration(5 * time.Second)}
client := http.Client{Timeout: 5 * time.Second}
go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data)
}
3 changes: 3 additions & 0 deletions pkg/models/dashboard_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ type DashboardAclInfoDTO struct {
UserId int64 `json:"userId"`
UserLogin string `json:"userLogin"`
UserEmail string `json:"userEmail"`
UserAvatarUrl string `json:"userAvatarUrl"`
TeamId int64 `json:"teamId"`
TeamEmail string `json:"teamEmail"`
TeamAvatarUrl string `json:"teamAvatarUrl"`
Team string `json:"team"`
Role *RoleType `json:"role,omitempty"`
Permission PermissionType `json:"permission"`
Expand Down
5 changes: 5 additions & 0 deletions pkg/models/dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ func GetFolderUrl(folderUid string, slug string) string {
return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
}

type ValidateDashboardBeforeSaveResult struct {
IsParentFolderChanged bool
}

//
// COMMANDS
//
Expand Down Expand Up @@ -268,6 +272,7 @@ type ValidateDashboardBeforeSaveCommand struct {
OrgId int64
Dashboard *Dashboard
Overwrite bool
Result *ValidateDashboardBeforeSaveResult
}

//
Expand Down
Loading

0 comments on commit fd75d59

Please sign in to comment.