外掛程式資訊清單

Metabase 外掛程式 JAR 包含外掛程式資訊清單 – 頂層檔案名為 metabase-plugin.yaml。當 Metabase 啟動時,它會迭代 plugins 目錄中的每個 JAR,並在每個 JAR 中尋找資訊清單。此資訊清單會告知 Metabase 外掛程式提供的內容以及如何初始化它。

資訊清單範例

info:
  name: Metabase SQLite Driver
  version: 1.0.0-SNAPSHOT-3.25.2
  description: Allows Metabase to connect to SQLite databases.
contact-info:
  name: Toucan McBird
  address: toucan.mcbird@example.com
driver:
  name: sqlite
  display-name: SQLite
  lazy-load: true
  parent: sql-jdbc
  connection-properties:
    - name: db
      display-name: Filename
      placeholder: /home/camsaul/toucan_sightings.sqlite
      required: true
init:
  - step: load-namespace
    namespace: metabase.driver.sqlite
  - step: register-jdbc-driver
    class: org.sqlite.JDBC

driver 區段告知 Metabase 外掛程式定義了一個名為 :sqlite 的驅動程式,其父項為 :sql-jdbc。Metabase 的外掛程式系統使用這些詳細資訊來呼叫 driver/register!。此外掛程式也列出了驅動程式的顯示名稱和連線屬性,Metabase 的外掛程式系統會使用這些屬性來為 driver/display-namedriver/connection-properties 建立實作。

延遲載入

上方範例中的驅動程式被列為 lazy-load: true,這表示雖然上述方法實作是在 Metabase 啟動時建立的,但 Metabase 不會在有人第一次嘗試連線到使用該驅動程式的資料庫時才初始化該驅動程式。

可以(但不應該)將驅動程式設定為 lazy-load: false,因為這會使 Metabase 花費更長的時間啟動並佔用更多記憶體。

外掛程式初始化

Metabase 會在需要時自動初始化外掛程式。初始化過程大致如下:Metabase 將驅動程式新增至類別路徑,然後依序執行外掛程式資訊清單的每個 init 區段。上方範例資訊清單中,有兩個步驟:load-namespace 步驟和 register-jdbc-driver 步驟。

init:
  - step: load-namespace
    namespace: metabase.driver.sqlite
  - step: register-jdbc-driver
    class: org.sqlite.JDBC

載入命名空間

您需要將一個或多個 load-namespace 步驟新增至您的驅動程式資訊清單,以告知 Metabase 哪些命名空間包含您的驅動程式方法實作。在上述範例中,命名空間為 metabase.driver.sqliteload-namespace一般的 Clojure 方式呼叫 require,這表示它也會根據需要在命名空間宣告的 :require 區段中列出的其他命名空間。如果您的驅動程式的方法實作分散在多個命名空間中,請確保它們也會被載入 – 您可以讓主要命名空間處理此問題(例如,透過將它們包含在命名空間宣告中的 :require 表單中),或透過新增額外的 load-namespace 步驟。

如需命名空間的一些背景資訊,請參閱Clojure 命名空間

註冊 JDBC 驅動程式

在底層使用 JDBC 驅動程式的驅動程式也需要新增 register-jdbc-driver 步驟。

如果您感興趣,原因是 Java 的 JDBC DriverManager 不會使用使用系統 ClassLoader 以外的其他方式載入的 JDBC 驅動程式,這實際上僅表示 Drivermanager 將僅使用作為核心 Metabase uberjar 一部分封裝的 JDBC 驅動程式類別。由於系統類別載入器不允許您在執行階段載入類別路徑,因此 Metabase 使用自訂 ClassLoader 來初始化外掛程式。為了解決此限制,Metabase 隨附了一個 JDBC 代理驅動程式類別,可以封裝其他 JDBC 驅動程式。當 Metabase 呼叫 register-jdbc-driver 時,Metabase 實際上會註冊代理類別的新實例,該實例將方法呼叫轉發到實際的 JDBC 驅動程式。DriverManager 對此完全沒問題。

建置驅動程式

若要將驅動程式建置為外掛程式 JAR,請查看建置驅動程式腳本 README

將您建置的 JAR 放入 Metabase 的 /plugins 目錄中,即可開始使用。

Metabase 外掛程式資訊清單參考

以下是一個附帶註解的外掛程式資訊清單範例,可協助您開始撰寫自己的資訊清單。

# Basic user-facing information about the driver goes under the info: key
info:

  # Make sure to give your plugin a name. In the future, we can show
  # this to the user in a 'plugin management' admin page.
  name: Metabase SQLite Driver

  # For the sake of consistency with the core Metabase project you
  # should use semantic versioning. It's not a bad idea to include the
  # version of its major dependency (e.g., a JDBC driver) when
  # applicable as part of the 'patch' part of the version, so we can
  # update dependencies and have that reflected in the version number
  #
  # For now core Metabase modules should have a version
  # 1.0.0-SNAPSHOT-x until version 1.0 ships and the API for plugins
  # is locked in
  version: 1.0.0-SNAPSHOT-3.25.2

  # Describe what your plugin does. Not used currently, but in the
  # future we may use this description in a plugins admin page.
  description: Allows Metabase to connect to SQLite databases.

# You can list any dependencies needed by the plugin by specifying a
# list of dependencies. If all dependencies are not met, the plugin
# will not be initialized.
#
# A dependency may be either a 'class' or (in the future) a 'plugin' dependency
dependencies:

  # A 'class' dependency checks whether a given class is available on
  # the classpath. It doesn't initialize the class; Metabase defers initialization
  # until it needs to use the driver
  # Don't use this for classes that ship as part of the plugin itself;
  # only use it for external dependencies.
  - class: oracle.jdbc.OracleDriver

    # You may optionally add a message that will be displayed for
    # information purposes in the logs, and possibly in a plugin
    # management page as well in the future
    message: >
      Metabase requires the Oracle JDBC driver to connect to JDBC databases. See
      https://metabase.dev.org.tw/docs/latest/administration-guide/databases/oracle.html
      for more details

  # A 'plugin' dependency checks whether a given plugin is available.
  # The value for 'plugin' is whatever that plugin has as its 'name:' -- make
  # sure you match it exactly!
  #
  # If the dependency is not available when this module is first loaded, the module
  # will be tried again later after more modules are loaded. This means things will
  # still work the way we expect even if, say, we initially attempt to load the
  # BigQuery driver *before* loading its dependency, the shared Google driver. Once
  # the shared Google driver is loaded, Metabase will detect that BigQuery's
  # dependencies are now satisfied and initialize the plugin.
  #
  # In the future, we'll like add version restrictions as well, but for now we only match
  # by name.
  - plugin: Metabase SQLHeavy Driver

# If a plugin adds a driver it should define a driver: section.
#
# To define multiple drivers, you can pass a list of maps instead. Note
# that multiple drivers currently still must share the same dependencies
# set and initialization steps. Thus registering multiple drivers is most
# useful for slight variations on the same driver or including an abstract
# parent driver. Note that init steps will get ran once for each driver
# that gets loaded. This can result in duplicate driver instances registered
# with the DriverManager, which is certainly not ideal but does not actually
# hurt anything.
#
# In the near future I might move init steps into driver itself (or
# at least allow them there)
driver:

  # Name of the driver; corresponds to the keyword (e.g. :sqlite) used
  # in the codebase
  name: sqlite

  # Nice display name shown to admins when connecting a database
  display-name: SQLite

  # Whether loading this driver can be deferred until the first
  # attempt to connect to a database of this type. Default: true. Only
  # set this to false if absolutely neccesary.
  lazy-load: true

  # Parent driver, if any.
  parent: sql-jdbc

  # You may alternatively specify a list of parents for drivers with
  # more than one:
  parent:
    - google
    - sql

  # Whether this driver is abstract. Default: false
  abstract: false

  # List of connection properties to ask users to set to connect to
  # this driver.
  connection-properties:
    # Connection properties can be one of the defaults found in
    # metabase.driver.common, listed by name:
    - dbname
    - host

    # Or a full map for a custom option. Complete schema for custom
    # options can be found in metabase.driver. NOTE: these are not
    # currently translated for i18n; I'm working on a way to translate
    # these. Prefer using one of the defaults from
    # metabase.driver.common if possible.
    - name: db
      display-name: Filename
      placeholder: /home/camsaul/toucan_sightings.sqlite
      required: true

    # Finally, you can use merge: to merge multiple maps. This is
    # useful to override specific properties in one of the defaults.
    - merge:
      - port
      - placeholder: 1433

# Steps to take to initialize the plugin. For lazy-load drivers, this
# is delayed until the driver is initialized the first time we connect
# to a database with it
init:

  # load-namespace tells Metabase to require a namespace from the JAR,
  # you can do whatever Clojurey things you need to do inside that
  # namespace
  - step: load-namespace
    namespace: metabase.driver.sqlite

  # register-jdbc-driver tells Metabase to register a JDBC driver that
  # will be used by this driver. (It actually registers a proxy
  # driver, because DriverManager won't allow drivers that are loaded
  # by different classloaders than it was loaded by (i.e., the system
  # classloader); don't worry to much about this, but know for
  # JDBC-based drivers you need to include your dependency here)
  - step: register-jdbc-driver
    class: org.sqlite.JDBC

接下來

為您的驅動程式實作多重方法

閱讀其他Metabase 版本的文件。