AI事業本部 Dynalystの黒崎(kuro_m88)です。
DatadogのSnowflakeインテグレーションが発表されたのでさっそく試してみました。また、自分の環境だとうまく動作しなかったため、回避方法を紹介します。 Monitor Snowflake with Datadog
どんな機能なのか
冒頭の画像のように、Snowflakeの各種メトリクスがDatadogに連携できます。
しくみとしては、Datadogが直接Snowflakeに接続してデータを取得するのではなく、サーバ等にインストールしたdatadog-agentからSnowflakeへ定期的(デフォルトは1時間)にクエリをなげてメトリクスを取得します。
取得できるデータはたくさんあり、メトリクスの一覧はドキュメントに記述されています。
ひととおりのメトリクスが自動で取得されるため、普段はクレジットとストレージの利用状況をダッシュボードやアラート設定によりモニタリングしておき、定期的に効率の悪いクエリやウェアハウスのサイズの見直しのために貯蓄したデータを分析する環境がすぐに作れます。
カスタムクエリ
標準で取得できるデータ以外に、自分でクエリを定義して、その結果をメトリクスにするという機能があります。これによりクエリで取得できるデータはなんでもメトリクスにできそうです。
Snowpipeを使ってログを自動で取り込んでいるのですが、カスタムクエリを用いると、取り込み件数の推移やエラー件数の状況が確認できます。
custom_queries:
- query: |
SELECT
PIPES.PIPE_NAME,
SUM(HISTORY.ROW_COUNT) as ROW_COUNT,
SUM(HISTORY.ERROR_COUNT) as ERROR_COUNT
FROM
SNOWFLAKE.ACCOUNT_USAGE.PIPES PIPES
LEFT JOIN
SNOWFLAKE.ACCOUNT_USAGE.COPY_HISTORY HISTORY
ON PIPES.PIPE_NAME = HISTORY.PIPE_NAME
AND PIPES.PIPE_NAME = HISTORY.PIPE_NAME
WHERE
PIPES.DELETED IS NULL
AND PIPES.IS_AUTOINGEST_ENABLED = 'YES'
AND HISTORY.LAST_LOAD_TIME >= DATEADD('HOUR', - 3, CURRENT_TIMESTAMP)
AND HISTORY.LAST_LOAD_TIME < DATEADD('HOUR', - 2, CURRENT_TIMESTAMP)
GROUP BY
PIPES.PIPE_NAME
;
columns:
- name: pipe_name
type: tag
- name: snowpipe.last_hour_row_count
type: gauge
- name: snowpipe.last_hour_error_count
type: gauge
SNOWFLAKE.COPY_HISTORYはドキュメントによると最大2時間の反映の遅延があるようです。そのため、3時間前〜2時間前のデータを最新の値として取得してみました。ほかにもシステムテーブル以外にもアプリケーション固有なDatadogのメトリクスにしたい項目もyamlファイルを更新するだけで追加ができるので非常に便利そうでした。
ここからは、検証した環境や手順、遭遇したエラーとその対処について紹介していきます。
検証環境
- クラウド: AWS (東京リージョン)
- VM: Amazon EC2 t3.micro
- OS: Amazon Linux2
- Snowflake: AWS (東京リージョン)
Snowflakeにモニタリング用のユーザとロールを作成する
Snowflakeでアカウント全体のモニタリングができるのは初期状態だとACCOUNTADMINというロールを持ったユーザだけです。このユーザは全てのSnowflakeのユーザの中で一番強い権限を持っており、モニタリングの用途で使うには権限が強すぎるので、モニタリングのみできるロールとユーザと、データ取得のためのウェアハウスを別途作成しました。
ロール作成
CREATE ROLE ACCOUNT_MONITOR; -- モニタリング用のロール, Snowflakeに格納された実データにはアクセスできない
GRANT
MONITOR EXECUTION, -- 所有していないタスクの実行履歴が取得できる
MONITOR USAGE, -- アカウントレベルの機能やクレジットの利用状況が取得できる
ON ACCOUNT TO ROLE ACCOUNT_MONITOR;
GRANT
IMPORTED PRIVILEGES
ON DATABASE SNOWFLAKE TO ROLE ACCOUNT_MONITOR; -- SNOWFLAKEというDBにアクセスできるようにする(ここに各種利用状況のviewなどがある)
GRANT ROLE ACCOUNT_MONITOR TO ROLE ACCOUNTADMIN; -- ACCOUNTADMINを持っている人はロールを切り替えられる, SYSADMINなどでもよさそう
ウェアハウス作成
CREATE WAREHOUSE ACCOUNT_MONITOR_WH WITH WAREHOUSE_SIZE = 'XSMALL' WAREHOUSE_TYPE = 'STANDARD' AUTO_SUSPEND = 60 AUTO_RESUME = TRUE; -- ウェアハウスの最小課金期間は60秒なので60秒で一時停止するようにする
GRANT USAGE ON WAREHOUSE ACCOUNT_MONITOR_WH TO ROLE ACCOUNT_MONITOR;
ユーザ作成
CREATE USER monitor_user DEFAULT_ROLE = 'ACCOUNT_MONITOR' DEFAULT_WAREHOUSE = 'ACCOUNT_MONITOR_WH' DEFAULT_NAMESPACE = 'SNOWFLAKE';
GRANT ROLE ACCOUNT_MONITOR TO USER account_monitor;
ALTER USER account_monitor SET PASSWORD = 'password12345';
datadog-agentのインストール
DD_API_KEYはDatadogのAPIキーを設定してください。
[ec2-user@ip-172-16-10-23 ~]$ DD_AGENT_MAJOR_VERSION=7 DD_API_KEY=xxxxxxxxxxxxx DD_SITE="datadoghq.com" bash -c "$(curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script.sh)"
Snowflake integrationのインストール
標準ではdatadog-agentにSnowflake integrationは入っていないので、追加でインストールします。
[ec2-user@ip-172-16-10-23 ~]$ sudo -u dd-agent datadog-agent integration install datadog-snowflake==2.1.2
設定ファイルをコピーします。
[ec2-user@ip-172-16-10-23 ~]$ sudo -u dd-agent cp /etc/datadog-agent/conf.d/snowflake.d/conf.yaml{.example,}
設定ファイルを編集する
/etc/datadog-agent/conf.d/snowflake.d/conf.yamlを編集します。
init_config:
instances:
- account: ab12345.ap-northeast-1.aws
user: monitor_user
password: password_12345
role: ACCOUNT_MONITOR
datadog-agentを再起動する
[ec2-user@ip-172-16-10-23 ~]$ sudo systemctl restart datadog-agent
本当はこれで動くはずだった
追記: 2020/11/09 datadog-snowflake 2.1.1 で紹介したワークアラウンドが採用されたため、datadog-snowflake 2.1.1以降を使えばこの問題には遭遇しません。
本当はこれで動くはずだったのですが、今回検証した環境ではうまく動きませんでした。以下のようなエラーが出ます。
2020-11-04 03:02:21 UTC | CORE | DEBUG | (pkg/collector/python/loader.go:141 in Load) | Unable to load python module - datadog_checks.snowflake: unable to import module 'datadog_checks.snowflake': Traceback (most recent call last):
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/datadog_checks/snowflake/__init__.py", line 5, in
from .check import SnowflakeCheck
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/datadog_checks/snowflake/check.py", line 6, in
import snowflake.connector as sf
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/snowflake/connector/__init__.py", line 21, in
from .connection import SnowflakeConnection
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/snowflake/connector/connection.py", line 16, in
from .incident import IncidentAPI
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/snowflake/connector/incident.py", line 15, in
from .network import REQUEST_ID
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/snowflake/connector/network.py", line 42, in
from .description import (
File "/opt/datadog-agent/embedded/lib/python3.8/site-packages/snowflake/connector/description.py", line 20, in
PLATFORM = platform.platform()
File "/opt/datadog-agent/embedded/lib/python3.8/platform.py", line 1205, in platform
libcname, libcversion = libc_ver(sys.executable)
File "/opt/datadog-agent/embedded/lib/python3.8/platform.py", line 193, in libc_ver
with open(executable, 'rb') as f:
IsADirectoryError: [Errno 21] Is a directory: '/opt/datadog-agent/embedded/lib/python3.8/site-packages'
今回はDatadogのSnowflakeインテグレーションについての記事なので詳細は割愛しますが、どうやらPython3.8以降の標準ライブラリの挙動が関係していそうです。
Python本体へのissueの起票とプルリクエスト、ワークアラウンドとしてdatadogのSnowflakeインテグレーションへこのエラーを回避する実装のプルリクエストを上げてあります。
- Python本体へ問題を報告したIssue: https://bugs.python.org/issue42257
- Pythonの標準ライブラリの実装の修正のプルリクエスト: https://github.com/python/cpython/pull/23140
- datadog-snowflakeが動かないことを報告したIssue: https://github.com/DataDog/integrations-core/issues/7931
- とりあえず動くようにしたかったのでワークアラウンドの提案: https://github.com/DataDog/integrations-core/pull/7932 (グローバルな値を汚染するのであまり良いアイデアではなさそうです)
datadog-snowflakeが動くようにするための修正
恒久的にどう対応すればよいのかは、前述のIssue等で相談して考えようと思っていますが、まずは動かして機能の検証がしたかったので、とりあえず動く方法を紹介します。
修正内容はこのプルリクエストの通りなのですが、Snowflakeインテグレーションのインストール後に編集したほうが動作検証としては楽です。
/opt/datadog-agent/embedded/lib/python3.8/site-packages/datadog_checks/snowflake/__init__.py を以下のように編集します。
# (C) Datadog, Inc. 2020-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import sys
if not sys.executable:
sys.executable = None
from .__about__ import __version__
from .check import SnowflakeCheck
__all__ = ['__version__', 'SnowflakeCheck']
編集したらdatadog-agentを再起動します。これで動くようになるはずです。
まとめ
DatadogのSnowflakeインテグレーションが出たのでさっそく触ってみましたが、とても便利そうです。元々はTableauを使って自前で作り込んだり、メトリクスをDatadogに送信するバッチを作ったりしようかと思っていたのですが、今回のリリースによりその必要がなくなりました。カスタムクエリを実行して、それがそのままメトリクスになるのはとても便利そうで、期待以上の機能でした。
欲を言えば、Snowflakeは公開鍵認証に対応していて、パスワードを使わずに認証することも可能なので、公開鍵認証にも対応してほしいと思いました。OSSなのでコントリビュートすることも可能です。
Snowflakeのモニタリングのためだけにサーバを用意するのはもったいないので、そのままインストールしても動かない件が解決できればコンテナ化して本番運用に載せようと思います。