func sendUsageStats() { log.Trace("Sending anonymous usage stats to stats.grafana.org") version := strings.Replace(setting.BuildVersion, ".", "_", -1) metrics := map[string]interface{}{} report := map[string]interface{}{ "version": version, "metrics": metrics, } UsageStats.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: if metric.Count() > 0 { metrics[name+".count"] = metric.Count() metric.Clear() } } }) statsQuery := m.GetSystemStatsQuery{} if err := bus.Dispatch(&statsQuery); err != nil { log.Error(3, "Failed to get system stats", err) return } metrics["stats.dashboards.count"] = statsQuery.Result.DashboardCount metrics["stats.users.count"] = statsQuery.Result.UserCount metrics["stats.orgs.count"] = statsQuery.Result.OrgCount dsStats := m.GetDataSourceStatsQuery{} if err := bus.Dispatch(&dsStats); err != nil { log.Error(3, "Failed to get datasource stats", err) return } // send counters for each data source // but ignore any custom data sources // as sending that name could be sensitive information dsOtherCount := 0 for _, dsStat := range dsStats.Result { if m.IsKnownDataSourcePlugin(dsStat.Type) { metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count } else { dsOtherCount += dsStat.Count } } metrics["stats.ds.other.count"] = dsOtherCount out, _ := json.MarshalIndent(report, "", " ") data := bytes.NewBuffer(out) client := http.Client{Timeout: time.Duration(5 * time.Second)} go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data) }
func inTransaction2(callback dbTransactionFunc2) error { var err error sess := session{Session: x.NewSession()} defer sess.Close() if err = sess.Begin(); err != nil { return err } err = callback(&sess) if err != nil { sess.Rollback() return err } else if err = sess.Commit(); err != nil { return err } if len(sess.events) > 0 { for _, e := range sess.events { if err = bus.Publish(e); err != nil { log.Error(3, "Failed to publish event after commit", err) } } } return nil }
func (mg *Migrator) exec(m Migration) error { if mg.LogLevel <= log.INFO { log.Info("Migrator: exec migration id: %v", m.Id()) } err := mg.inTransaction(func(sess *xorm.Session) error { condition := m.GetCondition() if condition != nil { sql, args := condition.Sql(mg.dialect) results, err := sess.Query(sql, args...) if err != nil || len(results) == 0 { log.Info("Migrator: skipping migration id: %v, condition not fulfilled", m.Id()) return sess.Rollback() } } _, err := sess.Exec(m.Sql(mg.dialect)) if err != nil { log.Error(3, "Migrator: exec FAILED migration id: %v, err: %v", m.Id(), err) return err } return nil }) if err != nil { return err } return nil }
func (ctx *Context) JsonApiErr(status int, message string, err error) { resp := make(map[string]interface{}) if err != nil { log.Error(4, "%s: %v", message, err) if setting.Env != setting.PROD { resp["error"] = err.Error() } } switch status { case 404: metrics.M_Api_Status_404.Inc(1) resp["message"] = "Not Found" case 500: metrics.M_Api_Status_500.Inc(1) resp["message"] = "Internal Server Error" } if message != "" { resp["message"] = message } ctx.JSON(status, resp) }
func EnsureAdminUser() { statsQuery := m.GetSystemStatsQuery{} if err := bus.Dispatch(&statsQuery); err != nil { log.Fatal(3, "Could not determine if admin user exists: %v", err) return } if statsQuery.Result.UserCount > 0 { return } cmd := m.CreateUserCommand{} cmd.Login = setting.AdminUser cmd.Email = setting.AdminUser + "@localhost" cmd.Password = setting.AdminPassword cmd.IsAdmin = true if err := bus.Dispatch(&cmd); err != nil { log.Error(3, "Failed to create default admin user", err) return } log.Info("Created default admin user: %v", setting.AdminUser) }
func loginUserWithUser(user *m.User, c *middleware.Context) { if user == nil { log.Error(3, "User login with nil user") } days := 86400 * setting.LogInRememberDays c.SetCookie(setting.CookieUserName, user.Login, days, setting.AppSubUrl+"/") c.SetSuperSecureCookie(util.EncodeMd5(user.Rands+user.Password), setting.CookieRememberName, user.Login, days, setting.AppSubUrl+"/") c.Session.Set(middleware.SESS_KEY_USERID, user.Id) }
func (index *JsonDashIndex) updateLoop() { ticker := time.NewTicker(time.Minute) for { select { case <-ticker.C: if err := index.updateIndex(); err != nil { log.Error(3, "Failed to update dashboard json index %v", err) } } } }
func initContextWithUserSessionCookie(ctx *Context) bool { // initialize session if err := ctx.Session.Start(ctx); err != nil { log.Error(3, "Failed to start session", err) return false } var userId int64 if userId = getRequestUserId(ctx); userId == 0 { return false } query := m.GetSignedInUserQuery{UserId: userId} if err := bus.Dispatch(&query); err != nil { log.Error(3, "Failed to get user with id %v", userId) return false } else { ctx.SignedInUser = query.Result ctx.IsSignedIn = true return true } }
func loadSpecifedConfigFile(configFile string) { if configFile == "" { configFile = filepath.Join(HomePath, "conf/custom.ini") // return without error if custom file does not exist if !pathExists(configFile) { return } } userConfig, err := ini.Load(configFile) userConfig.BlockMode = false if err != nil { log.Fatal(3, "Failed to parse %v, %v", configFile, err) } for _, section := range userConfig.Sections() { for _, key := range section.Keys() { if key.Value() == "" { continue } defaultSec, err := Cfg.GetSection(section.Name()) if err != nil { log.Error(3, "Unknown config section %s defined in %s", section.Name(), configFile) continue } defaultKey, err := defaultSec.GetKey(key.Name()) if err != nil { log.Error(3, "Unknown config key %s defined in section %s, in file %s", key.Name(), section.Name(), configFile) continue } defaultKey.SetValue(key.Value()) } } configFiles = append(configFiles, configFile) }
func initContextWithAuthProxy(ctx *Context) bool { if !setting.AuthProxyEnabled { return false } proxyHeaderValue := ctx.Req.Header.Get(setting.AuthProxyHeaderName) if len(proxyHeaderValue) == 0 { return false } query := getSignedInUserQueryForProxyAuth(proxyHeaderValue) if err := bus.Dispatch(query); err != nil { if err != m.ErrUserNotFound { ctx.Handle(500, "Failed find user specifed in auth proxy header", err) return true } if setting.AuthProxyAutoSignUp { cmd := getCreateUserCommandForProxyAuth(proxyHeaderValue) if err := bus.Dispatch(cmd); err != nil { ctx.Handle(500, "Failed to create user specified in auth proxy header", err) return true } query = &m.GetSignedInUserQuery{UserId: cmd.Result.Id} if err := bus.Dispatch(query); err != nil { ctx.Handle(500, "Failed find user after creation", err) return true } } else { return false } } // initialize session if err := ctx.Session.Start(ctx); err != nil { log.Error(3, "Failed to start session", err) return false } ctx.SignedInUser = query.Result ctx.IsSignedIn = true ctx.Session.Set(SESS_KEY_USERID, ctx.UserId) return true }
func processMailQueue() { for { select { case msg := <-mailQueue: num, err := buildAndSend(msg) tos := strings.Join(msg.To, "; ") info := "" if err != nil { if len(msg.Info) > 0 { info = ", info: " + msg.Info } log.Error(4, fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err)) } else { log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info)) } } } }
func (scanner *PluginScanner) walker(path string, f os.FileInfo, err error) error { if err != nil { return err } if f.IsDir() { return nil } if f.Name() == "plugin.json" { err := scanner.loadPluginJson(path) if err != nil { log.Error(3, "Failed to load plugin json file: %v, err: %v", path, err) scanner.errors = append(scanner.errors, err) } } return nil }
func (mg *Migrator) Start() error { if mg.LogLevel <= log.INFO { log.Info("Migrator: Starting DB migration") } logMap, err := mg.GetMigrationLog() if err != nil { return err } for _, m := range mg.migrations { _, exists := logMap[m.Id()] if exists { if mg.LogLevel <= log.DEBUG { log.Debug("Migrator: Skipping migration: %v, Already executed", m.Id()) } continue } sql := m.Sql(mg.dialect) record := MigrationLog{ MigrationId: m.Id(), Sql: sql, Timestamp: time.Now(), } if mg.LogLevel <= log.DEBUG { log.Debug("Migrator: Executing SQL: \n %v \n", sql) } if err := mg.exec(m); err != nil { log.Error(3, "Migrator: error: \n%s:\n%s", err, sql) record.Error = err.Error() mg.x.Insert(&record) return err } else { record.Success = true mg.x.Insert(&record) } } return nil }
func RenderToPng(params *RenderOpts) (string, error) { log.Info("PhantomRenderer::renderToPng url %v", params.Url) binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "phantomjs")) scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js")) pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20))) pngPath = pngPath + ".png" cmd := exec.Command(binPath, "--ignore-ssl-errors=true", "--ssl-protocol=any", scriptPath, "url="+params.Url, "width="+params.Width, "height="+params.Height, "png="+pngPath, "cookiename="+setting.SessionOptions.CookieName, "domain="+setting.Domain, "sessionid="+params.SessionId) stdout, err := cmd.StdoutPipe() if err != nil { return "", err } stderr, err := cmd.StderrPipe() if err != nil { return "", err } err = cmd.Start() if err != nil { return "", err } go io.Copy(os.Stdout, stdout) go io.Copy(os.Stdout, stderr) done := make(chan error) go func() { cmd.Wait() close(done) }() select { case <-time.After(15 * time.Second): if err := cmd.Process.Kill(); err != nil { log.Error(4, "failed to kill: %v", err) } case <-done: } return pngPath, nil }
func initContextWithAnonymousUser(ctx *Context) bool { if !setting.AnonymousEnabled { return false } orgQuery := m.GetOrgByNameQuery{Name: setting.AnonymousOrgName} if err := bus.Dispatch(&orgQuery); err != nil { log.Error(3, "Anonymous access organization error: '%s': %s", setting.AnonymousOrgName, err) return false } else { ctx.IsSignedIn = false ctx.AllowAnonymous = true ctx.SignedInUser = &m.SignedInUser{} ctx.OrgRole = m.RoleType(setting.AnonymousOrgRole) ctx.OrgId = orgQuery.Result.Id ctx.OrgName = orgQuery.Result.Name return true } }
// Handle handles and logs error by given status. func (ctx *Context) Handle(status int, title string, err error) { if err != nil { log.Error(4, "%s: %v", title, err) if setting.Env != setting.PROD { ctx.Data["ErrorMsg"] = err } } switch status { case 200: metrics.M_Page_Status_200.Inc(1) case 404: metrics.M_Page_Status_404.Inc(1) case 500: metrics.M_Page_Status_500.Inc(1) } ctx.Data["Title"] = title ctx.HTML(status, strconv.Itoa(status)) }
// special case for panel render calls with api key func initContextWithApiKeyFromSession(ctx *Context) bool { keyId := ctx.Session.Get(SESS_KEY_APIKEY) if keyId == nil { return false } keyQuery := m.GetApiKeyByIdQuery{ApiKeyId: keyId.(int64)} if err := bus.Dispatch(&keyQuery); err != nil { log.Error(3, "Failed to get api key by id", err) return false } else { apikey := keyQuery.Result ctx.IsSignedIn = true ctx.SignedInUser = &m.SignedInUser{} ctx.OrgRole = apikey.Role ctx.ApiKeyId = apikey.Id ctx.OrgId = apikey.OrgId return true } }
func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, error) { orgDataSources := make([]*m.DataSource, 0) if c.OrgId != 0 { query := m.GetDataSourcesQuery{OrgId: c.OrgId} err := bus.Dispatch(&query) if err != nil { return nil, err } orgDataSources = query.Result } datasources := make(map[string]interface{}) var defaultDatasource string for _, ds := range orgDataSources { url := ds.Url if ds.Access == m.DS_ACCESS_PROXY { url = setting.AppSubUrl + "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) } var dsMap = map[string]interface{}{ "type": ds.Type, "name": ds.Name, "url": url, } meta, exists := plugins.DataSources[ds.Type] if !exists { log.Error(3, "Could not find plugin definition for data source: %v", ds.Type) continue } dsMap["meta"] = meta if ds.IsDefault { defaultDatasource = ds.Name } if len(ds.JsonData) > 0 { dsMap["jsonData"] = ds.JsonData } if ds.Access == m.DS_ACCESS_DIRECT { if ds.BasicAuth { dsMap["basicAuth"] = util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword) } if ds.WithCredentials { dsMap["withCredentials"] = ds.WithCredentials } if ds.Type == m.DS_INFLUXDB_08 { dsMap["username"] = ds.User dsMap["password"] = ds.Password dsMap["url"] = url + "/db/" + ds.Database } if ds.Type == m.DS_INFLUXDB { dsMap["username"] = ds.User dsMap["password"] = ds.Password dsMap["database"] = ds.Database dsMap["url"] = url } } if ds.Type == m.DS_ES { dsMap["index"] = ds.Database } if ds.Type == m.DS_PROMETHEUS { // add unproxied server URL for link to Prometheus web UI dsMap["directUrl"] = ds.Url } datasources[ds.Name] = dsMap } // add grafana backend data source grafanaDatasourceMeta, _ := plugins.DataSources["grafana"] datasources["-- Grafana --"] = map[string]interface{}{ "type": "grafana", "meta": grafanaDatasourceMeta, } // add mixed backend data source datasources["-- Mixed --"] = map[string]interface{}{ "type": "mixed", "meta": plugins.DataSources["mixed"], } if defaultDatasource == "" { defaultDatasource = "-- Grafana --" } jsonObj := map[string]interface{}{ "defaultDatasource": defaultDatasource, "datasources": datasources, "appSubUrl": setting.AppSubUrl, "allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin, "buildInfo": map[string]interface{}{ "version": setting.BuildVersion, "commit": setting.BuildCommit, "buildstamp": setting.BuildStamp, }, } return jsonObj, nil }