セルフホストの Postgres の Database Monitoring の設定

Database Monitoring は、クエリメトリクス、クエリサンプル、実行計画、データベースの状態、フェイルオーバー、イベントを公開することで、Postgres データベースを詳細に可視化します。

読み取り専用ユーザーとしてログインし、Agent でデータベースから直接テレメトリを収集します。Postgres データベースで Database Monitoring を有効にするには、以下のセットアップを実行します。

  1. データベースパラメーターを構成する
  2. Agent にデータベースへのアクセス権を付与する
  3. Agent をインストールする

はじめに

サポート対象の PostgreSQL バージョン
9.6、10、11、12、13、14、15、16、17、18
前提条件
Postgres の追加提供モジュールがインストールされている必要があります。ほとんどのインストールでは、これはデフォルトで含まれていますが、あまり一般的でないインストールでは、お使いのバージョンの postgresql-contrib パッケージ の追加インストールが必要になる場合があります。
サポート対象の Agent バージョン
7.36.1 以上
パフォーマンスへの影響
Database Monitoring のデフォルトの Agent 構成は保守的ですが、収集間隔やクエリのサンプリングレートなどの設定を調整することで、よりニーズに合ったものにすることができます。大半のワークロードで、Agent はデータベース上のクエリ実行時間の 1 % 未満、および CPU の 1 % 未満を占めています。

Database Monitoring は、ベースとなる Agent 上のインテグレーションとして動作します (ベンチマークを参照)。
プロキシ、ロードバランサー、コネクションプーラー
Datadog Agent は、モニター対象のホストに直接接続する必要があります。セルフホスト型のデータベースの場合は、127.0.0.1 またはソケットを使用してください。Agent は、プロキシ、ロードバランサー、または pgbouncer のようなコネクションプーラーを介してデータベースに接続してはなりません。Agent が実行中に異なるホストに接続すると (フェイルオーバーやロードバランシングなどの場合)、Agent は 2 つのホスト間で統計情報の差を計算し、不正確なメトリクスを生成します。
データセキュリティへの配慮
Agent がお客様のデータベースからどのようなデータを収集するか、またそのデータの安全性をどのように確保しているかについては、機密情報 を参照してください。

Postgres 設定を構成する

postgresql.conf ファイルに以下のパラメーター を構成し、サーバーを再起動すると設定が有効になります。これらのパラメーターの詳細については、Postgres ドキュメント を参照してください。

必須パラメーター

パラメーター説明
shared_preload_librariespg_stat_statementspostgresql.queries.* メトリクスで必要です。pg_stat_statements 拡張機能を使用して、クエリメトリクスの収集を可能にします。
track_activity_query_size4096より大きなクエリを収集するために必要です。pg_stat_activity の SQL テキストのサイズを拡大します。デフォルト値のままにした場合、1024 文字を超えるクエリは収集されません。

オプションパラメーター

パラメーター説明
pg_stat_statements.trackALLストアドプロシージャや関数内のステートメントを追跡することができます。
pg_stat_statements.max10000pg_stat_statements で追跡する正規化されたクエリの数を増やします。多くの異なるクライアントからさまざまな種類のクエリが送信される大容量のデータベースに推奨されます。
pg_stat_statements.track_utilityoffPREPARE や EXPLAIN といったユーティリティコマンドを無効にします。この値を off に設定すると、SELECT、UPDATE、DELETE のようなクエリのみが追跡されます。
track_io_timingonクエリのブロックの読み取りおよび書き込み時間の収集を有効にします。

Agent にアクセスを付与する

Datadog Agent が統計やクエリを収集するためには、データベースサーバーへの読み取り専用のアクセスが必要となります。

Postgres が複製されている場合、以下の SQL コマンドはクラスター内のプライマリデータベースサーバー (ライター) で実行します。Agent は、接続しているデータベースにかかわらず、サーバー上のすべてのデータベースからテレメトリを収集できます。Agent で 別のデータベースに固有のデータに対するカスタムクエリ を実行する必要がない限り、デフォルトの postgres データベースを使用してください。

選択したデータベースに、スーパーユーザー (または十分な権限を持つほかのユーザー) として接続します。たとえば、psql を使用して postgres データベースに接続するには、次のようにします。

psql -h mydb.example.com -d postgres -U postgres

datadog ユーザーを作成します。

CREATE USER datadog WITH password '<PASSWORD>';

datadog ユーザーに関連テーブルへの権限を付与します。

ALTER ROLE datadog INHERIT;

すべてのデータベースに以下のスキーマを作成します。

CREATE SCHEMA datadog;
GRANT USAGE ON SCHEMA datadog TO datadog;
GRANT USAGE ON SCHEMA public TO datadog;
GRANT pg_monitor TO datadog;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

すべてのデータベースに以下のスキーマを作成します。

CREATE SCHEMA datadog;
GRANT USAGE ON SCHEMA datadog TO datadog;
GRANT USAGE ON SCHEMA public TO datadog;
GRANT pg_monitor TO datadog;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

すべてのデータベースに以下のスキーマを作成します。

CREATE SCHEMA datadog;
GRANT USAGE ON SCHEMA datadog TO datadog;
GRANT USAGE ON SCHEMA public TO datadog;
GRANT SELECT ON pg_stat_database TO datadog;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

すべてのデータベースに関数を作成して、Agent が pg_stat_activity および pg_stat_statements の全コンテンツを読み込めるようにします。

CREATE OR REPLACE FUNCTION datadog.pg_stat_activity() RETURNS SETOF pg_stat_activity AS
  $$ SELECT * FROM pg_catalog.pg_stat_activity; $$
LANGUAGE sql
SECURITY DEFINER;
CREATE OR REPLACE FUNCTION datadog.pg_stat_statements() RETURNS SETOF pg_stat_statements AS
    $$ SELECT * FROM pg_stat_statements; $$
LANGUAGE sql
SECURITY DEFINER;
追加のテーブルをクエリする必要があるデータ収集または Custom Metrics の場合は、それらのテーブルの SELECT 権限を datadog ユーザーに付与する必要がある場合があります。例:grant SELECT on <TABLE_NAME> to datadog;詳細については、PostgreSQL Custom Metrics の収集を参照してください。

実行計画関数を作成する

Agent が実行計画を収集できるように、すべてのデータベースに次の関数を作成します。

CREATE OR REPLACE FUNCTION datadog.explain_statement(
   l_query TEXT,
   OUT explain JSON
)
RETURNS SETOF JSON AS
$$
DECLARE
curs REFCURSOR;
plan JSON;

BEGIN
   SET TRANSACTION READ ONLY;

   OPEN curs FOR EXECUTE pg_catalog.concat('EXPLAIN (FORMAT JSON) ', l_query);
   FETCH curs INTO plan;
   CLOSE curs;
   RETURN QUERY SELECT plan;
END;
$$
LANGUAGE 'plpgsql'
RETURNS NULL ON NULL INPUT
SECURITY DEFINER;

パスワードを安全に保管する

Store your password using secret management software such as Vault. You can then reference this password as ENC[<SECRET_NAME>] in your Agent configuration files: for example, ENC[datadog_user_database_password]. See Secrets Management for more information.

The examples on this page use datadog_user_database_password to refer to the name of the secret where your password is stored. It is possible to reference your password in plain text, but this is not recommended.

データベースの権限を確認する

権限が正しく設定されていることを確認するために、次のコマンドを実行して、Agent ユーザーがデータベースに接続してコアテーブルを読み取れることを確認します。

psql -h localhost -U datadog postgres -A \
  -c "select * from pg_stat_database limit 1;" \
  && echo -e "\e[0;32mPostgres connection - OK\e[0m" \
  || echo -e "\e[0;31mCannot connect to Postgres\e[0m"
psql -h localhost -U datadog postgres -A \
  -c "select * from pg_stat_activity limit 1;" \
  && echo -e "\e[0;32mPostgres pg_stat_activity read OK\e[0m" \
  || echo -e "\e[0;31mCannot read from pg_stat_activity\e[0m"
psql -h localhost -U datadog postgres -A \
  -c "select * from pg_stat_statements limit 1;" \
  && echo -e "\e[0;32mPostgres pg_stat_statements read OK\e[0m" \
  || echo -e "\e[0;31mCannot read from pg_stat_statements\e[0m"
psql -h localhost -U datadog postgres -A \
  -c "select * from pg_stat_database limit 1;" \
  && echo -e "\e[0;32mPostgres connection - OK\e[0m" \
  || echo -e "\e[0;31mCannot connect to Postgres\e[0m"
psql -h localhost -U datadog postgres -A \
  -c "select * from datadog.pg_stat_activity() limit 1;" \
  && echo -e "\e[0;32mPostgres pg_stat_activity read OK\e[0m" \
  || echo -e "\e[0;31mCannot read from pg_stat_activity\e[0m"
psql -h localhost -U datadog postgres -A \
  -c "select * from datadog.pg_stat_statements() limit 1;" \
  && echo -e "\e[0;32mPostgres pg_stat_statements read OK\e[0m" \
  || echo -e "\e[0;31mCannot read from pg_stat_statements\e[0m"

パスワードの入力を求められた場合は、datadog ユーザーを作成したときに入力したパスワードを使用してください。

Agent をインストールする

Datadog Agent をインストールすると、Postgres での Database Monitoring に必要な Postgres チェックもインストールされます。 Agent をまだインストールしていない場合は、Agent のインストール手順 を参照してください。そこに記載されている、インストール手順に従います。

モニターする Postgres インスタンスを指すように、Agent の conf.d/postgres.d/conf.yaml ファイルを編集します。すべての構成オプションの一覧は、サンプル postgres.d/conf.yaml を参照してください。

init_config:
instances:
 - dbm: true
   host: localhost
   port: 5432
   username: datadog
   password: 'ENC[datadog_user_database_password]'

  ## Optional: Connect to a different database if needed for `custom_queries`
  # dbname: '<DB_NAME>'

: パスワードに特殊文字が含まれる場合は、単一引用符で囲んでください。

Agent を再起動 して、変更を適用します。

ログの収集 (オプション)

PostgreSQL のデフォルトのログは stderr に記録され、ログに詳細な情報は含まれません。ログ行のプレフィックスに指定されている追加の詳細をファイルに記録してください。詳細については、PostgreSQL の ドキュメント を参照してください。

  1. ログは /etc/postgresql/<VERSION>/main/postgresql.conf ファイル内で構成されます。ステートメント出力を含む通常のログ結果の場合、ログセクションで次のパラメーターを設定します。

      logging_collector = on
      log_line_prefix = '%m [%p] %d %a %u %h %c ' # this pattern is required to correlate metrics in the Datadog product
      log_file_mode = 0644
    
      ## For Windows
      #log_destination = 'eventlog'
    
  2. 詳細な期間メトリクスを収集し、Datadog インターフェイスで検索可能にするには、ステートメントを使用してインラインで構成する必要があります。以下の推奨構成では、すべてのステートメントとその実行時間がログに記録されます。特定の実行時間より長いステートメントのみに出力を制限するには、log_min_duration_statement を必要な最小値 (ミリ秒) に設定します。SQL ステートメントすべてをログに記録することが、組織のプライバシー要件に準拠しているかどうか確認してください。

    : log_statement および log_duration オプションはいずれもコメントアウトされています。このトピックについて詳しくは、こちら をご覧ください。

      log_min_duration_statement = 0    # -1 is disabled, 0 logs all statements
                                        # and their durations, > 0 logs only
                                        # statements running at least this number
                                        # of milliseconds
      #log_statement = 'all'
      #log_duration = on
    
  3. Datadog Agent でのログ収集は、デフォルトで無効になっています。次のようにして、datadog.yaml ファイルで有効化します。

    logs_enabled: true
    
  4. PostgreSQL のログの収集を開始するには、次の構成ブロックを conf.d/postgres.d/conf.yaml ファイルに追加し、編集します。

    logs:
      - type: file
        path: "<LOG_FILE_PATH>"
        source: postgresql
        service: "<SERVICE_NAME>"
        #To handle multi line that starts with yyyy-mm-dd use the following pattern
        #log_processing_rules:
        #  - type: multi_line
        #    pattern: \d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])
        #    name: new_log_start_with_date
    

    service および path パラメーターの値を変更し、ご使用の環境に合わせて構成します。使用可能なすべての構成オプションについては、サンプルの postgres.d/conf.yaml を参照してください。

  5. Agent を再起動 します。

auto_explain を使用して実行計画を収集する (オプション)

デフォルトでは、Agent は実行中のクエリのサンプリングに対してのみ EXPLAIN の実行計画を収集します。これらの実行計画は、特にアプリケーションコードがプリペアドステートメントを使用している場合、より一般的な内容になります。

すべてのクエリから取得した完全な EXPLAIN ANALYZE の実行計画を収集するには、auto_explain を使用する必要があります。これは、PostgreSQL にバンドルされたファーストパーティ拡張機能で、すべての主要プロバイダーで利用可能です。ログ収集は auto_explain 収集 の前提条件であるため、続行する前に有効にしてください。

重要:auto_explain は、難読化されていない SQL に表示される生の値のような、アプリケーションの機密情報が含まれる可能性があるログ行を生成します。dbm_parameterized_queries_read 権限を使用して、生成される計画を表示できるユーザーを制御できますが、ログ行自体は Datadog 組織内のすべてのユーザーに表示されますログに RBAC を使用することで、これらのログが適切なユーザーのみに表示されるようにすることができます。

ログ収集を有効にしたら、次の手順を実行します。

  1. auto_explainpostgresql.confshared_preload_libraries のリストに追加します。たとえば、shared_preload_librariespg_stat_statements に設定されている場合は、これを pg_stat_statements,auto_explain に変更します。

  2. より豊富なイベント相関を有効にするために、log_line_prefix を変更します。このパターンは auto_explain の実行計画を取り込むために必要です。

      log_line_prefix = '%m:%r:%u@%d:[%p]:%l:%e:%s:%v:%x:%c:%q%a:'
    
  3. auto_explain 設定を構成します。ログ形式は json である_必要_がありますが、ほかの設定はアプリケーションに応じて変更できます。この例では、1 秒を超えるすべてのクエリの EXPLAIN ANALYZE の実行計画をログに記録し、バッファ情報は含めますが、オーバーヘッドが発生する可能性があるためタイミング情報は除外します。

     auto_explain.log_format: "json"
     auto_explain.log_min_duration: "1000"
     auto_explain.log_analyze: "on"
     auto_explain.log_buffers: "on"
     auto_explain.log_timing: "off"
     auto_explain.log_triggers: "on"
     auto_explain.log_verbose: "on"
     auto_explain.log_nested_statements: "on"
     auto_explain.sample_rate: "1"
    
  4. Agent を再起動 します。

Agent の設定を確認する

Agent の status サブコマンドを実行 し、[Checks] セクションに postgres があることを確認します。または、データベース ページにアクセスして開始することもできます。

Agent の構成例

One agent connecting to multiple hosts

It is common to configure a single Agent host to connect to multiple remote database instances (see Agent installation architectures for DBM). To connect to multiple hosts, create an entry for each host in the Postgres integration config.

Datadog recommends using one Agent to monitor no more than 30 database instances.

Benchmarks show that one Agent running on a t4g.medium EC2 instance (2 CPUs and 4GB of RAM) can successfully monitor 30 RDS db.t3.medium instances (2 CPUs and 4GB of RAM).
init_config:
instances:
  - dbm: true
    host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    tags:
      - 'env:prod'
      - 'team:team-discovery'
      - 'service:example-service'
  - dbm: true
    host: example-service–replica-1.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    tags:
      - 'env:prod'
      - 'team:team-discovery'
      - 'service:example-service'
  - dbm: true
    host: example-service–replica-2.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    tags:
      - 'env:prod'
      - 'team:team-discovery'
      - 'service:example-service'
    [...]

Monitoring multiple databases on a database host

Use the database_autodiscovery option to permit the Agent to discover all databases on your host to monitor. You can specify include or exclude fields to narrow the scope of databases discovered. See the sample postgres.d/conf.yaml for more details.

init_config:
instances:
  - dbm: true
    host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    database_autodiscovery:
      enabled: true
      # Optionally, set the include field to specify
      # a set of databases you are interested in discovering
      include:
        - mydb.*
        - example.*
    tags:
      - 'env:prod'
      - 'team:team-discovery'
      - 'service:example-service'

Running custom queries

To collect custom metrics, use the custom_queries option. See the sample postgres.d/conf.yaml for more details.

init_config:
instances:
  - dbm: true
    host: localhost
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    custom_queries:
    - metric_prefix: employee
      query: SELECT age, salary, hours_worked, name FROM hr.employees;
      columns:
        - name: custom.employee_age
          type: gauge
        - name: custom.employee_salary
           type: gauge
        - name: custom.employee_hours
           type: count
        - name: name
           type: tag
      tags:
        - 'table:employees'

Monitoring relation metrics for multiple databases

In order to collect relation metrics (such as postgresql.seq_scans, postgresql.dead_rows, postgresql.index_rows_read, and postgresql.table_size), the Agent must be configured to connect to each database (by default, the Agent only connects to the postgres database).

Specify a single “DBM” instance to collect DBM telemetry from all databases. Use the database_autodiscovery option to avoid specifying each database name.

init_config:
instances:
  # This instance is the "DBM" instance. It will connect to the
  # all logical databases, and send DBM telemetry from all databases
  - dbm: true
    host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    database_autodiscovery:
      enabled: true
      exclude:
        - ^users$
        - ^inventory$
    relations:
      - relation_regex: .*
  # This instance only collects data from the `users` database
  # and collects relation metrics from tables prefixed by "2022_"
  - host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    dbname: users
    dbstrict: true
    relations:
      - relation_regex: 2022_.*
        relkind:
          - r
          - i
  # This instance only collects data from the `inventory` database
  # and collects relation metrics only from the specified tables
  - host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    dbname: inventory
    dbstrict: true
    relations:
      - relation_name: products
      - relation_name: external_seller_products

Collecting schemas

To enable this feature, use the collect_schemas option. You must also configure the Agent to connect to each logical database.

Use the database_autodiscovery option to avoid specifying each logical database. See the sample postgres.d/conf.yaml for more details.

init_config:
# This instance only collects data from the `users` database
# and collects relation metrics only from the specified tables
instances:
  - dbm: true
    host: example-service-primary.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    dbname: users
    dbstrict: true
    collect_schemas:
      enabled: true
    relations:
      - products
      - external_seller_products
  # This instance detects every logical database automatically
  # and collects relation metrics from every table
  - dbm: true
    host: example-service–replica-1.example-host.com
    port: 5432
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    database_autodiscovery:
      enabled: true
    collect_schemas:
      enabled: true
    relations:
      - relation_regex: .*

Working with hosts through a proxy

If the Agent must connect through a proxy such as the Cloud SQL Auth proxy, all telemetry is tagged with the hostname of the proxy rather than the database instance. Use the reported_hostname option to set a custom override of the hostname detected by the Agent.

init_config:
instances:
  - dbm: true
    host: localhost
    port: 5000
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    reported_hostname: example-service-primary
  - dbm: true
    host: localhost
    port: 5001
    username: datadog
    password: 'ENC[datadog_user_database_password]'
    reported_hostname: example-service-replica-1

トラブルシューティング

インテグレーションと Agent を手順どおりにインストールおよび構成しても期待通りに動作しない場合は、トラブルシューティング を参照してください。

参考資料