setting.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. // Copyright 2014 Unknwon
  2. // Copyright 2014 Torkel Ödegaard
  3. package setting
  4. import (
  5. "bytes"
  6. "fmt"
  7. "net/url"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "regexp"
  12. "runtime"
  13. "strings"
  14. "gopkg.in/ini.v1"
  15. "github.com/go-macaron/session"
  16. "github.com/grafana/grafana/pkg/log"
  17. "github.com/grafana/grafana/pkg/util"
  18. )
  19. type Scheme string
  20. const (
  21. HTTP Scheme = "http"
  22. HTTPS Scheme = "https"
  23. SOCKET Scheme = "socket"
  24. DEFAULT_HTTP_ADDR string = "0.0.0.0"
  25. )
  26. const (
  27. DEV string = "development"
  28. PROD string = "production"
  29. TEST string = "test"
  30. )
  31. var (
  32. // App settings.
  33. Env string = DEV
  34. AppUrl string
  35. AppSubUrl string
  36. InstanceName string
  37. // build
  38. BuildVersion string
  39. BuildCommit string
  40. BuildStamp int64
  41. // Paths
  42. LogsPath string
  43. HomePath string
  44. DataPath string
  45. PluginsPath string
  46. ProvisioningPath string
  47. CustomInitPath = "conf/custom.ini"
  48. // Log settings.
  49. LogModes []string
  50. LogConfigs []util.DynMap
  51. // Http server options
  52. Protocol Scheme
  53. Domain string
  54. HttpAddr, HttpPort string
  55. SshPort int
  56. CertFile, KeyFile string
  57. SocketPath string
  58. RouterLogging bool
  59. DataProxyLogging bool
  60. StaticRootPath string
  61. EnableGzip bool
  62. EnforceDomain bool
  63. // Security settings.
  64. SecretKey string
  65. LogInRememberDays int
  66. CookieUserName string
  67. CookieRememberName string
  68. DisableGravatar bool
  69. EmailCodeValidMinutes int
  70. DataProxyWhiteList map[string]bool
  71. DisableBruteForceLoginProtection bool
  72. // Snapshots
  73. ExternalSnapshotUrl string
  74. ExternalSnapshotName string
  75. ExternalEnabled bool
  76. SnapShotTTLDays int
  77. SnapShotRemoveExpired bool
  78. // Dashboard history
  79. DashboardVersionsToKeep int
  80. // User settings
  81. AllowUserSignUp bool
  82. AllowUserOrgCreate bool
  83. AutoAssignOrg bool
  84. AutoAssignOrgRole string
  85. VerifyEmailEnabled bool
  86. LoginHint string
  87. DefaultTheme string
  88. DisableLoginForm bool
  89. DisableSignoutMenu bool
  90. ExternalUserMngLinkUrl string
  91. ExternalUserMngLinkName string
  92. ExternalUserMngInfo string
  93. ViewersCanEdit bool
  94. // Http auth
  95. AdminUser string
  96. AdminPassword string
  97. AnonymousEnabled bool
  98. AnonymousOrgName string
  99. AnonymousOrgRole string
  100. // Auth proxy settings
  101. AuthProxyEnabled bool
  102. AuthProxyHeaderName string
  103. AuthProxyHeaderProperty string
  104. AuthProxyAutoSignUp bool
  105. AuthProxyLdapSyncTtl int
  106. AuthProxyWhitelist string
  107. // Basic Auth
  108. BasicAuthEnabled bool
  109. // Plugin settings
  110. PluginAppsSkipVerifyTLS bool
  111. // Session settings.
  112. SessionOptions session.Options
  113. // Global setting objects.
  114. Cfg *ini.File
  115. ConfRootPath string
  116. IsWindows bool
  117. // PhantomJs Rendering
  118. ImagesDir string
  119. PhantomDir string
  120. // for logging purposes
  121. configFiles []string
  122. appliedCommandLineProperties []string
  123. appliedEnvOverrides []string
  124. ReportingEnabled bool
  125. CheckForUpdates bool
  126. GoogleAnalyticsId string
  127. GoogleTagManagerId string
  128. // LDAP
  129. LdapEnabled bool
  130. LdapConfigFile string
  131. LdapAllowSignup bool = true
  132. // SMTP email settings
  133. Smtp SmtpSettings
  134. // QUOTA
  135. Quota QuotaSettings
  136. // Alerting
  137. AlertingEnabled bool
  138. ExecuteAlerts bool
  139. // logger
  140. logger log.Logger
  141. // Grafana.NET URL
  142. GrafanaComUrl string
  143. // S3 temp image store
  144. S3TempImageStoreBucketUrl string
  145. S3TempImageStoreAccessKey string
  146. S3TempImageStoreSecretKey string
  147. ImageUploadProvider string
  148. )
  149. type CommandLineArgs struct {
  150. Config string
  151. HomePath string
  152. Args []string
  153. }
  154. func init() {
  155. IsWindows = runtime.GOOS == "windows"
  156. logger = log.New("settings")
  157. }
  158. func parseAppUrlAndSubUrl(section *ini.Section) (string, string) {
  159. appUrl := section.Key("root_url").MustString("http://localhost:3000/")
  160. if appUrl[len(appUrl)-1] != '/' {
  161. appUrl += "/"
  162. }
  163. // Check if has app suburl.
  164. url, err := url.Parse(appUrl)
  165. if err != nil {
  166. log.Fatal(4, "Invalid root_url(%s): %s", appUrl, err)
  167. }
  168. appSubUrl := strings.TrimSuffix(url.Path, "/")
  169. return appUrl, appSubUrl
  170. }
  171. func ToAbsUrl(relativeUrl string) string {
  172. return AppUrl + relativeUrl
  173. }
  174. func shouldRedactKey(s string) bool {
  175. uppercased := strings.ToUpper(s)
  176. return strings.Contains(uppercased, "PASSWORD") || strings.Contains(uppercased, "SECRET") || strings.Contains(uppercased, "PROVIDER_CONFIG")
  177. }
  178. func shouldRedactURLKey(s string) bool {
  179. uppercased := strings.ToUpper(s)
  180. return strings.Contains(uppercased, "DATABASE_URL")
  181. }
  182. func applyEnvVariableOverrides() {
  183. appliedEnvOverrides = make([]string, 0)
  184. for _, section := range Cfg.Sections() {
  185. for _, key := range section.Keys() {
  186. sectionName := strings.ToUpper(strings.Replace(section.Name(), ".", "_", -1))
  187. keyName := strings.ToUpper(strings.Replace(key.Name(), ".", "_", -1))
  188. envKey := fmt.Sprintf("GF_%s_%s", sectionName, keyName)
  189. envValue := os.Getenv(envKey)
  190. if len(envValue) > 0 {
  191. key.SetValue(envValue)
  192. if shouldRedactKey(envKey) {
  193. envValue = "*********"
  194. }
  195. if shouldRedactURLKey(envKey) {
  196. u, _ := url.Parse(envValue)
  197. ui := u.User
  198. if ui != nil {
  199. _, exists := ui.Password()
  200. if exists {
  201. u.User = url.UserPassword(ui.Username(), "-redacted-")
  202. envValue = u.String()
  203. }
  204. }
  205. }
  206. appliedEnvOverrides = append(appliedEnvOverrides, fmt.Sprintf("%s=%s", envKey, envValue))
  207. }
  208. }
  209. }
  210. }
  211. func applyCommandLineDefaultProperties(props map[string]string) {
  212. appliedCommandLineProperties = make([]string, 0)
  213. for _, section := range Cfg.Sections() {
  214. for _, key := range section.Keys() {
  215. keyString := fmt.Sprintf("default.%s.%s", section.Name(), key.Name())
  216. value, exists := props[keyString]
  217. if exists {
  218. key.SetValue(value)
  219. if shouldRedactKey(keyString) {
  220. value = "*********"
  221. }
  222. appliedCommandLineProperties = append(appliedCommandLineProperties, fmt.Sprintf("%s=%s", keyString, value))
  223. }
  224. }
  225. }
  226. }
  227. func applyCommandLineProperties(props map[string]string) {
  228. for _, section := range Cfg.Sections() {
  229. sectionName := section.Name() + "."
  230. if section.Name() == ini.DEFAULT_SECTION {
  231. sectionName = ""
  232. }
  233. for _, key := range section.Keys() {
  234. keyString := sectionName + key.Name()
  235. value, exists := props[keyString]
  236. if exists {
  237. appliedCommandLineProperties = append(appliedCommandLineProperties, fmt.Sprintf("%s=%s", keyString, value))
  238. key.SetValue(value)
  239. }
  240. }
  241. }
  242. }
  243. func getCommandLineProperties(args []string) map[string]string {
  244. props := make(map[string]string)
  245. for _, arg := range args {
  246. if !strings.HasPrefix(arg, "cfg:") {
  247. continue
  248. }
  249. trimmed := strings.TrimPrefix(arg, "cfg:")
  250. parts := strings.Split(trimmed, "=")
  251. if len(parts) != 2 {
  252. log.Fatal(3, "Invalid command line argument", arg)
  253. return nil
  254. }
  255. props[parts[0]] = parts[1]
  256. }
  257. return props
  258. }
  259. func makeAbsolute(path string, root string) string {
  260. if filepath.IsAbs(path) {
  261. return path
  262. }
  263. return filepath.Join(root, path)
  264. }
  265. func evalEnvVarExpression(value string) string {
  266. regex := regexp.MustCompile(`\${(\w+)}`)
  267. return regex.ReplaceAllStringFunc(value, func(envVar string) string {
  268. envVar = strings.TrimPrefix(envVar, "${")
  269. envVar = strings.TrimSuffix(envVar, "}")
  270. envValue := os.Getenv(envVar)
  271. // if env variable is hostname and it is empty use os.Hostname as default
  272. if envVar == "HOSTNAME" && envValue == "" {
  273. envValue, _ = os.Hostname()
  274. }
  275. return envValue
  276. })
  277. }
  278. func evalConfigValues() {
  279. for _, section := range Cfg.Sections() {
  280. for _, key := range section.Keys() {
  281. key.SetValue(evalEnvVarExpression(key.Value()))
  282. }
  283. }
  284. }
  285. func loadSpecifedConfigFile(configFile string) error {
  286. if configFile == "" {
  287. configFile = filepath.Join(HomePath, CustomInitPath)
  288. // return without error if custom file does not exist
  289. if !pathExists(configFile) {
  290. return nil
  291. }
  292. }
  293. userConfig, err := ini.Load(configFile)
  294. if err != nil {
  295. return fmt.Errorf("Failed to parse %v, %v", configFile, err)
  296. }
  297. userConfig.BlockMode = false
  298. for _, section := range userConfig.Sections() {
  299. for _, key := range section.Keys() {
  300. if key.Value() == "" {
  301. continue
  302. }
  303. defaultSec, err := Cfg.GetSection(section.Name())
  304. if err != nil {
  305. defaultSec, _ = Cfg.NewSection(section.Name())
  306. }
  307. defaultKey, err := defaultSec.GetKey(key.Name())
  308. if err != nil {
  309. defaultKey, _ = defaultSec.NewKey(key.Name(), key.Value())
  310. }
  311. defaultKey.SetValue(key.Value())
  312. }
  313. }
  314. configFiles = append(configFiles, configFile)
  315. return nil
  316. }
  317. func loadConfiguration(args *CommandLineArgs) {
  318. var err error
  319. // load config defaults
  320. defaultConfigFile := path.Join(HomePath, "conf/defaults.ini")
  321. configFiles = append(configFiles, defaultConfigFile)
  322. // check if config file exists
  323. if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) {
  324. fmt.Println("Grafana-server Init Failed: Could not find config defaults, make sure homepath command line parameter is set or working directory is homepath")
  325. os.Exit(1)
  326. }
  327. // load defaults
  328. Cfg, err = ini.Load(defaultConfigFile)
  329. if err != nil {
  330. fmt.Println(fmt.Sprintf("Failed to parse defaults.ini, %v", err))
  331. os.Exit(1)
  332. return
  333. }
  334. Cfg.BlockMode = false
  335. // command line props
  336. commandLineProps := getCommandLineProperties(args.Args)
  337. // load default overrides
  338. applyCommandLineDefaultProperties(commandLineProps)
  339. // load specified config file
  340. err = loadSpecifedConfigFile(args.Config)
  341. if err != nil {
  342. initLogging()
  343. log.Fatal(3, err.Error())
  344. }
  345. // apply environment overrides
  346. applyEnvVariableOverrides()
  347. // apply command line overrides
  348. applyCommandLineProperties(commandLineProps)
  349. // evaluate config values containing environment variables
  350. evalConfigValues()
  351. // update data path and logging config
  352. DataPath = makeAbsolute(Cfg.Section("paths").Key("data").String(), HomePath)
  353. initLogging()
  354. }
  355. func pathExists(path string) bool {
  356. _, err := os.Stat(path)
  357. if err == nil {
  358. return true
  359. }
  360. if os.IsNotExist(err) {
  361. return false
  362. }
  363. return false
  364. }
  365. func setHomePath(args *CommandLineArgs) {
  366. if args.HomePath != "" {
  367. HomePath = args.HomePath
  368. return
  369. }
  370. HomePath, _ = filepath.Abs(".")
  371. // check if homepath is correct
  372. if pathExists(filepath.Join(HomePath, "conf/defaults.ini")) {
  373. return
  374. }
  375. // try down one path
  376. if pathExists(filepath.Join(HomePath, "../conf/defaults.ini")) {
  377. HomePath = filepath.Join(HomePath, "../")
  378. }
  379. }
  380. var skipStaticRootValidation bool = false
  381. func validateStaticRootPath() error {
  382. if skipStaticRootValidation {
  383. return nil
  384. }
  385. if _, err := os.Stat(path.Join(StaticRootPath, "build")); err != nil {
  386. logger.Error("Failed to detect generated javascript files in public/build")
  387. }
  388. return nil
  389. }
  390. func NewConfigContext(args *CommandLineArgs) error {
  391. setHomePath(args)
  392. loadConfiguration(args)
  393. Env = Cfg.Section("").Key("app_mode").MustString("development")
  394. InstanceName = Cfg.Section("").Key("instance_name").MustString("unknown_instance_name")
  395. PluginsPath = makeAbsolute(Cfg.Section("paths").Key("plugins").String(), HomePath)
  396. ProvisioningPath = makeAbsolute(Cfg.Section("paths").Key("provisioning").String(), HomePath)
  397. server := Cfg.Section("server")
  398. AppUrl, AppSubUrl = parseAppUrlAndSubUrl(server)
  399. Protocol = HTTP
  400. if server.Key("protocol").MustString("http") == "https" {
  401. Protocol = HTTPS
  402. CertFile = server.Key("cert_file").String()
  403. KeyFile = server.Key("cert_key").String()
  404. }
  405. if server.Key("protocol").MustString("http") == "socket" {
  406. Protocol = SOCKET
  407. SocketPath = server.Key("socket").String()
  408. }
  409. Domain = server.Key("domain").MustString("localhost")
  410. HttpAddr = server.Key("http_addr").MustString(DEFAULT_HTTP_ADDR)
  411. HttpPort = server.Key("http_port").MustString("3000")
  412. RouterLogging = server.Key("router_logging").MustBool(false)
  413. EnableGzip = server.Key("enable_gzip").MustBool(false)
  414. EnforceDomain = server.Key("enforce_domain").MustBool(false)
  415. StaticRootPath = makeAbsolute(server.Key("static_root_path").String(), HomePath)
  416. if err := validateStaticRootPath(); err != nil {
  417. return err
  418. }
  419. // read data proxy settings
  420. dataproxy := Cfg.Section("dataproxy")
  421. DataProxyLogging = dataproxy.Key("logging").MustBool(false)
  422. // read security settings
  423. security := Cfg.Section("security")
  424. SecretKey = security.Key("secret_key").String()
  425. LogInRememberDays = security.Key("login_remember_days").MustInt()
  426. CookieUserName = security.Key("cookie_username").String()
  427. CookieRememberName = security.Key("cookie_remember_name").String()
  428. DisableGravatar = security.Key("disable_gravatar").MustBool(true)
  429. DisableBruteForceLoginProtection = security.Key("disable_brute_force_login_protection").MustBool(false)
  430. // read snapshots settings
  431. snapshots := Cfg.Section("snapshots")
  432. ExternalSnapshotUrl = snapshots.Key("external_snapshot_url").String()
  433. ExternalSnapshotName = snapshots.Key("external_snapshot_name").String()
  434. ExternalEnabled = snapshots.Key("external_enabled").MustBool(true)
  435. SnapShotRemoveExpired = snapshots.Key("snapshot_remove_expired").MustBool(true)
  436. SnapShotTTLDays = snapshots.Key("snapshot_TTL_days").MustInt(90)
  437. // read dashboard settings
  438. dashboards := Cfg.Section("dashboards")
  439. DashboardVersionsToKeep = dashboards.Key("versions_to_keep").MustInt(20)
  440. // read data source proxy white list
  441. DataProxyWhiteList = make(map[string]bool)
  442. for _, hostAndIp := range util.SplitString(security.Key("data_source_proxy_whitelist").String()) {
  443. DataProxyWhiteList[hostAndIp] = true
  444. }
  445. // admin
  446. AdminUser = security.Key("admin_user").String()
  447. AdminPassword = security.Key("admin_password").String()
  448. users := Cfg.Section("users")
  449. AllowUserSignUp = users.Key("allow_sign_up").MustBool(true)
  450. AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
  451. AutoAssignOrg = users.Key("auto_assign_org").MustBool(true)
  452. AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Viewer"})
  453. VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false)
  454. LoginHint = users.Key("login_hint").String()
  455. DefaultTheme = users.Key("default_theme").String()
  456. ExternalUserMngLinkUrl = users.Key("external_manage_link_url").String()
  457. ExternalUserMngLinkName = users.Key("external_manage_link_name").String()
  458. ExternalUserMngInfo = users.Key("external_manage_info").String()
  459. ViewersCanEdit = users.Key("viewers_can_edit").MustBool(false)
  460. // auth
  461. auth := Cfg.Section("auth")
  462. DisableLoginForm = auth.Key("disable_login_form").MustBool(false)
  463. DisableSignoutMenu = auth.Key("disable_signout_menu").MustBool(false)
  464. // anonymous access
  465. AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false)
  466. AnonymousOrgName = Cfg.Section("auth.anonymous").Key("org_name").String()
  467. AnonymousOrgRole = Cfg.Section("auth.anonymous").Key("org_role").String()
  468. // auth proxy
  469. authProxy := Cfg.Section("auth.proxy")
  470. AuthProxyEnabled = authProxy.Key("enabled").MustBool(false)
  471. AuthProxyHeaderName = authProxy.Key("header_name").String()
  472. AuthProxyHeaderProperty = authProxy.Key("header_property").String()
  473. AuthProxyAutoSignUp = authProxy.Key("auto_sign_up").MustBool(true)
  474. AuthProxyLdapSyncTtl = authProxy.Key("ldap_sync_ttl").MustInt()
  475. AuthProxyWhitelist = authProxy.Key("whitelist").String()
  476. // basic auth
  477. authBasic := Cfg.Section("auth.basic")
  478. BasicAuthEnabled = authBasic.Key("enabled").MustBool(true)
  479. // global plugin settings
  480. PluginAppsSkipVerifyTLS = Cfg.Section("plugins").Key("app_tls_skip_verify_insecure").MustBool(false)
  481. // PhantomJS rendering
  482. ImagesDir = filepath.Join(DataPath, "png")
  483. PhantomDir = filepath.Join(HomePath, "tools/phantomjs")
  484. analytics := Cfg.Section("analytics")
  485. ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)
  486. CheckForUpdates = analytics.Key("check_for_updates").MustBool(true)
  487. GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String()
  488. GoogleTagManagerId = analytics.Key("google_tag_manager_id").String()
  489. ldapSec := Cfg.Section("auth.ldap")
  490. LdapEnabled = ldapSec.Key("enabled").MustBool(false)
  491. LdapConfigFile = ldapSec.Key("config_file").String()
  492. LdapAllowSignup = ldapSec.Key("allow_sign_up").MustBool(true)
  493. alerting := Cfg.Section("alerting")
  494. AlertingEnabled = alerting.Key("enabled").MustBool(true)
  495. ExecuteAlerts = alerting.Key("execute_alerts").MustBool(true)
  496. readSessionConfig()
  497. readSmtpSettings()
  498. readQuotaSettings()
  499. if VerifyEmailEnabled && !Smtp.Enabled {
  500. log.Warn("require_email_validation is enabled but smtp is disabled")
  501. }
  502. // check old key name
  503. GrafanaComUrl = Cfg.Section("grafana_net").Key("url").MustString("")
  504. if GrafanaComUrl == "" {
  505. GrafanaComUrl = Cfg.Section("grafana_com").Key("url").MustString("https://grafana.com")
  506. }
  507. imageUploadingSection := Cfg.Section("external_image_storage")
  508. ImageUploadProvider = imageUploadingSection.Key("provider").MustString("")
  509. return nil
  510. }
  511. func readSessionConfig() {
  512. sec := Cfg.Section("session")
  513. SessionOptions = session.Options{}
  514. SessionOptions.Provider = sec.Key("provider").In("memory", []string{"memory", "file", "redis", "mysql", "postgres", "memcache"})
  515. SessionOptions.ProviderConfig = strings.Trim(sec.Key("provider_config").String(), "\" ")
  516. SessionOptions.CookieName = sec.Key("cookie_name").MustString("grafana_sess")
  517. SessionOptions.CookiePath = AppSubUrl
  518. SessionOptions.Secure = sec.Key("cookie_secure").MustBool()
  519. SessionOptions.Gclifetime = Cfg.Section("session").Key("gc_interval_time").MustInt64(86400)
  520. SessionOptions.Maxlifetime = Cfg.Section("session").Key("session_life_time").MustInt64(86400)
  521. SessionOptions.IDLength = 16
  522. if SessionOptions.Provider == "file" {
  523. SessionOptions.ProviderConfig = makeAbsolute(SessionOptions.ProviderConfig, DataPath)
  524. os.MkdirAll(path.Dir(SessionOptions.ProviderConfig), os.ModePerm)
  525. }
  526. if SessionOptions.CookiePath == "" {
  527. SessionOptions.CookiePath = "/"
  528. }
  529. }
  530. func initLogging() {
  531. // split on comma
  532. LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), ",")
  533. // also try space
  534. if len(LogModes) == 1 {
  535. LogModes = strings.Split(Cfg.Section("log").Key("mode").MustString("console"), " ")
  536. }
  537. LogsPath = makeAbsolute(Cfg.Section("paths").Key("logs").String(), HomePath)
  538. log.ReadLoggingConfig(LogModes, LogsPath, Cfg)
  539. }
  540. func LogConfigurationInfo() {
  541. var text bytes.Buffer
  542. for _, file := range configFiles {
  543. logger.Info("Config loaded from", "file", file)
  544. }
  545. if len(appliedCommandLineProperties) > 0 {
  546. for _, prop := range appliedCommandLineProperties {
  547. logger.Info("Config overridden from command line", "arg", prop)
  548. }
  549. }
  550. if len(appliedEnvOverrides) > 0 {
  551. text.WriteString("\tEnvironment variables used:\n")
  552. for _, prop := range appliedEnvOverrides {
  553. logger.Info("Config overridden from Environment variable", "var", prop)
  554. }
  555. }
  556. logger.Info("Path Home", "path", HomePath)
  557. logger.Info("Path Data", "path", DataPath)
  558. logger.Info("Path Logs", "path", LogsPath)
  559. logger.Info("Path Plugins", "path", PluginsPath)
  560. logger.Info("Path Provisioning", "path", ProvisioningPath)
  561. logger.Info("App mode " + Env)
  562. }