(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 (require 'metabase-enterprise.core) true (catch Throwable _ false))) |
Whether code from | (def tests-available? (try (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 boolean. Fetch a configuration key and parse it as a keyword. | (defn config-int ^Integer [k] (some-> k config-str Integer/parseInt)) (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)))) |