commit 8154b4f60d1522466de8c3c1bbe4877946cd4aad Author: Torkel Ödegaard Date: Fri Aug 8 12:35:15 2014 +0200 search and save are 'working', barely diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..42857a1b225 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +node_modules +coverage/ +.aws-config.json +dist + +public +gin-bin +# locally required config files +web.config +config.js + +# Editor junk +*.sublime-workspace +*.swp +.idea/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..651db133841 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "grafana"] + path = grafana + url = git@github.com:torkelo/grafana-private.git diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000000..e8f044e1da9 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,35 @@ +{ + "browser": true, + + "bitwise":false, + "curly": true, + "eqnull": true, + "globalstrict": true, + "devel": true, + "eqeqeq": true, + "forin": false, + "immed": true, + "supernew": true, + "expr": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "noempty": true, + "undef": true, + "boss": true, + "trailing": true, + "laxbreak": true, + "laxcomma": true, + "sub": true, + "unused": true, + "maxdepth": 5, + "maxlen": 140, + + "globals": { + "define": true, + "require": true, + "Chromath": false, + "setImmediate": true + } +} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..0ce3be24b19 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000000..2a16428867d --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,38 @@ +/* jshint node:true */ +'use strict'; +module.exports = function (grunt) { + + var config = { + pkg: grunt.file.readJSON('package.json'), + baseDir: '.', + srcDir: 'public', + destDir: 'dist', + tempDir: 'tmp', + docsDir: 'docs/' + }; + + // load plugins + require('load-grunt-tasks')(grunt); + + // load task definitions + grunt.loadTasks('tasks'); + + // Utility function to load plugin settings into config + function loadConfig(config,path) { + require('glob').sync('*', {cwd: path}).forEach(function(option) { + var key = option.replace(/\.js$/,''); + // If key already exists, extend it. It is your responsibility to avoid naming collisions + config[key] = config[key] || {}; + grunt.util._.extend(config[key], require(path + option)(config,grunt)); + }); + // technically not required + return config; + } + + // Merge that object with what with whatever we have here + loadConfig(config,'./tasks/options/'); + + // pass the config to grunt + grunt.initConfig(config); + +}; \ No newline at end of file diff --git a/backend/configuration/configuration.go b/backend/configuration/configuration.go new file mode 100644 index 00000000000..3bf6038df74 --- /dev/null +++ b/backend/configuration/configuration.go @@ -0,0 +1,11 @@ +package configuration + +type Cfg struct { + httpPort string + DashboardSource DashboardSourceCfg +} + +type DashboardSourceCfg struct { + sourceType string + path string +} diff --git a/backend/httpApi/api.go b/backend/httpApi/api.go new file mode 100644 index 00000000000..f93a0adc60c --- /dev/null +++ b/backend/httpApi/api.go @@ -0,0 +1,106 @@ +package httpApi + +import ( + "html/template" + + log "github.com/alecthomas/log4go" + "github.com/gin-gonic/gin" + "github.com/torkelo/grafana-pro/backend/models" + "github.com/torkelo/grafana-pro/backend/stores" +) + +type HttpServer struct { + port string + shutdown chan bool + store stores.Store +} + +func NewHttpServer(port string, store stores.Store) *HttpServer { + self := &HttpServer{} + self.port = port + self.store = store + + return self +} + +func CacheHeadersMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + c.Writer.Header().Add("Cache-Control", "max-age=0, public, must-revalidate, proxy-revalidate") + } +} + +func (self *HttpServer) ListenAndServe() { + log.Info("Starting Http Listener on port %v", self.port) + + defer func() { self.shutdown <- true }() + + r := gin.Default() + r.Use(CacheHeadersMiddleware()) + + templates := template.New("templates") + templates.Delims("[[", "]]") + templates.ParseFiles("./views/index.html") + + r.SetHTMLTemplate(templates) + + r.GET("/", self.index) + r.GET("/api/dashboards/:id", self.getDashboard) + r.GET("/api/search/", self.search) + r.POST("/api/dashboard", self.postDashboard) + + r.Static("/public", "./public") + r.Static("/app", "./public/app") + r.Static("/img", "./public/img") + + r.Run(":" + self.port) +} + +type IndexViewModel struct { + Title string +} + +func (self *HttpServer) index(c *gin.Context) { + c.HTML(200, "index.html", &IndexViewModel{Title: "hello from go"}) +} + +type ErrorRsp struct { + Message string `json:"message"` +} + +func (self *HttpServer) getDashboard(c *gin.Context) { + id := c.Params.ByName("id") + + dash, err := self.store.GetById(id) + if err != nil { + c.JSON(404, &ErrorRsp{Message: "Dashboard not found"}) + return + } + + c.JSON(200, dash.Data) +} + +func (self *HttpServer) search(c *gin.Context) { + query := c.Params.ByName("q") + + results, err := self.store.Query(query) + if err != nil { + c.JSON(500, &ErrorRsp{Message: "Search error"}) + return + } + + c.JSON(200, results) +} + +func (self *HttpServer) postDashboard(c *gin.Context) { + var command saveDashboardCommand + + if c.EnsureBody(&command) { + err := self.store.Save(&models.Dashboard{Data: command.Dashboard}) + if err == nil { + c.JSON(200, gin.H{"status": "saved"}) + return + } + } + + c.JSON(500, gin.H{"error": "bad request"}) +} diff --git a/backend/httpApi/api_test.go b/backend/httpApi/api_test.go new file mode 100644 index 00000000000..6daae4e93fa --- /dev/null +++ b/backend/httpApi/api_test.go @@ -0,0 +1 @@ +package httpApi diff --git a/backend/httpApi/commands.go b/backend/httpApi/commands.go new file mode 100644 index 00000000000..922d2607621 --- /dev/null +++ b/backend/httpApi/commands.go @@ -0,0 +1,7 @@ +package httpApi + +type saveDashboardCommand struct { + Id string `json:"id"` + Title string `json:"title"` + Dashboard map[string]interface{} +} diff --git a/backend/models/dashboards.go b/backend/models/dashboards.go new file mode 100644 index 00000000000..9f333aff8dc --- /dev/null +++ b/backend/models/dashboards.go @@ -0,0 +1,53 @@ +package models + +import ( + "encoding/json" + "io" +) + +type Dashboard struct { + Data map[string]interface{} +} + +type SearchResult struct { + Type string `json:"title"` + Id string `json:"id"` + Title string `json:"title"` +} + +func NewDashboard(title string) *Dashboard { + dash := &Dashboard{} + dash.Data = make(map[string]interface{}) + dash.Data["title"] = title + + return dash +} + +func NewFromJson(reader io.Reader) (*Dashboard, error) { + dash := NewDashboard("temp") + jsonParser := json.NewDecoder(reader) + + if err := jsonParser.Decode(&dash.Data); err != nil { + return nil, err + } + + return dash, nil +} + +/*type DashboardServices struct { +} + +type DashboardServicesFilter struct { +} + +type DashboardServicesFilterTime struct { + From string To string +}*/ + +func (dash *Dashboard) GetString(prop string) string { + return dash.Data[prop].(string) +} + +func (dash *Dashboard) Title() string { + return dash.GetString("title") +} diff --git a/backend/server/server.go b/backend/server/server.go new file mode 100644 index 00000000000..b3fcaf37779 --- /dev/null +++ b/backend/server/server.go @@ -0,0 +1,27 @@ +package server + +import ( + "github.com/torkelo/grafana-pro/backend/httpApi" + "github.com/torkelo/grafana-pro/backend/stores" +) + +type Server struct { + HttpServer *httpApi.HttpServer + Store stores.Store +} + +func NewServer(port string) (*Server, error) { + store := stores.New() + httpServer := httpApi.NewHttpServer(port, store) + + return &Server{ + HttpServer: httpServer, + Store: store, + }, nil +} + +func (self *Server) ListenAndServe() error { + self.HttpServer.ListenAndServe() + + return nil +} diff --git a/backend/stores/file_store.go b/backend/stores/file_store.go new file mode 100644 index 00000000000..7ecba7d1c81 --- /dev/null +++ b/backend/stores/file_store.go @@ -0,0 +1,155 @@ +package stores + +import ( + "encoding/json" + "io" + "os" + "path/filepath" + "strings" + + log "github.com/alecthomas/log4go" + "github.com/torkelo/grafana-pro/backend/models" +) + +type fileStore struct { + dataDir string + dashDir string + cache map[string]*models.Dashboard +} + +func NewFileStore(dataDir string) *fileStore { + + if dirDoesNotExist(dataDir) { + log.Crashf("FileStore failed to initialize, dataDir does not exist %v", dataDir) + } + + dashDir := filepath.Join(dataDir, "dashboards") + + if dirDoesNotExist(dashDir) { + log.Debug("Did not find dashboard dir, creating...") + err := os.Mkdir(dashDir, 0777) + if err != nil { + log.Crashf("FileStore failed to initialize, could not create directory %v, error: %v", dashDir, err) + } + } + + store := &fileStore{} + store.dataDir = dataDir + store.dashDir = dashDir + store.cache = make(map[string]*models.Dashboard) + go store.scanFiles() + + return store +} + +func (store *fileStore) scanFiles() { + visitor := func(path string, f os.FileInfo, err error) error { + if err != nil { + return err + } + if f.IsDir() { + return nil + } + if strings.HasSuffix(f.Name(), ".json") { + err = store.loadDashboardIntoCache(path) + if err != nil { + return err + } + } + return nil + } + + err := filepath.Walk(store.dashDir, visitor) + if err != nil { + log.Error("FileStore::updateCache failed %v", err) + } +} + +func (store fileStore) loadDashboardIntoCache(filename string) error { + log.Info("Loading dashboard file %v into cache", filename) + dash, err := loadDashboardFromFile(filename) + if err != nil { + return err + } + + store.cache[dash.Title()] = dash + + return nil +} + +func (store *fileStore) Close() { + +} + +func (store *fileStore) GetById(id string) (*models.Dashboard, error) { + log.Debug("FileStore::GetById id = %v", id) + filename := store.getFilePathForDashboard(id) + + return loadDashboardFromFile(filename) +} + +func (store *fileStore) Save(dash *models.Dashboard) error { + filename := store.getFilePathForDashboard(dash.Title()) + + log.Debug("Saving dashboard %v to %v", dash.Title(), filename) + + var err error + var data []byte + if data, err = json.Marshal(dash.Data); err != nil { + return err + } + + return writeFile(filename, data) +} + +func (store *fileStore) Query(query string) ([]*models.SearchResult, error) { + results := make([]*models.SearchResult, 0, 50) + + for _, dash := range store.cache { + item := &models.SearchResult{ + Id: dash.Title(), + Type: "dashboard", + } + results = append(results, item) + } + + return results, nil +} + +func loadDashboardFromFile(filename string) (*models.Dashboard, error) { + log.Debug("FileStore::loading dashboard from file %v", filename) + + configFile, err := os.Open(filename) + if err != nil { + return nil, err + } + + return models.NewFromJson(configFile) +} + +func (store *fileStore) getFilePathForDashboard(id string) string { + id = strings.ToLower(id) + id = strings.Replace(id, " ", "-", -1) + return filepath.Join(store.dashDir, id) + ".json" +} + +func dirDoesNotExist(dir string) bool { + _, err := os.Stat(dir) + return os.IsNotExist(err) +} + +func writeFile(filename string, data []byte) error { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return err + } + n, err := f.Write(data) + if err == nil && n < len(data) { + err = io.ErrShortWrite + } + if err1 := f.Close(); err == nil { + err = err1 + } + + return err +} diff --git a/backend/stores/file_store_test.go b/backend/stores/file_store_test.go new file mode 100644 index 00000000000..f896e20e687 --- /dev/null +++ b/backend/stores/file_store_test.go @@ -0,0 +1,112 @@ +package stores + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "testing" + + . "github.com/smartystreets/goconvey/convey" + "github.com/torkelo/grafana-pro/backend/models" +) + +func TestFileStore(t *testing.T) { + + GivenFileStore("When saving a dashboard", t, func(store *fileStore) { + dashboard := models.NewDashboard("hello") + + err := store.Save(dashboard) + + Convey("should be saved to disk", func() { + So(err, ShouldBeNil) + + _, err = os.Stat(store.getFilePathForDashboard("hello")) + So(err, ShouldBeNil) + }) + }) + + GivenFileStore("When getting a saved dashboard", t, func(store *fileStore) { + copyDashboardToTempData("default.json", "", store.dashDir) + dash, err := store.GetById("default") + + Convey("should be read from disk", func() { + So(err, ShouldBeNil) + So(dash, ShouldNotBeNil) + + So(dash.Title(), ShouldEqual, "Grafana Play Home") + }) + }) + + GivenFileStore("when getting dashboard with capital letters", t, func(store *fileStore) { + copyDashboardToTempData("annotations.json", "", store.dashDir) + dash, err := store.GetById("AnnoTations") + + Convey("should be read from disk", func() { + So(err, ShouldBeNil) + So(dash, ShouldNotBeNil) + + So(dash.Title(), ShouldEqual, "Annotations") + }) + }) + + GivenFileStore("When copying dashboards into data dir", t, func(store *fileStore) { + copyDashboardToTempData("annotations.json", "", store.dashDir) + copyDashboardToTempData("default.json", "", store.dashDir) + copyDashboardToTempData("graph-styles.json", "", store.dashDir) + store.scanFiles() + + Convey("scan should generate index of all dashboards", func() { + + result, err := store.Query("*") + So(err, ShouldBeNil) + So(len(result), ShouldEqual, 3) + }) + }) +} + +func copyDashboardToTempData(name string, destName string, dir string) { + if destName == "" { + destName = name + } + source, _ := filepath.Abs("../../data/dashboards/" + name) + dest := filepath.Join(dir, destName) + err := copyFile(dest, source) + if err != nil { + panic(fmt.Sprintf("failed to copy file %v", name)) + } +} + +func GivenFileStore(desc string, t *testing.T, f func(store *fileStore)) { + Convey(desc, t, func() { + tempDir, _ := ioutil.TempDir("", "store") + + store := NewFileStore(tempDir) + + f(store) + + Reset(func() { + os.RemoveAll(tempDir) + }) + }) +} + +func copyFile(dst, src string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + _, err = io.Copy(out, in) + cerr := out.Close() + if err != nil { + return err + } + return cerr +} diff --git a/backend/stores/store.go b/backend/stores/store.go new file mode 100644 index 00000000000..e071d1e7a66 --- /dev/null +++ b/backend/stores/store.go @@ -0,0 +1,16 @@ +package stores + +import ( + "github.com/torkelo/grafana-pro/backend/models" +) + +type Store interface { + GetById(id string) (*models.Dashboard, error) + Save(dash *models.Dashboard) error + Query(query string) ([]*models.SearchResult, error) + Close() +} + +func New() Store { + return NewFileStore("data") +} diff --git a/data/dashboards/annotations.json b/data/dashboards/annotations.json new file mode 100644 index 00000000000..727313e95dd --- /dev/null +++ b/data/dashboards/annotations.json @@ -0,0 +1,269 @@ +{ + "title": "Annotations", + "services": { + "filter": { + "list": [], + "time": { + "from": "now-1h", + "to": "now" + } + } + }, + "rows": [ + { + "title": "Welcome to Grafana", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 12, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(apps.fakesite.web_server_02.counters.requests.count,2)" + }, + { + "target": "aliasByNode(apps.fakesite.web_server_01.counters.requests.count,2)" + } + ], + "aliasColors": {}, + "aliasYAxis": {}, + "title": "Amnotations example", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + }, + { + "title": "test", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(apps.fakesite.web_server_02.counters.request_status.code_304.count,5)" + } + ], + "aliasColors": { + "web_server_01": "#1F78C1", + "web_server_02": "#6ED0E0" + }, + "aliasYAxis": {}, + "title": "Annotations example", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "### Annotations\n\n- Annotation is a feature that must be enabled in the dashboards settings / Controls tab / Feature toggles\n- Annotation bar is then visible at the top. \n- Click on the cog to open the Annotations dialog \n- In this dialog you can add or edit annotations \n- Currently only Graphite metrics and Graphite events are supported sources of annotations\n- More datasource options for annotations will be added \n- Click on the annotation name in the bar to toggle the annotation on or off\n\n", + "style": {}, + "title": "Description" + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "dark", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": false + }, + { + "type": "annotations", + "enable": true, + "annotations": [ + { + "name": "deploys", + "type": "graphite metric", + "showLine": true, + "iconColor": "#C0C6BE", + "lineColor": "rgba(253, 54, 54, 0.77)", + "iconSize": 13, + "enable": true, + "target": "alias(apps.fakesite.web_server_01.counters.request_status.code_500.count, 'deployed v1.3')" + }, + { + "name": "puppet apply", + "type": "graphite metric", + "showLine": true, + "iconColor": "#C0C6BE", + "lineColor": "rgba(255, 96, 96, 0.592157)", + "iconSize": 13, + "enable": false, + "target": "alias(apps.fakesite.web_server_02.counters.request_status.code_403.count,'puppet apply')" + } + ] + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [ + "annotations", + "graphite", + "showcase" + ], + "timezone": "browser" +} \ No newline at end of file diff --git a/data/dashboards/default.json b/data/dashboards/default.json new file mode 100644 index 00000000000..2dc6f36ab62 --- /dev/null +++ b/data/dashboards/default.json @@ -0,0 +1,409 @@ +{ + "title": "Grafana Play Home", + "services": { + "filter": { + "list": [], + "time": { + "from": "now-15m", + "to": "now" + } + } + }, + "rows": [ + { + "title": "test", + "height": "190px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "error": false, + "span": 12, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "html", + "content": "

Welcome to grafana demo, playground and interactive tutorial site.

\n\n
\n\t
\n\t\t

Feature showcases

\n\t\t\n\t
\n\t
\n\t\t

Graphite tutorials

\n\t\t
    \n\t\t\t
  • \n\t\t\t\tGraphite introduction (TODO)\n\t\t\t
  • \n\t\t\t
  • \n\t\t\t\tBasic functions (TODO)\n\t\t\t
  • \n\t\t\t
  • \n\t\t\t\tAdvanced functions (TODO)\n\t\t\t
  • \n\t\t\t
  • \n\t\t\t\tTips and tricks (TODO)\n\t\t\t
  • \n\t\t
\n\t
\n\t
\n\t\t

InfluxDB examples

\n\t\t
    \n\t\t\t
  • \n\t\t\t\tTODO\n\t\t\t
  • \n\t\t
\n\t
\n
\n\n", + "style": {}, + "title": "Grafana demo site" + } + ], + "notice": false + }, + { + "title": "test", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 3, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(scaleToSeconds(apps.fakesite.*.counters.requests.count,1),2)" + } + ], + "aliasColors": { + "web_server_04": "#3F6833", + "web_server_03": "#508642", + "web_server_02": "#7EB26D", + "web_server_01": "#B7DBAB" + }, + "aliasYAxis": {}, + "title": "server requests", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": true, + "max": true, + "current": true, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "alias(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),'logins')" + }, + { + "target": "alias(timeShift(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),'1h'),'logins (-1 hour)')" + } + ], + "aliasColors": { + "logins": "#7EB26D", + "logins (-1 day)": "#447EBC" + }, + "aliasYAxis": {}, + "title": "logins", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + }, + { + "title": "", + "height": "300px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 4, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "bytes", + "none" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": true, + "max": false, + "current": true, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "alias(scale(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),1000000),'memory')" + }, + { + "target": "alias(scaleToSeconds(apps.fakesite.web_server_01.counters.request_status.code_302.count,1),'cpu')" + } + ], + "aliasColors": { + "cpu": "#E24D42" + }, + "aliasYAxis": { + "cpu": 2 + }, + "title": "Memory / CPU", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "span": 8, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "ms", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": false, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": true, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.timers.ads_timer.*,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "client side full page load", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + }, + { + "title": "test", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "dark", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": false + }, + { + "type": "annotations", + "enable": false + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [ + "showcase", + "startpage", + "home", + "default" + ], + "timezone": "browser" +} \ No newline at end of file diff --git a/data/dashboards/graph-styles.json b/data/dashboards/graph-styles.json new file mode 100644 index 00000000000..4f9147cdf62 --- /dev/null +++ b/data/dashboards/graph-styles.json @@ -0,0 +1,796 @@ +{ + "title": "Graph styles", + "services": { + "filter": { + "list": [], + "time": { + "from": "now-15m", + "to": "now" + } + } + }, + "rows": [ + { + "title": "Simple graph", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(scaleToSeconds(apps.backend.*.counters.requests.count,1),2)" + } + ], + "aliasColors": { + "web_server_04": "#E24D42", + "web_server_03": "#508642", + "web_server_02": "#EAB839", + "web_server_01": "#EF843C" + }, + "aliasYAxis": {}, + "title": "Simple graph", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Simple graph\n- Click on the title and select edit to open edit mode\n- The display styles tab allows you change line width, fill, stacking, and more\n- You can change a series color by clicking the colored line in the legend ", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Stacked Graph", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 2, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(scaleToSeconds(apps.fakesite.*.counters.requests.count,1),2)" + } + ], + "aliasColors": { + "web_server_04": "#E24D42", + "web_server_03": "#EF843C", + "web_server_02": "#EAB839", + "web_server_01": "#F2C96D" + }, + "aliasYAxis": {}, + "title": "Stacked lines", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Stacked graph\n- This graph shows stacked series, with area fill and 2px line width\n- We have also added legend values. These can be enabled in the Grid & Axes tab in edit mode. \n- Legend values can be Min, Max, Total, Current and Average", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Staircase line", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "ms", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": true, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.timers.ads_timer.upper_90,4)" + }, + { + "target": "aliasByNode(statsd.fakesite.timers.ads_timer.upper_90,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "Staircase line", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Staircase & Y-Axis format\n- In display styles tab you can switch to staircase line \n- In Axes & Grid tab you can change to different Y units & formats.\n", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Right Y-Axis", + "height": "300px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "bytes", + "none" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": true, + "max": false, + "current": true, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "alias(scale(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),1000000),'memory')" + }, + { + "target": "alias(scaleToSeconds(apps.fakesite.web_server_02.counters.requests.count,1),'cpu')" + } + ], + "aliasColors": { + "cpu": "#E24D42" + }, + "aliasYAxis": { + "cpu": 2 + }, + "title": "Memory / CPU", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Second Y-Axis\n- Click on the series legend color line to open the color selector\n- In the series color selector popup you can also move the series to the Right-Y axis\n- Multiple Y-Axis are great for showing to related series that have different magnitudes ", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "test", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "none", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "null", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(apps.fakesite.web_server_01.counters.request_status.code_404.count,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "Null point mode", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Null point mode\n- This option under Display styles tab controls how null values are handled\n- The graph to left shows how the default \"null\" looks. \n- __null__ null values are left null and this leaves empty spaces in the graph\n- __null as zero__ null values are drawn as zero values\n- __connected__ null values are ignored and the line jumps directly to the next value.", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Thresholds", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "none", + "short" + ], + "grid": { + "max": 700, + "min": 0, + "threshold1": 400, + "threshold2": 600, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": true, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(apps.fakesite.web_server_01.counters.requests.count,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9", + "requests": "#6ED0E0" + }, + "aliasYAxis": {}, + "title": "Thresholds", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Thresholds\n- You can define thresholds in the Grid & Axes tab in edit mode \n- You can define one or two thresholds, color is also changeable. \n- You can have lower bound thresholds as well. ", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Bars", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "ms", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": false, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": true, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": true, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.timers.ads_timer.*,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "Bars", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Bars\n- In display styles tab you can switch from line to bars\n- The width of the bar is relative to the pixel width between two values\n", + "style": {}, + "title": "Description" + } + ], + "notice": false + }, + { + "title": "Graphite PNG", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "ms", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": false, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 2, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(apps.backend.*.counters.requests.count,2)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "Graphite PNG", + "datasource": null, + "renderer": "png", + "annotate": { + "enable": false + } + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Graphite PNG support\n- You can switch from client side rendering to graphite's server side PNG rendering\n- You cannot click and drag to zoom in in this render mode.\n", + "style": {}, + "title": "Description" + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "dark", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": false + }, + { + "type": "annotations", + "enable": false + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [ + "showcase", + "annotations" + ], + "timezone": "browser" +} \ No newline at end of file diff --git a/data/dashboards/templated-graphs-nested.json b/data/dashboards/templated-graphs-nested.json new file mode 100644 index 00000000000..abd26cc8f17 --- /dev/null +++ b/data/dashboards/templated-graphs-nested.json @@ -0,0 +1,288 @@ +{ + "title": "Templated Graphs Nested", + "services": { + "filter": { + "list": [ + { + "type": "filter", + "name": "app", + "query": "apps.*", + "includeAll": true, + "options": [ + { + "text": "All", + "value": "{backend,fakesite}" + }, + { + "text": "backend", + "value": "backend" + }, + { + "text": "fakesite", + "value": "fakesite" + } + ], + "current": { + "text": "backend", + "value": "backend" + } + }, + { + "type": "filter", + "name": "server", + "query": "apps.[[app]].*", + "includeAll": true, + "options": [ + { + "text": "All", + "value": "{backend_01,backend_02,backend_03,backend_04}" + }, + { + "text": "backend_01", + "value": "backend_01" + }, + { + "text": "backend_02", + "value": "backend_02" + }, + { + "text": "backend_03", + "value": "backend_03" + }, + { + "text": "backend_04", + "value": "backend_04" + } + ], + "current": { + "text": "All", + "value": "{backend_01,backend_02,backend_03,backend_04}" + } + } + ], + "time": { + "from": "now-6h", + "to": "now" + } + } + }, + "rows": [ + { + "title": "Row1", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 12, + "editable": true, + "type": "graphite", + "loadingEditor": false, + "datasource": null, + "renderer": "flot", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "annotate": { + "enable": false + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "groupByNode(apps.[[app]].[[server]].counters.requests.count,2,'sum')" + } + ], + "aliasColors": { + "highres.test": "#1F78C1", + "scale(highres.test,3)": "#6ED0E0", + "mobile": "#6ED0E0", + "tablet": "#EAB839" + }, + "aliasYAxis": {}, + "title": "Traffic" + } + ], + "notice": false + }, + { + "title": "Row1", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 12, + "editable": true, + "type": "graphite", + "loadingEditor": false, + "datasource": null, + "renderer": "flot", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "annotate": { + "enable": false + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(movingAverage(scaleToSeconds(apps.[[app]].[[server]].counters.requests.count,60),10),1,2)" + } + ], + "aliasColors": { + "highres.test": "#1F78C1", + "scale(highres.test,3)": "#6ED0E0", + "mobile": "#6ED0E0", + "tablet": "#EAB839" + }, + "aliasYAxis": {}, + "title": "Sessions / min" + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "dark", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": true + }, + { + "type": "annotations", + "enable": false + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [ + "showcase", + "templated" + ], + "timezone": "browser" +} \ No newline at end of file diff --git a/data/dashboards/templated-graphs.json b/data/dashboards/templated-graphs.json new file mode 100644 index 00000000000..f979e4d1223 --- /dev/null +++ b/data/dashboards/templated-graphs.json @@ -0,0 +1,272 @@ +{ + "title": "Templated Graphs", + "services": { + "filter": { + "list": [ + { + "type": "filter", + "name": "root", + "query": "statsd.fakesite.counters.session_start.*", + "includeAll": true, + "options": [ + { + "text": "All", + "value": "{desktop,mobile,tablet}" + }, + { + "text": "desktop", + "value": "desktop" + }, + { + "text": "mobile", + "value": "mobile" + }, + { + "text": "tablet", + "value": "tablet" + } + ], + "current": { + "text": "All", + "value": "{desktop,mobile,tablet}" + } + } + ], + "time": { + "from": "now-6h", + "to": "now" + } + } + }, + "rows": [ + { + "title": "Row1", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 12, + "editable": true, + "type": "graphite", + "loadingEditor": false, + "datasource": null, + "renderer": "flot", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "annotate": { + "enable": false + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 1, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(summarize(statsd.fakesite.counters.session_start.[[root]].count,'1min','sum'),4)" + } + ], + "aliasColors": { + "highres.test": "#1F78C1", + "scale(highres.test,3)": "#6ED0E0", + "mobile": "#6ED0E0", + "tablet": "#EAB839" + }, + "aliasYAxis": {}, + "title": "Device sessions" + } + ], + "notice": false + }, + { + "title": "Row1", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "loadingEditor": false, + "datasource": null, + "renderer": "flot", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "annotate": { + "enable": false + }, + "resolution": 100, + "lines": false, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": true, + "stack": true, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(summarize(statsd.fakesite.counters.session_start.[[root]].count,'1h','sum'),4)" + } + ], + "aliasColors": { + "highres.test": "#1F78C1", + "scale(highres.test,3)": "#6ED0E0", + "tablet": "#EAB839", + "desktop": "#7EB26D", + "mobile": "#6ED0E0" + }, + "aliasYAxis": {}, + "title": "Device sessions (1h)" + }, + { + "error": false, + "span": 6, + "editable": true, + "type": "text", + "loadingEditor": false, + "mode": "markdown", + "content": "#### Templated metric queries / graphs \n- In dashboard settings, in the Controls tab / Feature toggles. You can enable 'Filtering' \n- This feature when enabled will show you a bar bellow the menu.\n- In this bar you can add filters, or what should be named templated metric segments. \n- A filter is a query for a specific metric segment\n- Open any graph in this dashboard and edit mode and you can see that the [[device]] filter is used instead of a wildcard.\n- Try clicking the All link in the filter menu at the top, change device and see that all graphs change to only show values for that device. ", + "style": {}, + "title": "Description" + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "dark", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": true + }, + { + "type": "annotations", + "enable": false + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [ + "showcase", + "templated" + ], + "timezone": "browser" +} \ No newline at end of file diff --git a/data/dashboards/testing-save.json b/data/dashboards/testing-save.json new file mode 100644 index 00000000000..fdd008c4cf7 --- /dev/null +++ b/data/dashboards/testing-save.json @@ -0,0 +1 @@ +{"editable":true,"nav":[{"collapse":false,"enable":true,"notice":false,"now":true,"refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"status":"Stable","time_options":["5m","15m","1h","6h","12h","24h","2d","7d","30d"],"type":"timepicker"}],"pulldowns":[{"collapse":false,"enable":false,"notice":false,"type":"filtering"},{"enable":false,"type":"annotations"}],"refresh":false,"rows":[{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"web_server_01":"#EF843C","web_server_02":"#EAB839","web_server_03":"#508642","web_server_04":"#E24D42"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":0,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":false,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":true,"linewidth":1,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":false,"steppedLine":false,"targets":[{"target":"aliasByNode(scaleToSeconds(apps.backend.*.counters.requests.count,1),2)"}],"timezone":"browser","title":"Simple graph","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["short","short"],"zerofill":true},{"content":"#### Simple graph\n- Click on the title and select edit to open edit mode\n- The display styles tab allows you change line width, fill, stacking, and more\n- You can change a series color by clicking the colored line in the legend ","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Simple graph"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"web_server_01":"#F2C96D","web_server_02":"#EAB839","web_server_03":"#EF843C","web_server_04":"#E24D42"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":2,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":true,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":true,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":true,"steppedLine":false,"targets":[{"target":"aliasByNode(scaleToSeconds(apps.fakesite.*.counters.requests.count,1),2)"}],"timezone":"browser","title":"Stacked lines","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["short","short"],"zerofill":true},{"content":"#### Stacked graph\n- This graph shows stacked series, with area fill and 2px line width\n- We have also added legend values. These can be enabled in the Grid \u0026 Axes tab in edit mode. \n- Legend values can be Min, Max, Total, Current and Average","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Stacked Graph"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"upper_25":"#BA43A9","upper_50":"#7EB26D","upper_75":"#EAB839"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":1,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":true,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":true,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":true,"steppedLine":true,"targets":[{"target":"aliasByNode(statsd.fakesite.timers.ads_timer.upper_90,4)"},{"target":"aliasByNode(statsd.fakesite.timers.ads_timer.upper_90,4)"}],"timezone":"browser","title":"Staircase line","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["ms","short"],"zerofill":true},{"content":"#### Staircase \u0026 Y-Axis format\n- In display styles tab you can switch to staircase line \n- In Axes \u0026 Grid tab you can change to different Y units \u0026 formats.\n","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Staircase line"},{"collapsable":true,"collapse":false,"editable":true,"height":"300px","notice":false,"panels":[{"aliasColors":{"cpu":"#E24D42"},"aliasYAxis":{"cpu":2},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":0,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":false,"current":true,"max":false,"min":true,"show":true,"total":false,"values":true},"legend_counts":true,"lines":true,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":false,"steppedLine":false,"targets":[{"target":"alias(scale(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),1000000),'memory')"},{"target":"alias(scaleToSeconds(apps.fakesite.web_server_02.counters.requests.count,1),'cpu')"}],"timezone":"browser","title":"Memory / CPU","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["bytes","none"],"zerofill":true},{"content":"#### Second Y-Axis\n- Click on the series legend color line to open the color selector\n- In the series color selector popup you can also move the series to the Right-Y axis\n- Multiple Y-Axis are great for showing to related series that have different magnitudes ","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Right Y-Axis"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"upper_25":"#BA43A9","upper_50":"#7EB26D","upper_75":"#EAB839"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":1,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":true,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":true,"linewidth":2,"nullPointMode":"null","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":false,"steppedLine":false,"targets":[{"target":"aliasByNode(apps.fakesite.web_server_01.counters.request_status.code_404.count,4)"}],"timezone":"browser","title":"Null point mode","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["none","short"],"zerofill":true},{"content":"#### Null point mode\n- This option under Display styles tab controls how null values are handled\n- The graph to left shows how the default \"null\" looks. \n- __null__ null values are left null and this leaves empty spaces in the graph\n- __null as zero__ null values are drawn as zero values\n- __connected__ null values are ignored and the line jumps directly to the next value.","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"test"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"requests":"#6ED0E0","upper_25":"#BA43A9","upper_50":"#7EB26D","upper_75":"#EAB839"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":0,"grid":{"leftMax":700,"leftMin":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":400,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":600,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":false,"current":false,"max":false,"min":false,"show":true,"total":true,"values":true},"legend_counts":true,"lines":true,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":false,"steppedLine":false,"targets":[{"target":"aliasByNode(apps.fakesite.web_server_01.counters.requests.count,4)"}],"timezone":"browser","title":"Thresholds","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["none","short"],"zerofill":true},{"content":"#### Thresholds\n- You can define thresholds in the Grid \u0026 Axes tab in edit mode \n- You can define one or two thresholds, color is also changeable. \n- You can have lower bound thresholds as well. ","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Thresholds"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"upper_25":"#BA43A9","upper_50":"#7EB26D","upper_75":"#EAB839"},"aliasYAxis":{},"annotate":{"enable":false},"bars":true,"datasource":null,"editable":true,"fill":1,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":true,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":false,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":5,"points":false,"renderer":"flot","resolution":100,"scale":1,"span":6,"spyable":true,"stack":true,"steppedLine":true,"targets":[{"target":"aliasByNode(statsd.fakesite.timers.ads_timer.*,4)"}],"timezone":"browser","title":"Bars","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["ms","short"],"zerofill":true},{"content":"#### Bars\n- In display styles tab you can switch from line to bars\n- The width of the bar is relative to the pixel width between two values\n","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Bars"},{"collapsable":true,"collapse":false,"editable":true,"height":"250px","notice":false,"panels":[{"aliasColors":{"upper_25":"#BA43A9","upper_50":"#7EB26D","upper_75":"#EAB839"},"aliasYAxis":{},"annotate":{"enable":false},"bars":false,"datasource":null,"editable":true,"fill":1,"grid":{"leftMax":null,"leftMin":null,"max":null,"min":0,"rightMax":null,"rightMin":null,"threshold1":null,"threshold1Color":"rgba(216, 200, 27, 0.27)","threshold2":null,"threshold2Color":"rgba(234, 112, 112, 0.22)"},"interactive":true,"legend":{"avg":true,"current":false,"max":false,"min":false,"show":true,"total":false,"values":true},"legend_counts":true,"lines":false,"linewidth":2,"nullPointMode":"connected","options":false,"percentage":false,"pointradius":2,"points":false,"renderer":"png","resolution":100,"scale":1,"span":6,"spyable":true,"stack":true,"steppedLine":false,"targets":[{"target":"aliasByNode(apps.backend.*.counters.requests.count,2)"}],"timezone":"browser","title":"Graphite PNG","tooltip":{"query_as_alias":true,"value_type":"cumulative"},"type":"graph","x-axis":true,"y-axis":true,"y_formats":["ms","short"],"zerofill":true},{"content":"#### Graphite PNG support\n- You can switch from client side rendering to graphite's server side PNG rendering\n- You cannot click and drag to zoom in in this render mode.\n","editable":true,"error":false,"loadingEditor":false,"mode":"markdown","span":6,"style":{},"title":"Description","type":"text"}],"title":"Graphite PNG"}],"style":"dark","tags":["showcase","annotations"],"templating":{"list":[]},"time":{"from":"now-15m","to":"now"},"timezone":"browser","title":"Testing save","version":2} \ No newline at end of file diff --git a/data/dashboards/white-theme.json b/data/dashboards/white-theme.json new file mode 100644 index 00000000000..4ffa2fc1a60 --- /dev/null +++ b/data/dashboards/white-theme.json @@ -0,0 +1,519 @@ +{ + "title": "White theme", + "services": { + "filter": { + "list": [], + "time": { + "from": "now-1h", + "to": "now" + } + } + }, + "rows": [ + { + "title": "test", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 3, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": false, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(scaleToSeconds(apps.fakesite.*.counters.requests.count,1),2)" + } + ], + "aliasColors": { + "web_server_04": "#3F6833", + "web_server_03": "#508642", + "web_server_02": "#7EB26D", + "web_server_01": "#B7DBAB" + }, + "aliasYAxis": {}, + "title": "server requests", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(movingAverage(scaleToSeconds(apps.fakesite.*.counters.request_status.code_302.count,1),4),2)" + } + ], + "aliasColors": { + "logins": "#7EB26D", + "logins (-1 day)": "#447EBC" + }, + "aliasYAxis": {}, + "title": "logins", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + }, + { + "title": "", + "height": "300px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 4, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "bytes", + "none" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 0, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": false, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": true, + "max": false, + "current": true, + "total": false, + "avg": false + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "alias(scale(scaleToSeconds(apps.fakesite.web_server_01.counters.requests.count,1),1000000),'memory')" + }, + { + "target": "alias(scaleToSeconds(apps.fakesite.web_server_02.counters.requests.count,1),'cpu')" + } + ], + "aliasColors": { + "cpu": "#E24D42" + }, + "aliasYAxis": { + "cpu": 2 + }, + "title": "Memory / CPU", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "span": 8, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "ms", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": false, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": true, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(statsd.fakesite.timers.ads_timer.*,4)" + } + ], + "aliasColors": { + "upper_75": "#EAB839", + "upper_50": "#7EB26D", + "upper_25": "#BA43A9" + }, + "aliasYAxis": {}, + "title": "client side full page load", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + }, + { + "title": "test", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(movingAverage(scaleToSeconds(apps.fakesite.*.counters.request_status.code_302.count,1),4),2)" + } + ], + "aliasColors": { + "logins": "#7EB26D", + "logins (-1 day)": "#447EBC", + "web_server_03": "#1F78C1", + "web_server_02": "#6ED0E0", + "web_server_01": "#64B0C8" + }, + "aliasYAxis": {}, + "title": "logins", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + }, + { + "span": 6, + "editable": true, + "type": "graphite", + "x-axis": true, + "y-axis": true, + "scale": 1, + "y_formats": [ + "short", + "short" + ], + "grid": { + "max": null, + "min": 0, + "threshold1": null, + "threshold2": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "resolution": 100, + "lines": true, + "fill": 1, + "linewidth": 2, + "points": false, + "pointradius": 5, + "bars": false, + "stack": true, + "spyable": true, + "options": false, + "legend": { + "show": true, + "values": true, + "min": false, + "max": false, + "current": false, + "total": false, + "avg": true + }, + "interactive": true, + "legend_counts": true, + "timezone": "browser", + "percentage": false, + "zerofill": true, + "nullPointMode": "connected", + "steppedLine": false, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "targets": [ + { + "target": "aliasByNode(movingAverage(scaleToSeconds(apps.fakesite.*.counters.request_status.code_302.count,1),4),2)" + } + ], + "aliasColors": { + "logins": "#7EB26D", + "logins (-1 day)": "#447EBC", + "web_server_03": "#E24D42", + "web_server_02": "#EF843C", + "web_server_01": "#EAB839" + }, + "aliasYAxis": {}, + "title": "logins", + "datasource": null, + "renderer": "flot", + "annotate": { + "enable": false + } + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "panel_hints": true, + "style": "light", + "pulldowns": [ + { + "type": "filtering", + "collapse": false, + "notice": false, + "enable": false + }, + { + "type": "annotations", + "enable": false + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "enable": true, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "now": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": false, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": false, + "hide": false + }, + "refresh": false, + "tags": [], + "timezone": "browser" +} \ No newline at end of file diff --git a/grafana b/grafana new file mode 160000 index 00000000000..91a6ae756f3 --- /dev/null +++ b/grafana @@ -0,0 +1 @@ +Subproject commit 91a6ae756f30744afe82dabbb5caa7f43d6f7e5a diff --git a/grafana-pro b/grafana-pro new file mode 100755 index 00000000000..255abcbd2c7 Binary files /dev/null and b/grafana-pro differ diff --git a/grafana-pro.sublime-project b/grafana-pro.sublime-project new file mode 100644 index 00000000000..c5bb4a23c20 --- /dev/null +++ b/grafana-pro.sublime-project @@ -0,0 +1,18 @@ +{ + "folders": + [ + { + "follow_symlinks": true, + "path": ".", + "folder_exclude_patterns": [ + "node_modules", + "grafana" + ] + } + ], + "settings": + { + "tab_size": 2, + "trim_trailing_white_space_on_save": true + } +} diff --git a/grafana.go b/grafana.go new file mode 100644 index 00000000000..fb28ee81010 --- /dev/null +++ b/grafana.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "time" + + log "github.com/alecthomas/log4go" + "github.com/torkelo/grafana-pro/backend/server" +) + +func main() { + port := os.Getenv("PORT") + if port == "" { + port = "3838" + } + + log.Info("Starting Grafana-Pro v.1-alpha") + + server, err := server.NewServer(port) + if err != nil { + time.Sleep(time.Second) + panic(err) + } + + err = server.ListenAndServe() + if err != nil { + log.Error("ListenAndServe failed: ", err) + } + + time.Sleep(time.Millisecond * 2000) +} diff --git a/package.json b/package.json new file mode 100644 index 00000000000..e95428e903e --- /dev/null +++ b/package.json @@ -0,0 +1,68 @@ +{ + "author": { + "name": "Torkel Ödegaard", + "company": "Coding Instinct AB" + }, + "name": "grafana", + "version": "1.7.0-rc1", + "repository": { + "type": "git", + "url": "http://github.com/torkelo/grafana.git" + }, + "devDependencies": { + "expect.js": "~0.2.0", + "glob": "~3.2.7", + "grunt": "~0.4.0", + "grunt-angular-templates": "^0.5.5", + "grunt-cli": "~0.1.13", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-compress": "~0.5.2", + "grunt-contrib-concat": "^0.4.0", + "grunt-contrib-connect": "~0.5.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-cssmin": "~0.6.1", + "grunt-contrib-htmlmin": "~0.1.3", + "grunt-contrib-jshint": "~0.10.0", + "grunt-contrib-less": "~0.7.0", + "grunt-contrib-requirejs": "~0.4.1", + "grunt-contrib-uglify": "~0.2.4", + "grunt-filerev": "^0.2.1", + "grunt-git-describe": "~2.3.2", + "grunt-karma": "~0.8.3", + "grunt-ngmin": "0.0.3", + "grunt-string-replace": "~0.2.4", + "grunt-usemin": "^2.1.1", + "jshint-stylish": "~0.1.5", + "karma": "~0.12.16", + "karma-chrome-launcher": "~0.1.4", + "karma-coffee-preprocessor": "~0.1.2", + "karma-coverage": "^0.2.5", + "karma-coveralls": "^0.1.4", + "karma-expect": "~1.1.0", + "karma-firefox-launcher": "~0.1.3", + "karma-html2js-preprocessor": "~0.1.0", + "karma-jasmine": "~0.2.2", + "karma-mocha": "~0.1.4", + "karma-phantomjs-launcher": "~0.1.1", + "karma-requirejs": "~0.2.1", + "karma-script-launcher": "~0.1.0", + "load-grunt-tasks": "~0.2.0", + "mocha": "~1.16.1", + "requirejs": "~2.1.14", + "rjs-build-analysis": "0.0.3" + }, + "engines": { + "node": "0.10.x", + "npm": "1.2.x" + }, + "scripts": { + "test": "grunt test", + "coveralls": "grunt karma:coveralls && rm -rf ./coverage" + }, + "license": "Apache License", + "dependencies": { + "grunt-jscs-checker": "^0.4.4", + "karma-sinon": "^1.0.3", + "sinon": "^1.10.3" + } +} diff --git a/tasks/build_task.js b/tasks/build_task.js new file mode 100644 index 00000000000..3a96c5bf985 --- /dev/null +++ b/tasks/build_task.js @@ -0,0 +1,37 @@ +module.exports = function(grunt) { + + // Concat and Minify the src directory into dist + grunt.registerTask('build', [ + 'jshint:source', + 'jshint:tests', + 'clean:on_start', + 'less:src', + 'concat:css', + 'copy:everything_but_less_to_temp', + 'htmlmin:build', + 'ngtemplates', + 'cssmin:build', + 'build:grafanaVersion', + 'ngmin:build', + 'requirejs:build', + 'concat:js', + 'filerev', + 'usemin', + 'clean:temp', + 'uglify:dest' + ]); + + + grunt.registerTask('build:grafanaVersion', function() { + grunt.config('string-replace.config', { + files: { + '<%= tempDir %>/app/app.js': '<%= tempDir %>/app/app.js' + }, + options: { + replacements: [{ pattern: /@grafanaVersion@/g, replacement: '<%= pkg.version %>' }] + } + }); + grunt.task.run('string-replace:config'); + }); + +}; diff --git a/tasks/default_task.js b/tasks/default_task.js new file mode 100644 index 00000000000..14b483fb2ca --- /dev/null +++ b/tasks/default_task.js @@ -0,0 +1,5 @@ +// Lint and build CSS +module.exports = function(grunt) { + grunt.registerTask('default', ['jscs', 'jshint', 'less:src', 'concat:css']); + grunt.registerTask('test', ['default', 'karma:test']); +}; diff --git a/tasks/distribute_task.js b/tasks/distribute_task.js new file mode 100644 index 00000000000..7cff5efb897 --- /dev/null +++ b/tasks/distribute_task.js @@ -0,0 +1,31 @@ +module.exports = function(grunt) { + + // build, then zip and upload to s3 + grunt.registerTask('distribute', [ + 'distribute:load_s3_config', + 'build', + 'compress:zip', + 'compress:tgz', + 's3:dist', + 'clean:temp' + ]); + + // build, then zip and upload to s3 + grunt.registerTask('release', [ + // 'distribute:load_s3_config', + 'build', + 'compress:zip_release', + 'compress:tgz_release', + //'s3:release', + //'clean:temp' + ]); + + // collect the key and secret from the .aws-config.json file, finish configuring the s3 task + grunt.registerTask('distribute:load_s3_config', function () { + var config = grunt.file.readJSON('.aws-config.json'); + grunt.config('s3.options', { + key: config.key, + secret: config.secret + }); + }); +} \ No newline at end of file diff --git a/tasks/options/clean.js b/tasks/options/clean.js new file mode 100644 index 00000000000..7db6ef22f26 --- /dev/null +++ b/tasks/options/clean.js @@ -0,0 +1,7 @@ +module.exports = function(config) { + return { + on_start: ['<%= destDir %>', '<%= tempDir %>'], + temp: ['<%= tempDir %>'], + docs: ['<%= docsDir %>'] + }; +}; \ No newline at end of file diff --git a/tasks/options/compress.js b/tasks/options/compress.js new file mode 100644 index 00000000000..7a03cff052f --- /dev/null +++ b/tasks/options/compress.js @@ -0,0 +1,76 @@ +module.exports = function(config) { + return { + zip: { + options: { + archive: '<%= tempDir %>/<%= pkg.name %>-latest.zip' + }, + files : [ + { + expand: true, + cwd: '<%= destDir %>', + src: ['**/*'], + dest: '<%= pkg.name %>/', + }, + { + expand: true, + dest: '<%= pkg.name %>/', + src: ['LICENSE.md', 'README.md', 'NOTICE.md'], + } + ] + }, + tgz: { + options: { + archive: '<%= tempDir %>/<%= pkg.name %>-latest.tar.gz' + }, + files : [ + { + expand: true, + cwd: '<%= destDir %>', + src: ['**/*'], + dest: '<%= pkg.name %>/', + }, + { + expand: true, + src: ['LICENSE.md', 'README.md', 'NOTICE.md'], + dest: '<%= pkg.name %>/', + } + ] + }, + zip_release: { + options: { + archive: '<%= tempDir %>/<%= pkg.name %>-<%= pkg.version %>.zip' + }, + files : [ + { + expand: true, + cwd: '<%= destDir %>', + src: ['**/*'], + dest: '<%= pkg.name %>-<%= pkg.version %>/', + }, + { + expand: true, + src: ['LICENSE.md', 'README.md', 'NOTICE.md'], + dest: '<%= pkg.name %>-<%= pkg.version %>/', + } + ] + }, + tgz_release: { + options: { + archive: '<%= tempDir %>/<%= pkg.name %>-<%= pkg.version %>.tar.gz' + }, + files : [ + { + expand: true, + cwd: '<%= destDir %>', + src: ['**/*'], + dest: '<%= pkg.name %>-<%= pkg.version %>/', + }, + { + expand: true, + src: ['LICENSE.md', 'README.md', 'NOTICE.md'], + dest: '<%= pkg.name %>-<%= pkg.version %>/', + } + ] + } + }; +}; \ No newline at end of file diff --git a/tasks/options/concat.js b/tasks/options/concat.js new file mode 100644 index 00000000000..2251435ef51 --- /dev/null +++ b/tasks/options/concat.js @@ -0,0 +1,22 @@ +module.exports = function(config) { + return { + css: { + src: [ + '<%= srcDir %>/css/normalize.min.css', + '<%= srcDir %>/css/timepicker.css', + '<%= srcDir %>/css/spectrum.css', + '<%= srcDir %>/css/animate.min.css', + '<%= srcDir %>/css/bootstrap.dark.min.css' + ], + dest: '<%= srcDir %>/css/default.min.css' + }, + js: { + src: [ + '<%= destDir %>/vendor/require/require.js', + '<%= destDir %>/app/components/require.config.js', + '<%= destDir %>/app/app.js', + ], + dest: '<%= destDir %>/app/app.js' + }, + }; +}; diff --git a/tasks/options/connect.js b/tasks/options/connect.js new file mode 100644 index 00000000000..a2b70e02f96 --- /dev/null +++ b/tasks/options/connect.js @@ -0,0 +1,20 @@ +module.exports = function(config) { + return { + dev: { + options: { + port: 5601, + hostname: '*', + base: config.srcDir, + keepalive: true + } + }, + dist: { + options: { + port: 5605, + hostname: '*', + base: config.destDir, + keepalive: true + } + }, + } +}; diff --git a/tasks/options/copy.js b/tasks/options/copy.js new file mode 100644 index 00000000000..a76466c5417 --- /dev/null +++ b/tasks/options/copy.js @@ -0,0 +1,11 @@ +module.exports = function(config) { + return { + // copy source to temp, we will minify in place for the dist build + everything_but_less_to_temp: { + cwd: '<%= srcDir %>', + expand: true, + src: ['**/*', '!**/*.less', '!config.js'], + dest: '<%= tempDir %>' + } + }; +}; \ No newline at end of file diff --git a/tasks/options/cssmin.js b/tasks/options/cssmin.js new file mode 100644 index 00000000000..b049a383fca --- /dev/null +++ b/tasks/options/cssmin.js @@ -0,0 +1,10 @@ +module.exports = function(config) { + return { + build: { + expand: true, + cwd: '<%= tempDir %>', + src: '**/*.css', + dest: '<%= tempDir %>' + } + }; +}; \ No newline at end of file diff --git a/tasks/options/filerev.js b/tasks/options/filerev.js new file mode 100644 index 00000000000..cd9ca020500 --- /dev/null +++ b/tasks/options/filerev.js @@ -0,0 +1,17 @@ +module.exports = function(config) { + return { + options: { + encoding: 'utf8', + algorithm: 'md5', + length: 8, + }, + css: { + src: '<%= destDir %>/css/default.min.css', + dest: '<%= destDir %>/css' + }, + js: { + src: '<%= destDir %>/app/app.js', + dest: '<%= destDir %>/app' + } + }; +}; diff --git a/tasks/options/git-describe.js b/tasks/options/git-describe.js new file mode 100644 index 00000000000..44df7ac5f74 --- /dev/null +++ b/tasks/options/git-describe.js @@ -0,0 +1,7 @@ +module.exports = function(config) { + return { + me: { + // Target-specific file lists and/or options go here. + } + }; +}; \ No newline at end of file diff --git a/tasks/options/htmlmin.js b/tasks/options/htmlmin.js new file mode 100644 index 00000000000..b5d36b89e77 --- /dev/null +++ b/tasks/options/htmlmin.js @@ -0,0 +1,18 @@ +module.exports = function(config) { + return { + build: { + options:{ + removeComments: true, + collapseWhitespace: true + }, + expand: true, + cwd: '<%= tempDir %>', + src: [ + //'index.html', + 'app/panels/**/*.html', + 'app/partials/**/*.html' + ], + dest: '<%= tempDir %>' + } + }; +}; \ No newline at end of file diff --git a/tasks/options/jscs.js b/tasks/options/jscs.js new file mode 100644 index 00000000000..313893b440d --- /dev/null +++ b/tasks/options/jscs.js @@ -0,0 +1,22 @@ +module.exports = function(config) { + return { + src: [ + 'Gruntfile.js', + '<%= srcDir %>/app/**/*.js', + '!<%= srcDir %>/app/panels/*/{lib,leaflet}/*', + '!<%= srcDir %>/app/dashboards/*' + ], + options: { + config: ".jscs.json", + }, + }; +}; + +/* + "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"], + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], + "disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], + "disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="], + "requireRightStickedOperators": ["!"], + "requireLeftStickedOperators": [","], + */ \ No newline at end of file diff --git a/tasks/options/jshint.js b/tasks/options/jshint.js new file mode 100644 index 00000000000..60c212e785d --- /dev/null +++ b/tasks/options/jshint.js @@ -0,0 +1,26 @@ +module.exports = function(config) { + return { + source: { + files: { + src: ['Gruntfile.js', '<%= srcDir %>/app/**/*.js'], + } + }, + tests: { + files: { + src: ['<%= srcDir %>/test/**/*.js'], + } + }, + options: { + jshintrc: true, + reporter: require('jshint-stylish'), + ignores: [ + 'node_modules/*', + 'dist/*', + 'sample/*', + '<%= srcDir %>/vendor/*', + '<%= srcDir %>/app/panels/*/{lib,leaflet}/*', + '<%= srcDir %>/app/dashboards/*' + ] + } + }; +}; \ No newline at end of file diff --git a/tasks/options/karma.js b/tasks/options/karma.js new file mode 100644 index 00000000000..0318741a329 --- /dev/null +++ b/tasks/options/karma.js @@ -0,0 +1,27 @@ +module.exports = function(config) { + return { + dev: { + configFile: 'src/test/karma.conf.js', + singleRun: false, + }, + debug: { + configFile: 'src/test/karma.conf.js', + singleRun: false, + browsers: ['Chrome'] + }, + test: { + configFile: 'src/test/karma.conf.js', + }, + coveralls: { + configFile: 'src/test/karma.conf.js', + reporters: ['dots','coverage','coveralls'], + preprocessors: { + 'src/app/**/*.js': ['coverage'] + }, + coverageReporter: { + type: 'lcov', + dir: 'coverage/' + } + } + }; +}; diff --git a/tasks/options/less.js b/tasks/options/less.js new file mode 100644 index 00000000000..4d9fe764e03 --- /dev/null +++ b/tasks/options/less.js @@ -0,0 +1,25 @@ +module.exports = function(config) { + return { + // this is the only task, other than copy, that runs on the src directory, since we don't really need + // the less files in the dist. Everything else runs from on temp, and require copys everything + // from temp -> dist + dist:{ + expand: true, + cwd:'<%= srcDir %>/vendor/bootstrap/less/', + src: ['bootstrap.dark.less', 'bootstrap.light.less'], + dest: '<%= tempDir %>/css/', + }, + // Compile in place when not building + src:{ + options: { + paths: ["<%= srcDir %>/vendor/bootstrap/less", "<%= srcDir %>/css/less"], + yuicompress:true + }, + files: { + "<%= srcDir %>/css/bootstrap.dark.min.css": "<%= srcDir %>/css/less/bootstrap.dark.less", + "<%= srcDir %>/css/bootstrap.light.min.css": "<%= srcDir %>/css/less/bootstrap.light.less", + "<%= srcDir %>/css/bootstrap-responsive.min.css": "<%= srcDir %>/css/less/grafana-responsive.less" + } + } + }; +}; \ No newline at end of file diff --git a/tasks/options/meta.js b/tasks/options/meta.js new file mode 100644 index 00000000000..3792f116faa --- /dev/null +++ b/tasks/options/meta.js @@ -0,0 +1,9 @@ +module.exports = function(config) { + return { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' + + ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= pkg.license %> */\n\n' + }; +}; \ No newline at end of file diff --git a/tasks/options/ngmin.js b/tasks/options/ngmin.js new file mode 100644 index 00000000000..39dbb7a540a --- /dev/null +++ b/tasks/options/ngmin.js @@ -0,0 +1,19 @@ +module.exports = function(config) { + return { + build: { + expand:true, + cwd:'<%= tempDir %>', + src: [ + 'app/controllers/**/*.js', + 'app/directives/**/*.js', + 'app/services/**/*.js', + 'app/filters/**/*.js', + 'app/panels/**/*.js', + 'app/routes/**/*.js', + 'app/app.js', + 'vendor/angular/**/*.js', + ], + dest: '<%= tempDir %>' + } + }; +}; diff --git a/tasks/options/ngtemplates.js b/tasks/options/ngtemplates.js new file mode 100644 index 00000000000..7971a102e6c --- /dev/null +++ b/tasks/options/ngtemplates.js @@ -0,0 +1,18 @@ +module.exports = function(config) { + return { + grafana: { + cwd: '<%= tempDir %>', + src: ['app/**/*.html', '!app/panels/*/module.html'], + dest: '<%= tempDir %>/app/components/partials.js', + options: { + bootstrap: function(module, script) { + return "define('components/partials', ['angular'], function(angular) { \n" + + "angular.module('grafana').run(['$templateCache', function($templateCache) { \n" + + script + + '\n}]);' + + '\n});'; + } + } + } + }; +}; \ No newline at end of file diff --git a/tasks/options/requirejs.js b/tasks/options/requirejs.js new file mode 100644 index 00000000000..1d4f04c0606 --- /dev/null +++ b/tasks/options/requirejs.js @@ -0,0 +1,83 @@ +module.exports = function(config,grunt) { + var _c = { + build: { + options: { + appDir: '<%= tempDir %>', + dir: '<%= destDir %>', + + mainConfigFile: '<%= tempDir %>/app/components/require.config.js', + modules: [], // populated below + + optimize: 'none', + optimizeCss: 'none', + optimizeAllPluginResources: false, + + paths: { config: '../config.sample' }, // fix, fallbacks need to be specified + + removeCombined: true, + findNestedDependencies: true, + normalizeDirDefines: 'all', + inlineText: true, + skipPragmas: true, + + done: function (done, output) { + var duplicates = require('rjs-build-analysis').duplicates(output); + + if (duplicates.length > 0) { + grunt.log.subhead('Duplicates found in requirejs build:'); + grunt.log.warn(duplicates); + done(new Error('r.js built duplicate modules, please check the excludes option.')); + } + + done(); + } + } + } + }; + + // setup the modules require will build + var requireModules = _c.build.options.modules = [ + { + // main/common module + name: 'app', + include: [ + 'css', + 'kbn', + 'text', + 'jquery', + 'angular', + 'settings', + 'bootstrap', + 'modernizr', + 'timepicker', + 'datepicker', + 'underscore', + 'filters/all', + 'jquery.flot', + 'services/all', + 'angular-strap', + 'directives/all', + 'jquery.flot.pie', + 'angular-dragdrop', + ] + } + ]; + + var fs = require('fs'); + var panelPath = config.srcDir+'/app/panels' + + // create a module for each directory in src/app/panels/ + fs.readdirSync(panelPath).forEach(function (panelName) { + requireModules[0].include.push('panels/'+panelName+'/module'); + requireModules[0].include.push('text!panels/'+panelName+'/module.html'); + }); + + // exclude the literal config definition from all modules + requireModules + .forEach(function (module) { + module.excludeShallow = module.excludeShallow || []; + module.excludeShallow.push('config'); + }); + + return _c; +}; diff --git a/tasks/options/uglify.js b/tasks/options/uglify.js new file mode 100644 index 00000000000..1ca15b06957 --- /dev/null +++ b/tasks/options/uglify.js @@ -0,0 +1,16 @@ +module.exports = function(config) { + return { + dest: { + expand: true, + src: ['**/*.js', '!config.sample.js', '!app/dashboards/*.js', '!app/dashboards/**/*.js',], + dest: '<%= destDir %>', + cwd: '<%= destDir %>', + options: { + quite: true, + compress: true, + preserveComments: false, + banner: '<%= meta.banner %>' + } + } + }; +}; \ No newline at end of file diff --git a/tasks/options/usemin.js b/tasks/options/usemin.js new file mode 100644 index 00000000000..0abd8ed4ec5 --- /dev/null +++ b/tasks/options/usemin.js @@ -0,0 +1,5 @@ +module.exports = function(config) { + return { + html: '<%= destDir %>/index.html', + }; +}; diff --git a/tasks/options/useminPrepare.js b/tasks/options/useminPrepare.js new file mode 100644 index 00000000000..23bab7e3f22 --- /dev/null +++ b/tasks/options/useminPrepare.js @@ -0,0 +1,5 @@ +module.exports = function(config) { + return { + html: 'tmp/index.html', + }; +}; diff --git a/tasks/server_task.js b/tasks/server_task.js new file mode 100644 index 00000000000..e6fee262a14 --- /dev/null +++ b/tasks/server_task.js @@ -0,0 +1,3 @@ +module.exports = function(grunt) { + grunt.registerTask('server', ['connect:dev']); +}; \ No newline at end of file diff --git a/views/index.html b/views/index.html new file mode 100644 index 00000000000..d8747d1d7a8 --- /dev/null +++ b/views/index.html @@ -0,0 +1,35 @@ + + + + + + + + + Grafana + + + + + + + + + + + + + + + + + +
+ + {{alert.title}}
{{$index + 1}} alert(s)
+
+ +
+ + +