options.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // Copyright 2019 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package config // import "miniflux.app/config"
  5. import (
  6. "fmt"
  7. "strings"
  8. "miniflux.app/version"
  9. )
  10. const (
  11. defaultHTTPS = false
  12. defaultLogDateTime = false
  13. defaultHSTS = true
  14. defaultHTTPService = true
  15. defaultSchedulerService = true
  16. defaultDebug = false
  17. defaultTiming = false
  18. defaultBaseURL = "http://localhost"
  19. defaultRootURL = "http://localhost"
  20. defaultBasePath = ""
  21. defaultWorkerPoolSize = 5
  22. defaultPollingFrequency = 60
  23. defaultBatchSize = 10
  24. defaultPollingScheduler = "round_robin"
  25. defaultSchedulerEntryFrequencyMinInterval = 5
  26. defaultSchedulerEntryFrequencyMaxInterval = 24 * 60
  27. defaultRunMigrations = false
  28. defaultDatabaseURL = "user=postgres password=postgres dbname=miniflux2 sslmode=disable"
  29. defaultDatabaseMaxConns = 20
  30. defaultDatabaseMinConns = 1
  31. defaultListenAddr = "127.0.0.1:8080"
  32. defaultCertFile = ""
  33. defaultKeyFile = ""
  34. defaultCertDomain = ""
  35. defaultCertCache = "/tmp/cert_cache"
  36. defaultCleanupFrequencyHours = 24
  37. defaultCleanupArchiveReadDays = 60
  38. defaultCleanupArchiveUnreadDays = 180
  39. defaultCleanupRemoveSessionsDays = 30
  40. defaultProxyImages = "http-only"
  41. defaultCreateAdmin = false
  42. defaultAdminUsername = ""
  43. defaultAdminPassword = ""
  44. defaultOAuth2UserCreation = false
  45. defaultOAuth2ClientID = ""
  46. defaultOAuth2ClientSecret = ""
  47. defaultOAuth2RedirectURL = ""
  48. defaultOAuth2OidcDiscoveryEndpoint = ""
  49. defaultOAuth2Provider = ""
  50. defaultPocketConsumerKey = ""
  51. defaultHTTPClientTimeout = 20
  52. defaultHTTPClientMaxBodySize = 15
  53. defaultHTTPClientProxy = ""
  54. defaultAuthProxyHeader = ""
  55. defaultAuthProxyUserCreation = false
  56. defaultMaintenanceMode = false
  57. defaultMaintenanceMessage = "Miniflux is currently under maintenance"
  58. defaultMetricsCollector = false
  59. defaultMetricsRefreshInterval = 60
  60. defaultMetricsAllowedNetworks = "127.0.0.1/8"
  61. )
  62. var defaultHTTPClientUserAgent = "Mozilla/5.0 (compatible; Miniflux/" + version.Version + "; +https://miniflux.app)"
  63. // Options contains configuration options.
  64. type Options struct {
  65. HTTPS bool
  66. logDateTime bool
  67. hsts bool
  68. httpService bool
  69. schedulerService bool
  70. debug bool
  71. serverTimingHeader bool
  72. baseURL string
  73. rootURL string
  74. basePath string
  75. databaseURL string
  76. databaseMaxConns int
  77. databaseMinConns int
  78. runMigrations bool
  79. listenAddr string
  80. certFile string
  81. certDomain string
  82. certCache string
  83. certKeyFile string
  84. cleanupFrequencyHours int
  85. cleanupArchiveReadDays int
  86. cleanupArchiveUnreadDays int
  87. cleanupRemoveSessionsDays int
  88. pollingFrequency int
  89. batchSize int
  90. pollingScheduler string
  91. schedulerEntryFrequencyMinInterval int
  92. schedulerEntryFrequencyMaxInterval int
  93. workerPoolSize int
  94. createAdmin bool
  95. adminUsername string
  96. adminPassword string
  97. proxyImages string
  98. oauth2UserCreationAllowed bool
  99. oauth2ClientID string
  100. oauth2ClientSecret string
  101. oauth2RedirectURL string
  102. oauth2OidcDiscoveryEndpoint string
  103. oauth2Provider string
  104. pocketConsumerKey string
  105. httpClientTimeout int
  106. httpClientMaxBodySize int64
  107. httpClientProxy string
  108. httpClientUserAgent string
  109. authProxyHeader string
  110. authProxyUserCreation bool
  111. maintenanceMode bool
  112. maintenanceMessage string
  113. metricsCollector bool
  114. metricsRefreshInterval int
  115. metricsAllowedNetworks []string
  116. }
  117. // NewOptions returns Options with default values.
  118. func NewOptions() *Options {
  119. return &Options{
  120. HTTPS: defaultHTTPS,
  121. logDateTime: defaultLogDateTime,
  122. hsts: defaultHSTS,
  123. httpService: defaultHTTPService,
  124. schedulerService: defaultSchedulerService,
  125. debug: defaultDebug,
  126. serverTimingHeader: defaultTiming,
  127. baseURL: defaultBaseURL,
  128. rootURL: defaultRootURL,
  129. basePath: defaultBasePath,
  130. databaseURL: defaultDatabaseURL,
  131. databaseMaxConns: defaultDatabaseMaxConns,
  132. databaseMinConns: defaultDatabaseMinConns,
  133. runMigrations: defaultRunMigrations,
  134. listenAddr: defaultListenAddr,
  135. certFile: defaultCertFile,
  136. certDomain: defaultCertDomain,
  137. certCache: defaultCertCache,
  138. certKeyFile: defaultKeyFile,
  139. cleanupFrequencyHours: defaultCleanupFrequencyHours,
  140. cleanupArchiveReadDays: defaultCleanupArchiveReadDays,
  141. cleanupArchiveUnreadDays: defaultCleanupArchiveUnreadDays,
  142. cleanupRemoveSessionsDays: defaultCleanupRemoveSessionsDays,
  143. pollingFrequency: defaultPollingFrequency,
  144. batchSize: defaultBatchSize,
  145. pollingScheduler: defaultPollingScheduler,
  146. schedulerEntryFrequencyMinInterval: defaultSchedulerEntryFrequencyMinInterval,
  147. schedulerEntryFrequencyMaxInterval: defaultSchedulerEntryFrequencyMaxInterval,
  148. workerPoolSize: defaultWorkerPoolSize,
  149. createAdmin: defaultCreateAdmin,
  150. proxyImages: defaultProxyImages,
  151. oauth2UserCreationAllowed: defaultOAuth2UserCreation,
  152. oauth2ClientID: defaultOAuth2ClientID,
  153. oauth2ClientSecret: defaultOAuth2ClientSecret,
  154. oauth2RedirectURL: defaultOAuth2RedirectURL,
  155. oauth2OidcDiscoveryEndpoint: defaultOAuth2OidcDiscoveryEndpoint,
  156. oauth2Provider: defaultOAuth2Provider,
  157. pocketConsumerKey: defaultPocketConsumerKey,
  158. httpClientTimeout: defaultHTTPClientTimeout,
  159. httpClientMaxBodySize: defaultHTTPClientMaxBodySize * 1024 * 1024,
  160. httpClientProxy: defaultHTTPClientProxy,
  161. httpClientUserAgent: defaultHTTPClientUserAgent,
  162. authProxyHeader: defaultAuthProxyHeader,
  163. authProxyUserCreation: defaultAuthProxyUserCreation,
  164. maintenanceMode: defaultMaintenanceMode,
  165. maintenanceMessage: defaultMaintenanceMessage,
  166. metricsCollector: defaultMetricsCollector,
  167. metricsRefreshInterval: defaultMetricsRefreshInterval,
  168. metricsAllowedNetworks: []string{defaultMetricsAllowedNetworks},
  169. }
  170. }
  171. // LogDateTime returns true if the date/time should be displayed in log messages.
  172. func (o *Options) LogDateTime() bool {
  173. return o.logDateTime
  174. }
  175. // HasMaintenanceMode returns true if maintenance mode is enabled.
  176. func (o *Options) HasMaintenanceMode() bool {
  177. return o.maintenanceMode
  178. }
  179. // MaintenanceMessage returns maintenance message.
  180. func (o *Options) MaintenanceMessage() string {
  181. return o.maintenanceMessage
  182. }
  183. // HasDebugMode returns true if debug mode is enabled.
  184. func (o *Options) HasDebugMode() bool {
  185. return o.debug
  186. }
  187. // HasServerTimingHeader returns true if server-timing headers enabled.
  188. func (o *Options) HasServerTimingHeader() bool {
  189. return o.serverTimingHeader
  190. }
  191. // BaseURL returns the application base URL with path.
  192. func (o *Options) BaseURL() string {
  193. return o.baseURL
  194. }
  195. // RootURL returns the base URL without path.
  196. func (o *Options) RootURL() string {
  197. return o.rootURL
  198. }
  199. // BasePath returns the application base path according to the base URL.
  200. func (o *Options) BasePath() string {
  201. return o.basePath
  202. }
  203. // IsDefaultDatabaseURL returns true if the default database URL is used.
  204. func (o *Options) IsDefaultDatabaseURL() bool {
  205. return o.databaseURL == defaultDatabaseURL
  206. }
  207. // DatabaseURL returns the database URL.
  208. func (o *Options) DatabaseURL() string {
  209. return o.databaseURL
  210. }
  211. // DatabaseMaxConns returns the maximum number of database connections.
  212. func (o *Options) DatabaseMaxConns() int {
  213. return o.databaseMaxConns
  214. }
  215. // DatabaseMinConns returns the minimum number of database connections.
  216. func (o *Options) DatabaseMinConns() int {
  217. return o.databaseMinConns
  218. }
  219. // ListenAddr returns the listen address for the HTTP server.
  220. func (o *Options) ListenAddr() string {
  221. return o.listenAddr
  222. }
  223. // CertFile returns the SSL certificate filename if any.
  224. func (o *Options) CertFile() string {
  225. return o.certFile
  226. }
  227. // CertKeyFile returns the private key filename for custom SSL certificate.
  228. func (o *Options) CertKeyFile() string {
  229. return o.certKeyFile
  230. }
  231. // CertDomain returns the domain to use for Let's Encrypt certificate.
  232. func (o *Options) CertDomain() string {
  233. return o.certDomain
  234. }
  235. // CertCache returns the directory to use for Let's Encrypt session cache.
  236. func (o *Options) CertCache() string {
  237. return o.certCache
  238. }
  239. // CleanupFrequencyHours returns the interval in hours for cleanup jobs.
  240. func (o *Options) CleanupFrequencyHours() int {
  241. return o.cleanupFrequencyHours
  242. }
  243. // CleanupArchiveReadDays returns the number of days after which marking read items as removed.
  244. func (o *Options) CleanupArchiveReadDays() int {
  245. return o.cleanupArchiveReadDays
  246. }
  247. // CleanupArchiveUnreadDays returns the number of days after which marking unread items as removed.
  248. func (o *Options) CleanupArchiveUnreadDays() int {
  249. return o.cleanupArchiveUnreadDays
  250. }
  251. // CleanupRemoveSessionsDays returns the number of days after which to remove sessions.
  252. func (o *Options) CleanupRemoveSessionsDays() int {
  253. return o.cleanupRemoveSessionsDays
  254. }
  255. // WorkerPoolSize returns the number of background worker.
  256. func (o *Options) WorkerPoolSize() int {
  257. return o.workerPoolSize
  258. }
  259. // PollingFrequency returns the interval to refresh feeds in the background.
  260. func (o *Options) PollingFrequency() int {
  261. return o.pollingFrequency
  262. }
  263. // BatchSize returns the number of feeds to send for background processing.
  264. func (o *Options) BatchSize() int {
  265. return o.batchSize
  266. }
  267. // PollingScheduler returns the scheduler used for polling feeds.
  268. func (o *Options) PollingScheduler() string {
  269. return o.pollingScheduler
  270. }
  271. // SchedulerEntryFrequencyMaxInterval returns the maximum interval in minutes for the entry frequency scheduler.
  272. func (o *Options) SchedulerEntryFrequencyMaxInterval() int {
  273. return o.schedulerEntryFrequencyMaxInterval
  274. }
  275. // SchedulerEntryFrequencyMinInterval returns the minimum interval in minutes for the entry frequency scheduler.
  276. func (o *Options) SchedulerEntryFrequencyMinInterval() int {
  277. return o.schedulerEntryFrequencyMinInterval
  278. }
  279. // IsOAuth2UserCreationAllowed returns true if user creation is allowed for OAuth2 users.
  280. func (o *Options) IsOAuth2UserCreationAllowed() bool {
  281. return o.oauth2UserCreationAllowed
  282. }
  283. // OAuth2ClientID returns the OAuth2 Client ID.
  284. func (o *Options) OAuth2ClientID() string {
  285. return o.oauth2ClientID
  286. }
  287. // OAuth2ClientSecret returns the OAuth2 client secret.
  288. func (o *Options) OAuth2ClientSecret() string {
  289. return o.oauth2ClientSecret
  290. }
  291. // OAuth2RedirectURL returns the OAuth2 redirect URL.
  292. func (o *Options) OAuth2RedirectURL() string {
  293. return o.oauth2RedirectURL
  294. }
  295. // OAuth2OidcDiscoveryEndpoint returns the OAuth2 OIDC discovery endpoint.
  296. func (o *Options) OAuth2OidcDiscoveryEndpoint() string {
  297. return o.oauth2OidcDiscoveryEndpoint
  298. }
  299. // OAuth2Provider returns the name of the OAuth2 provider configured.
  300. func (o *Options) OAuth2Provider() string {
  301. return o.oauth2Provider
  302. }
  303. // HasHSTS returns true if HTTP Strict Transport Security is enabled.
  304. func (o *Options) HasHSTS() bool {
  305. return o.hsts
  306. }
  307. // RunMigrations returns true if the environment variable RUN_MIGRATIONS is not empty.
  308. func (o *Options) RunMigrations() bool {
  309. return o.runMigrations
  310. }
  311. // CreateAdmin returns true if the environment variable CREATE_ADMIN is not empty.
  312. func (o *Options) CreateAdmin() bool {
  313. return o.createAdmin
  314. }
  315. // AdminUsername returns the admin username if defined.
  316. func (o *Options) AdminUsername() string {
  317. return o.adminUsername
  318. }
  319. // AdminPassword returns the admin password if defined.
  320. func (o *Options) AdminPassword() string {
  321. return o.adminPassword
  322. }
  323. // ProxyImages returns "none" to never proxy, "http-only" to proxy non-HTTPS, "all" to always proxy.
  324. func (o *Options) ProxyImages() string {
  325. return o.proxyImages
  326. }
  327. // HasHTTPService returns true if the HTTP service is enabled.
  328. func (o *Options) HasHTTPService() bool {
  329. return o.httpService
  330. }
  331. // HasSchedulerService returns true if the scheduler service is enabled.
  332. func (o *Options) HasSchedulerService() bool {
  333. return o.schedulerService
  334. }
  335. // PocketConsumerKey returns the Pocket Consumer Key if configured.
  336. func (o *Options) PocketConsumerKey(defaultValue string) string {
  337. if o.pocketConsumerKey != "" {
  338. return o.pocketConsumerKey
  339. }
  340. return defaultValue
  341. }
  342. // HTTPClientTimeout returns the time limit in seconds before the HTTP client cancel the request.
  343. func (o *Options) HTTPClientTimeout() int {
  344. return o.httpClientTimeout
  345. }
  346. // HTTPClientMaxBodySize returns the number of bytes allowed for the HTTP client to transfer.
  347. func (o *Options) HTTPClientMaxBodySize() int64 {
  348. return o.httpClientMaxBodySize
  349. }
  350. // HTTPClientProxy returns the proxy URL for HTTP client.
  351. func (o *Options) HTTPClientProxy() string {
  352. return o.httpClientProxy
  353. }
  354. // HasHTTPClientProxyConfigured returns true if the HTTP proxy is configured.
  355. func (o *Options) HasHTTPClientProxyConfigured() bool {
  356. return o.httpClientProxy != ""
  357. }
  358. // AuthProxyHeader returns an HTTP header name that contains username for
  359. // authentication using auth proxy.
  360. func (o *Options) AuthProxyHeader() string {
  361. return o.authProxyHeader
  362. }
  363. // IsAuthProxyUserCreationAllowed returns true if user creation is allowed for
  364. // users authenticated using auth proxy.
  365. func (o *Options) IsAuthProxyUserCreationAllowed() bool {
  366. return o.authProxyUserCreation
  367. }
  368. // HasMetricsCollector returns true if metrics collection is enabled.
  369. func (o *Options) HasMetricsCollector() bool {
  370. return o.metricsCollector
  371. }
  372. // MetricsRefreshInterval returns the refresh interval in seconds.
  373. func (o *Options) MetricsRefreshInterval() int {
  374. return o.metricsRefreshInterval
  375. }
  376. // MetricsAllowedNetworks returns the list of networks allowed to connect to the metrics endpoint.
  377. func (o *Options) MetricsAllowedNetworks() []string {
  378. return o.metricsAllowedNetworks
  379. }
  380. // HTTPClientUserAgent returns the global User-Agent header for miniflux.
  381. func (o *Options) HTTPClientUserAgent() string {
  382. return o.httpClientUserAgent
  383. }
  384. func (o *Options) String() string {
  385. var builder strings.Builder
  386. builder.WriteString(fmt.Sprintf("LOG_DATE_TIME: %v\n", o.logDateTime))
  387. builder.WriteString(fmt.Sprintf("DEBUG: %v\n", o.debug))
  388. builder.WriteString(fmt.Sprintf("SERVER_TIMING_HEADER: %v\n", o.serverTimingHeader))
  389. builder.WriteString(fmt.Sprintf("HTTP_SERVICE: %v\n", o.httpService))
  390. builder.WriteString(fmt.Sprintf("SCHEDULER_SERVICE: %v\n", o.schedulerService))
  391. builder.WriteString(fmt.Sprintf("HTTPS: %v\n", o.HTTPS))
  392. builder.WriteString(fmt.Sprintf("HSTS: %v\n", o.hsts))
  393. builder.WriteString(fmt.Sprintf("BASE_URL: %v\n", o.baseURL))
  394. builder.WriteString(fmt.Sprintf("ROOT_URL: %v\n", o.rootURL))
  395. builder.WriteString(fmt.Sprintf("BASE_PATH: %v\n", o.basePath))
  396. builder.WriteString(fmt.Sprintf("LISTEN_ADDR: %v\n", o.listenAddr))
  397. builder.WriteString(fmt.Sprintf("DATABASE_URL: %v\n", o.databaseURL))
  398. builder.WriteString(fmt.Sprintf("DATABASE_MAX_CONNS: %v\n", o.databaseMaxConns))
  399. builder.WriteString(fmt.Sprintf("DATABASE_MIN_CONNS: %v\n", o.databaseMinConns))
  400. builder.WriteString(fmt.Sprintf("RUN_MIGRATIONS: %v\n", o.runMigrations))
  401. builder.WriteString(fmt.Sprintf("CERT_FILE: %v\n", o.certFile))
  402. builder.WriteString(fmt.Sprintf("KEY_FILE: %v\n", o.certKeyFile))
  403. builder.WriteString(fmt.Sprintf("CERT_DOMAIN: %v\n", o.certDomain))
  404. builder.WriteString(fmt.Sprintf("CERT_CACHE: %v\n", o.certCache))
  405. builder.WriteString(fmt.Sprintf("CLEANUP_FREQUENCY_HOURS: %v\n", o.cleanupFrequencyHours))
  406. builder.WriteString(fmt.Sprintf("CLEANUP_ARCHIVE_READ_DAYS: %v\n", o.cleanupArchiveReadDays))
  407. builder.WriteString(fmt.Sprintf("CLEANUP_ARCHIVE_UNREAD_DAYS: %v\n", o.cleanupArchiveUnreadDays))
  408. builder.WriteString(fmt.Sprintf("CLEANUP_REMOVE_SESSIONS_DAYS: %v\n", o.cleanupRemoveSessionsDays))
  409. builder.WriteString(fmt.Sprintf("WORKER_POOL_SIZE: %v\n", o.workerPoolSize))
  410. builder.WriteString(fmt.Sprintf("POLLING_FREQUENCY: %v\n", o.pollingFrequency))
  411. builder.WriteString(fmt.Sprintf("BATCH_SIZE: %v\n", o.batchSize))
  412. builder.WriteString(fmt.Sprintf("POLLING_SCHEDULER: %v\n", o.pollingScheduler))
  413. builder.WriteString(fmt.Sprintf("SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL: %v\n", o.schedulerEntryFrequencyMaxInterval))
  414. builder.WriteString(fmt.Sprintf("SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL: %v\n", o.schedulerEntryFrequencyMinInterval))
  415. builder.WriteString(fmt.Sprintf("PROXY_IMAGES: %v\n", o.proxyImages))
  416. builder.WriteString(fmt.Sprintf("CREATE_ADMIN: %v\n", o.createAdmin))
  417. builder.WriteString(fmt.Sprintf("ADMIN_USERNAME: %v\n", o.adminUsername))
  418. builder.WriteString(fmt.Sprintf("ADMIN_PASSWORD: %v\n", o.adminPassword))
  419. builder.WriteString(fmt.Sprintf("POCKET_CONSUMER_KEY: %v\n", o.pocketConsumerKey))
  420. builder.WriteString(fmt.Sprintf("OAUTH2_USER_CREATION: %v\n", o.oauth2UserCreationAllowed))
  421. builder.WriteString(fmt.Sprintf("OAUTH2_CLIENT_ID: %v\n", o.oauth2ClientID))
  422. builder.WriteString(fmt.Sprintf("OAUTH2_CLIENT_SECRET: %v\n", o.oauth2ClientSecret))
  423. builder.WriteString(fmt.Sprintf("OAUTH2_REDIRECT_URL: %v\n", o.oauth2RedirectURL))
  424. builder.WriteString(fmt.Sprintf("OAUTH2_OIDC_DISCOVERY_ENDPOINT: %v\n", o.oauth2OidcDiscoveryEndpoint))
  425. builder.WriteString(fmt.Sprintf("OAUTH2_PROVIDER: %v\n", o.oauth2Provider))
  426. builder.WriteString(fmt.Sprintf("HTTP_CLIENT_TIMEOUT: %v\n", o.httpClientTimeout))
  427. builder.WriteString(fmt.Sprintf("HTTP_CLIENT_MAX_BODY_SIZE: %v\n", o.httpClientMaxBodySize))
  428. builder.WriteString(fmt.Sprintf("HTTP_CLIENT_PROXY: %v\n", o.httpClientProxy))
  429. builder.WriteString(fmt.Sprintf("HTTP_CLIENT_USER_AGENT: %v\n", o.httpClientUserAgent))
  430. builder.WriteString(fmt.Sprintf("AUTH_PROXY_HEADER: %v\n", o.authProxyHeader))
  431. builder.WriteString(fmt.Sprintf("AUTH_PROXY_USER_CREATION: %v\n", o.authProxyUserCreation))
  432. builder.WriteString(fmt.Sprintf("MAINTENANCE_MODE: %v\n", o.maintenanceMode))
  433. builder.WriteString(fmt.Sprintf("MAINTENANCE_MESSAGE: %v\n", o.maintenanceMessage))
  434. builder.WriteString(fmt.Sprintf("METRICS_COLLECTOR: %v\n", o.metricsCollector))
  435. builder.WriteString(fmt.Sprintf("METRICS_REFRESH_INTERVAL: %v\n", o.metricsRefreshInterval))
  436. builder.WriteString(fmt.Sprintf("METRICS_ALLOWED_NETWORKS: %v\n", o.metricsAllowedNetworks))
  437. return builder.String()
  438. }