|
| 1 | +--- |
| 2 | +title: "HyperDXを試す" |
| 3 | +date: 2025/06/18 00:00:00 |
| 4 | +postid: a |
| 5 | +tag: |
| 6 | + - HyperDX |
| 7 | + - CNCF |
| 8 | + - オブサーバビリティ |
| 9 | + - OpenTelemetry |
| 10 | +category: |
| 11 | + - Programming |
| 12 | +thumbnail: /images/20250618a/thumbnail.png |
| 13 | +author: 澁川喜規 |
| 14 | +lede: "HyperDXはいわゆるオブザーバービリティに属すプロダクトです。この領域のプロダクトはかなりのデータ量を扱う必要があったり、可用性のために、ストレージとビューアが分かれていたり、大量のツールと連携させる必要があったりします。" |
| 15 | +--- |
| 16 | +[CNCF連載](/articles/20250616a/) 3日目はHyperDXを試してみたという記事です。とはいっても、HyperDX自体はCNCFに登録されたプロダクトでもなんでもないのですが(OpenTelemetry関連という接点はあり)、興味あったので試してみました。 |
| 17 | + |
| 18 | +HyperDXはいわゆるオブザーバービリティに属すプロダクトです。この領域のプロダクトはかなりのデータ量を扱う必要があったり、可用性のために、ストレージとビューアが分かれていたり、大量のツールと連携させる必要があったりします。 |
| 19 | + |
| 20 | +ELKスタックだと、ElasticsearchとLokiとKibana。GrafanaはLokiとPrometheusを連携させたり。OpenTelemetryのときによくデモされたJaegerはDBとビューを持ってトレースの機能を備えていてオールインワンです。 |
| 21 | + |
| 22 | +本番環境はSaaSにまるっと運用をお任せというのが良いとは思いますが、ローカルの作ったり壊したりする環境用良さそうなツールを探してみて見つけたのがHyperDXでした。 |
| 23 | + |
| 24 | +* ログ、メトリックス、トレースに対応 |
| 25 | +* ストレージもUIも持っている |
| 26 | +* OpenTelemetry対応 |
| 27 | + |
| 28 | +HyperDX自身はプロダクション環境でも使えるレベルのプロダクトのようです。管理画面のユーザー管理も厳しいパスワード条件の要求などもしてきます。今回はローカル開発で気軽に使いたい、という目的だったので、管理ユーザーもないローカル版を入れます。ユーザー管理付きのオールインワン版とか、クラウドのClickHouseストレージを使うバージョンとかもあります。 |
| 29 | + |
| 30 | +以下のDockerコマンドで起動します。 |
| 31 | + |
| 32 | +```sh |
| 33 | +$ docker run -p 4318:4318 -p 4317:4317 -p 8080:8080 |
| 34 | + -v ./mongodb:/data/db |
| 35 | + docker.hyperdx.io/hyperdx/hyperdx-local |
| 36 | + |
| 37 | +(略) |
| 38 | + |
| 39 | +Send OpenTelemetry data via: |
| 40 | + http/protobuf: OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 |
| 41 | + gRPC: OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 |
| 42 | + |
| 43 | +Exporting data to ClickHouse: |
| 44 | + Endpoint: tcp://ch-server:9000?dial_timeout=10s |
| 45 | + Database: default |
| 46 | + |
| 47 | +Waiting for ClickHouse to be ready... |
| 48 | +ClickHouse is ready! |
| 49 | + |
| 50 | +Visit the HyperDX UI at http://localhost:8080 |
| 51 | +``` |
| 52 | + |
| 53 | +ウェブのインタフェースが8080ポート、gRPCの情報受付が4317ポートです。 |
| 54 | + |
| 55 | +なお、このイメージは永続化可能なパスが3つあります。ローカルで気軽に使いたいという用途なのでログ自身は消えても良いので管理画面のデータだけ永続化するようにしています。 |
| 56 | + |
| 57 | +* `/data/db` (HyperDXの管理画面で設定する情報を保持するMongoDBのデータ) |
| 58 | +* `/var/lib/clickhouse` (バックエンドのDBのClickHouseのデータ) |
| 59 | +* `/var/log/clickhouse-server` (バックエンドのDBのClickHouseのログ) |
| 60 | + |
| 61 | +# Pythonアプリケーションを作る |
| 62 | + |
| 63 | +OpenTelemetryで情報を出力するPythonアプリケーションを作ります。FastAPIで作ります。 |
| 64 | + |
| 65 | +```shell |
| 66 | +mkdir pysample |
| 67 | +uv init |
| 68 | +uv add fastapi --extra standard |
| 69 | +``` |
| 70 | + |
| 71 | +OpenTelemetryのトレースのspanを追加するために、traceパッケージを利用します。いまどきのOpenTelemetryは[ゼロコードコンフィグ](https://opentelemetry.io/docs/zero-code/python/)ということで、接続先の情報はプログラムに書いたりしないという方法が追加されたようです。言語によって手法は違うようですが、モンキーパッチやeBPFなんかを利用するようです。なので接続情報はこのコードにはありません。 |
| 72 | + |
| 73 | +```shell |
| 74 | +uv add opentelemetry-api opentelemetry-sdk |
| 75 | +``` |
| 76 | + |
| 77 | +```py |
| 78 | +import logging |
| 79 | + |
| 80 | +from fastapi import FastAPI |
| 81 | + |
| 82 | +from opentelemetry import trace |
| 83 | + |
| 84 | +app = FastAPI() |
| 85 | + |
| 86 | +from time import perf_counter, sleep |
| 87 | + |
| 88 | +# ここがエンドポイント本体! |
| 89 | +@app.get("/") |
| 90 | +async def read_root(): |
| 91 | + sleep(0.1) |
| 92 | + # トレースを手動で設定 |
| 93 | + with trace.get_tracer_provider().get_tracer("sleep").start_as_current_span(__name__) as span: |
| 94 | + sleep(0.2) |
| 95 | + logging.info("read_root") |
| 96 | + logging.warning("I am hungry") |
| 97 | + sleep(0.1) |
| 98 | + return {"message": "Hello, world!"} |
| 99 | +``` |
| 100 | + |
| 101 | +今回はuvを使っていますが、uvの場合はちょっと問題があって[回避の手順が別のページ](https://opentelemetry.io/docs/zero-code/python/troubleshooting/#bootstrap-using-uv)にあります。その手順の通りに行います。`uv pip install`は`uv add`とは異なり`pyproject.toml`にパッケージは追加しません。opentelemetry-bootstrapというコマンドが[有名どころのPythonライブラリを検知して、それに対応した計装ライブラリをピックアップ](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap_gen.py)します。なかなか力技。 |
| 102 | + |
| 103 | +```sh |
| 104 | +uv pip install opentelemetry-distro opentelemetry-exporter-otlp |
| 105 | +uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement - |
| 106 | +``` |
| 107 | + |
| 108 | +これは`uv pip install`で入れているので`uv pip compile pyproject.toml`には出てきません。`uv pip freeze > requirements.txt`で`requirements.txt`を作る必要があります。 |
| 109 | + |
| 110 | +以下のコマンドで起動して、 http://localhost:8000/ で起動してログを送ります。[設定](https://opentelemetry.io/docs/zero-code/python/configuration/)は環境変数と`opentelemetry-instrument`コマンドラッパーの`--service_name`といった引数で渡す方法が選べますが、真設定は環境変数にしといた方がDockerとかにするときに便利かと思って環境変数にしています。 |
| 111 | + |
| 112 | +デフォルトのOTLPのプロトコルはgrpcですが、この場合はhttpsになってしまい証明書エラーが出てしまいます。今回はローカルなので証明書はいらないhttp/protobufもしくはhttp/jsonにします。 |
| 113 | + |
| 114 | +```sh |
| 115 | +export OTEL_SERVICE_NAME=hyperdx-demo |
| 116 | +export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf |
| 117 | +export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # 省略可能 |
| 118 | +export OTEL_PYTHON_LOG_CORRELATION=true |
| 119 | +export OTEL_PYTHON_LOG_LEVEL=info |
| 120 | +export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true |
| 121 | + |
| 122 | +$ uv run opentelemetry-instrument fastapi run --port 8000 |
| 123 | +``` |
| 124 | + |
| 125 | +結構はまったのですが、`fastapi dev`の開発モードだとログとかは出てこないですね。ちょっと不便。 |
| 126 | + |
| 127 | +# UIの設定 |
| 128 | + |
| 129 | +ローカルモードだとユーザー設定などはありませんので、いきなりコネクション選択が表示されます。オールインワンのイメージだとパスワード設定などがあります。このコネクションは緑のCreateを押せばOKです。 |
| 130 | + |
| 131 | +<img src="/images/20250618a/スクリーンショット_2025-06-13_19.13.05.png" alt="スクリーンショット_2025-06-13_19.13.05.png" width="1200" height="685" loading="lazy"> |
| 132 | + |
| 133 | +引き続きデータソース入力が表示されます。最初は二進も三進もわからなかったのですが、[こちら](https://clickhouse.com/docs/use-cases/observability/clickstack/config#datasource-settings)の情報を見れば少しは歯が立ちます。 |
| 134 | + |
| 135 | +<img src="/images/20250618a/スクリーンショット_2025-06-13_19.16.16.png" alt="スクリーンショット_2025-06-13_19.16.16.png" width="1200" height="685" loading="lazy"> |
| 136 | + |
| 137 | +以下の2つのソースを設定しました。名前、ソースタイプ、テーブル以外はデフォルトのままです。 |
| 138 | + |
| 139 | +* Name: Logs |
| 140 | + * Data Source Type: Logs |
| 141 | + * Table: ``otel_logs`` |
| 142 | +* Name: Traces |
| 143 | + * Data Source Type: Trace |
| 144 | + * Table: ``otel_traces`` |
| 145 | + |
| 146 | +# ログを見てみる |
| 147 | + |
| 148 | +左上のメニューでSearchを選び、データソースを選択すると出力したログ一覧が見れます。クリックすると時間や出力したサービスなど詳細な情報が見れます。いちいちデータソース選択とか面倒と思われるかもしれませんが、プロダクションで超大規模サービスを想定してでしょうね。同じ種類のデータでも日ごとにパーティションを切って別テーブルに、とかそういうのを想定しているのかと思います。 |
| 149 | + |
| 150 | +<img src="/images/20250618a/log.png" alt="log.png" width="1200" height="522" loading="lazy"> |
| 151 | + |
| 152 | +トレースは、それぞれのログをクリックしたあとに、トレースのタグを選択します。右側でトレースのデータソースを選択すると、いつものトレースが見られます。ログのデータソース設定のオプショナル中くれている設定に関連するトレースデータソースを設定できるので、そこを設定しておくとクリックは不要になります。動作は軽快です。 |
| 153 | + |
| 154 | +<img src="/images/20250618a/trace.png" alt="trace.png" width="1200" height="629" loading="lazy"> |
| 155 | + |
| 156 | +# まとめ |
| 157 | + |
| 158 | +ローカルでログやトレースが見れるHyperDXを試してみました。メトリクスも本当は見られたりするのですがダッシュボード設定が難しくまた今度にしようかと。あと、ウェブの操作画面を記録するセッション機能とやらもあるのですが、機能とかが多くてちょっとこちらも時間を設けてゆっくり調べてみようと思います。 |
| 159 | + |
| 160 | +OpenTelemetryでデータ投入できるので、本番環境のクラウドサービスのログ基盤とかにもスムーズに遷移できる気がします。 |
| 161 | + |
| 162 | +設定がyamlかなにかで軽く共有できれば開発用Dockerとかで気軽に立ち上げてみんなで見るとかやりたいところですが、ちょっとそこはローカル専用にするにはちょっと不便。 |
0 commit comments