(ns metabase.config
(:require
#_{:clj-kondo/ignore [:discouraged-namespace]}
[cheshire.core :as json]
[clojure.java.io :as io]
[clojure.string :as str]
[environ.core :as env]
[net.cgrand.macrovich :as macros])
(:import
(clojure.lang Keyword))) | |
(set! *warn-on-reflection* true) | |
Indicates whether Enterprise Edition extensions are available this existed long before 0.39.0, but that's when it was made public | (def ^{:doc :added "0.39.0"} ee-available?
(try
#_{:clj-kondo/ignore [:metabase/modules]}
(require 'metabase-enterprise.core)
true
(catch Throwable _
false))) |
Whether code from | (def tests-available?
(try
#_{:clj-kondo/ignore [:metabase/modules]}
(require 'metabase.test.core)
true
(catch Throwable _
false))) |
Are we running on a Windows machine? | (def ^Boolean is-windows?
#_{:clj-kondo/ignore [:discouraged-var]}
(str/includes? (str/lower-case (System/getProperty "os.name")) "win")) |
Global application defaults | (def ^:private app-defaults
{:mb-run-mode "prod"
;; DB Settings
:mb-db-type "h2"
:mb-db-file "metabase.db"
:mb-db-automigrate "true"
:mb-db-logging "true"
;; Jetty Settings. Full list of options is available here: https://github.com/ring-clojure/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj
:mb-jetty-port "3000"
:mb-jetty-join "true"
;; other application settings
:mb-password-complexity "normal"
:mb-version-info-url "https://static.metabase.com/version-info.json"
:mb-version-info-ee-url "https://static.metabase.com/version-info-ee.json"
:mb-ns-trace "" ; comma-separated namespaces to trace
:max-session-age "20160" ; session length in minutes (14 days)
:mb-colorize-logs (str (not is-windows?)) ; since PowerShell and cmd.exe don't support ANSI color escape codes or emoji,
:mb-emoji-in-logs (str (not is-windows?)) ; disable them by default when running on Windows. Otherwise they're enabled
:mb-qp-cache-backend "db"
:mb-jetty-async-response-timeout (str (* 10 60 1000))}) ; 10m |
separate map for EE stuff so merge conflicts aren't annoying. | (def ^:private ee-app-defaults
{:embed-max-session-age "1440"}) ; how long a FULL APP EMBED session is valid for. One day, by default |
(alter-var-root #'app-defaults merge ee-app-defaults) | |
Retrieve value for a single configuration key. Accepts either a keyword or a string. We resolve properties from these places:
| (defn config-str
[k]
(let [k (keyword k)
env-val (k env/env)]
(or (when-not (str/blank? env-val) env-val)
(k app-defaults)))) |
Fetch a configuration key and parse it as an integer. These are convenience functions for accessing config values that ensures a specific return type TODO - These names are bad. They should be something like Fetch a configuration key and parse it as a Long. Fetch a configuration key and parse it as a boolean. Fetch a configuration key and parse it as a keyword. | (defn config-int ^Integer [k] (some-> k config-str Integer/parseInt)) (defn config-long ^Long [k] (some-> k config-str Long/parseLong)) (defn config-bool ^Boolean [k] (some-> k config-str Boolean/parseBoolean)) (defn config-kw ^Keyword [k] (some-> k config-str keyword)) |
The mode in which Metabase is being run | (def run-mode (config-kw :mb-run-mode)) |
Are we running in Are we running in Are we running in | (def ^Boolean is-dev? (= :dev run-mode)) (def ^Boolean is-prod? (= :prod run-mode)) (def ^Boolean is-test? (= :test run-mode)) |
Version stuff | |
(defn- version-info-from-properties-file []
(when-let [props-file (io/resource "version.properties")]
(with-open [reader (io/reader props-file)]
(let [props (java.util.Properties.)]
(.load props reader)
(into {} (for [[k v] props]
[(keyword k) v])))))) | |
Information about the current version of Metabase. Comes from mb-version-info -> {:tag: "v0.11.1", :hash: "afdf863", :date: "2015-10-05"} TODO - Can we make this | (def mb-version-info
(or (version-info-from-properties-file)
;; if version info is not defined for whatever reason
{:tag "vLOCAL_DEV"
:hash "06d1ba2ae111e66253209c01c244d6379acfc6dcb1911fa9ab6012cec9ce52e5"})) |
A formatted version string representing the currently running application.
Looks something like | (def ^String mb-version-string
(let [{:keys [tag hash]} mb-version-info]
(format "%s (%s)" tag hash))) |
A formatted version string including the word 'Metabase' appropriate for passing along
with database connections so admins can identify them as Metabase ones.
Looks something like | (def ^String mb-app-id-string (str "Metabase " (mb-version-info :tag))) |
Detect major version from a version string. ex: (major-version "v1.50.25") -> 50 | (defn major-version
[version-string]
(some-> (second (re-find #"\d+\.(\d+)" version-string))
parse-long)) |
Returns the major version of the running Metabase JAR. When the version.properties file is missing (e.g., running in local dev), returns nil. | (defn current-major-version [] (major-version (:tag mb-version-info))) |
Returns the minor version of the running Metabase JAR. When the version.properties file is missing (e.g., running in local dev), returns nil. | (defn current-minor-version
[]
(some-> (second (re-find #"\d+\.\d+\.(\d+)" (:tag mb-version-info)))
parse-long)) |
This UUID is randomly-generated upon launch and used to identify this specific Metabase instance during
this specifc run. Restarting the server will change this UUID, and each server in a horizontal cluster
will have its own ID, making this different from the | (defonce local-process-uuid (str (random-uuid))) |
A string that contains identifying information about the Metabase version and the local process. | (defonce mb-version-and-process-identifier (format "%s [%s]" mb-app-id-string local-process-uuid)) |
Default user details provided as a JSON string at launch time for first-user setup flow. | (defn mb-user-defaults
[]
(when-let [user-json (env/env :mb-user-defaults)]
(json/parse-string user-json true))) |
The user-id of the internal metabase user. This is needed in the OSS edition to filter out users for setup/has-user-setup. | (def ^:const internal-mb-user-id 13371338) |
Whether to disable database cache. Here for loading circularity reasons. | (def ^:dynamic *disable-setting-cache* false) |
Load sample content on fresh installs?
Using this effectively means | (defn load-sample-content? [] (not (false? (config-bool :mb-load-sample-content)))) |
A unique identifier for the current request. This is bound by
| (def ^:dynamic *request-id* nil) |
Sort of like [[macros/case]] but emits different code for dev or release builds. Useful if you want macros to emit
extra stuff for debugging only in dev builds -- for example [[metabase.util.log]] macros emit extra code for
capturing logs in tests only in Accepts the following keys:
| (defmacro build-type-case
{:style/indent 0}
[& {:keys [dev release], cljs-dev :cljs/dev, cljs-release :cljs/release, clj-dev :clj/dev, clj-release :clj/release}]
(assert (not (and dev (or clj-dev cljs-dev)))
"Cannot specify dev in combination with clj-dev/cljs-dev")
(assert (not (and release (or clj-release cljs-release)))
"Cannot specify release in combination with clj-release/cljs-release")
(let [build-type (macros/case :clj (if tests-available?
:clj/dev
:clj/release)
:cljs (case (:shadow.build/mode &env)
:dev :cljs/dev
:release :cljs/release))]
(case build-type
:clj/dev (or dev clj-dev)
:cljs/dev (or dev cljs-dev)
:clj/release (or release clj-release)
:cljs/release (or release cljs-release)))) |