主流のエンタープライズフルリンク監視システム - OpenTelemetry (2)

ここに画像の説明を挿入します

4. デプロイ(Python)

それでは、デモ プログラムを OTel に段階的に接続してみましょう。この記事では、Python デモのデプロイメントの例を取り上げます。

準備(1/5)

最初のステップは、環境をセットアップしてパッケージをインストールすることです。著者が centos7 で Python 3.6.8 をインストールした後、pip を使用して Otel に必要なパッケージをインストールしました。

pip3 install flask
pip3 install opentelemetry-distro
cd /opt/
mkdir otel-demo
cd otel-demo

opentelemetry-distro には、後で使用する API、SDK、opentelemetry-bootstrap、および opentelemetry-instrument パッケージがまとめられています。

HTTPサーバーの作成(2/5)

[root@node-138 otel-demo]# cat app.py
#!/usr/bin/python env

from flask import Flask,request

app=Flask(__name__)

@app.route("/greeting")
def greeting():
    user = request.args.get("user", "DaoCloud")
    return "hello, Cloud Native! This is %s."%user

ここでは、まず自動インストルメンテーションを使用して、OTel をこの小さなフラスコ アプリケーションに接続します。

自動計装(3/5)

この方法は面倒な操作を代替し、基本的な観測データを自動生成するもので、ここでは最も簡単な方法を使用します。

opentelemetry-bootstrap -a install

このコマンドは、インストールされているライブラリを検出し、開発者が「プラグイン」するために必要な関連パッケージを自動的にインストールします。

[root@node-138 otel-demo]# opentelemetry-bootstrap
opentelemetry-instrumentation-aws-lambda==0.33b0
opentelemetry-instrumentation-dbapi==0.33b0
opentelemetry-instrumentation-logging==0.33b0
opentelemetry-instrumentation-sqlite3==0.33b0
opentelemetry-instrumentation-urllib==0.33b0
opentelemetry-instrumentation-wsgi==0.33b0
opentelemetry-instrumentation-flask==0.33b0
opentelemetry-instrumentation-jinja2==0.33b0

opentelemetry-instrument のヘルプには多くのオプションが表示されます。これらのオプションは、OTel で設定できる環境変数に対応しており、コマンド ラインに入力された変数の優先順位は、デフォルトで設定されている変数よりも高くなります。

[root@node-138 ~]# opentelemetry-instrument -h
usage: opentelemetry-instrument [-h]
                                [--attribute_count_limit ATTRIBUTE_COUNT_LIMIT]
                                [--attribute_value_length_limit ATTRIBUTE_VALUE_LENGTH_LIMIT]
...
                                command ...

...
  --exporter_otlp_traces_certificate EXPORTER_OTLP_TRACES_CERTIFICATE
  --exporter_otlp_traces_compression EXPORTER_OTLP_TRACES_COMPRESSION
  --exporter_otlp_traces_endpoint EXPORTER_OTLP_TRACES_ENDPOINT
...
  --traces_exporter TRACES_EXPORTER
  --version             print version information

...

この時点で、アプリケーションは実際に OTel へのアクセスを完了したので、サービスを開始してその効果を確認してみましょう。

opentelemetry-instrument --traces_exporter console --metrics_exporter console flask run

起動コマンドの実行後、別のウィンドウを開いて HTTP サーバーにリクエストを送信し、最終的な効果を確認します。

[root@node-138 ~]# curl 127.0.0.1:5000/greeting
hello, Cloud Native! This is DaoCloud.

メインウィンドウ

[root@node-138 otel-demo]# opentelemetry-instrument --traces_exporter console --metrics_exporter console flask run
You are using Python 3.6. This version does not support timestamps with nanosecond precision and the OpenTelemetry SDK will use millisecond precision instead. Please refer to PEP 564 for more information. Please upgrade to Python 3.7 or newer to use nanosecond precision.
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [30/Aug/2023 08:44:57] "GET /greeting HTTP/1.1" 200 -
{
    
    
    "name": "/greeting",
    "context": {
    
    
        "trace_id": "0x72c633526437624bfb78df6f5e1210c3",
        "span_id": "0x2b65163734329c43",
        "trace_state": "[]"
    },
    "kind": "SpanKind.SERVER",
    "parent_id": null,
    "start_time": "2023-08-30T00:44:57.362599Z",
    "end_time": "2023-08-30T00:44:57.364329Z",
    "status": {
    
    
        "status_code": "UNSET"
    },
    "attributes": {
    
    
        "http.method": "GET",
        "http.server_name": "127.0.0.1",
        "http.scheme": "http",
        "net.host.port": 5000,
        "http.host": "127.0.0.1:5000",
        "http.target": "/greeting",
        "net.peer.ip": "127.0.0.1",
        "http.user_agent": "curl/7.29.0",
        "net.peer.port": 47178,
        "http.flavor": "1.1",
        "http.route": "/greeting",
        "http.status_code": 200
    },
    "events": [],
    "links": [],
    "resource": {
    
    
        "attributes": {
    
    
            "telemetry.sdk.language": "python",
            "telemetry.sdk.name": "opentelemetry",
            "telemetry.sdk.version": "1.12.0",
            "telemetry.auto.version": "0.33b0",
            "service.name": "unknown_service"
        },
        "schema_url": ""
    }
}
{
    
    "resource_metrics": [{
    
    "resource": {
    
    "attributes": {
    
    "telemetry.sdk.language": "python", "telemetry.sdk.name": "opentelemetry", "telemetry.sdk.version": "1.12.0", "telemetry.auto.version": "0.33b0", "service.name": "unknown_service"}, "schema_url": ""}, "scope_metrics": [{
    
    "scope": {
    
    "name": "opentelemetry.instrumentation.flask", "version": "0.33b0", "schema_url": ""}, "metrics": [{
    
    "name": "http.server.active_requests", "description": "measures the number of concurrent HTTP requests that are currently in-flight", "unit": "requests", "data": {
    
    "data_points": [{
    
    "attributes": {
    
    "http.method": "GET", "http.host": "127.0.0.1:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1"}, "start_time_unix_nano": 1693356297362655744, "time_unix_nano": 1693356352010139136, "value": 0}], "aggregation_temporality": 2, "is_monotonic": false}}, {
    
    "name": "http.server.duration", "description": "measures the duration of the inbound HTTP request", "unit": "ms", "data": {
    
    "data_points": [{
    
    "attributes": {
    
    "http.method": "GET", "http.host": "127.0.0.1:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1", "net.host.port": 5000, "http.status_code": 200}, "start_time_unix_nano": 1693356297364467968, "time_unix_nano": 1693356352010139136, "count": 1, "sum": 2, "bucket_counts": [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], "explicit_bounds": [0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0], "min": 2, "max": 2}], "aggregation_temporality": 2}}], "schema_url": ""}], "schema_url": ""}]}

上記はそれぞれリクエストのトレース情報とメトリクス情報であり、これらの情報はユーザーにとって自動インストルメンテーションの「組み込み」観測項目です。たとえば、/greeting ルーティング リクエストのライフ サイクル データや、http.server.active_requests や http.server.duration などのインジケータ データを追跡します。しかし、これらのデータは、運用環境でアプリケーションの可観測性を実際に構築するには十分とは言えません

観測項目追加(手動)(4/5)

自動統合はユーザーにいくつかの基本的な観察データを提供しますが、これらのデータは主に、帯域内または帯域外の HTTP リクエストなどのシステムの「エッジ」から取得され、アプリケーションの内部状況をユーザーに示すことはできません。以下は自動計測に基づいています。次に、いくつかの観察機能を手動で追加します。

  • 痕跡
[root@node-138 otel-demo]# cat app.py
#!/usr/bin/python env

from flask import Flask,request
from opentelemetry import trace

app=Flask(__name__)
tracer=trace.get_tracer(__name__)

@app.route("/greeting")
def greeting():
  with tracer.start_as_current_span("greeting") as greeting_span:
    user = request.args.get("user", "DaoCloud")
    greeting_words = "hello, Cloud Native! This is %s."%user
    greeting_span.set_attribute("greeting.content",greeting_words)
    greeting_span.set_attribute("greeting.person",user)
    return greeting_words

トレーサを初期化し、トレース データ (つまり、自動統合によって作成されたスパン データのサブスパンであるスパン) を作成します。

サービスを再度実行してリクエストします。

[root@node-138 otel-demo]# opentelemetry-instrument --traces_exporter console -- metrics_exporter console flask run                                                       
You are using Python 3.6. This version does not support timestamps with nanoseco                                                          nd precision and the OpenTelemetry SDK will use millisecond precision instead. P                                                          lease refer to PEP 564 for more information. Please upgrade to Python 3.7 or new                                                          er to use nanosecond precision.
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployme                                                          nt.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [30/Aug/2023 08:57:40] "GET /greeting HTTP/1.1" 200 -
{
    
    
    "name": "greeting",
    "context": {
    
    
        "trace_id": "0x5e489ef3e6d5ba767676bb23ff31842f",
        "span_id": "0xb2fbc81eb8ae804d",								
        "trace_state": "[]"
    },
    "kind": "SpanKind.INTERNAL",
    "parent_id": "0x7553887517e8ff6f",									#parent_id
    "start_time": "2023-08-30T00:57:40.131915Z",
    "end_time": "2023-08-30T00:57:40.132000Z",
    "status": {
    
    
        "status_code": "UNSET"
    },
    "attributes": {
    
    
        "greeting.content": "hello, Cloud Native! This is DaoCloud.",#新增属性
        "greeting.person": "DaoCloud"															#新增属性
    },
    "events": [],
    "links": [],
    "resource": {
    
    
        "attributes": {
    
    
            "telemetry.sdk.language": "python",
            "telemetry.sdk.name": "opentelemetry",
            "telemetry.sdk.version": "1.12.0",
            "telemetry.auto.version": "0.33b0",
            "service.name": "unknown_service"
        },
        "schema_url": ""
    }
}
{
    
    
    "name": "/greeting",
    "context": {
    
    
        "trace_id": "0x5e489ef3e6d5ba767676bb23ff31842f",
        "span_id": "0x7553887517e8ff6f",								#span_id
        "trace_state": "[]"
    },
    "kind": "SpanKind.SERVER",
    "parent_id": null,
    "start_time": "2023-08-30T00:57:40.130697Z",
    "end_time": "2023-08-30T00:57:40.132480Z",
    "status": {
    
    
        "status_code": "UNSET"
    },
    "attributes": {
    
    
        "http.method": "GET",
        "http.server_name": "127.0.0.1",
        "http.scheme": "http",
        "net.host.port": 5000,
        "http.host": "127.0.0.1:5000",
        "http.target": "/greeting",
        "net.peer.ip": "127.0.0.1",
        "http.user_agent": "curl/7.29.0",
        "net.peer.port": 47186,
        "http.flavor": "1.1",
        "http.route": "/greeting",
        "http.status_code": 200
    },
    "events": [],
    "links": [],
    "resource": {
    
    
        "attributes": {
    
    
            "telemetry.sdk.language": "python",
            "telemetry.sdk.name": "opentelemetry",
            "telemetry.sdk.version": "1.12.0",
            "telemetry.auto.version": "0.33b0",
            "service.name": "unknown_service"
        },
        "schema_url": ""
    }
}

手動で作成したグリーティング スパンのparent_id は、/greeting の span_id と同じであり、親子関係を示していることがわかります。

  • メトリクス
[root@node-138 otel-demo]# cat app.py
#!/usr/bin/python env

from flask import Flask,request
from opentelemetry import trace,metrics

app=Flask(__name__)
tracer=trace.get_tracer(__name__)
meter=metrics.get_meter(__name__)
greeting_counter=meter.create_counter(
    "greeting_counter",
    description="The number of greeting times of each person",
)

@app.route("/greeting")
def greeting():
  with tracer.start_as_current_span("greeting") as greeting_span:
    user = request.args.get("user", "DaoCloud")
    greeting_words = "hello, Cloud Native! This is %s."%user
    greeting_span.set_attribute("greeting.content",greeting_words)
    greeting_span.set_attribute("greeting.person",user)
    greeting_counter.add(1, {
    
    "greeting.persion": user})
    return greeting_words

メーターを初期化し、各ユーザー パラメーターをカウントする (呼び出し数をカウントする) カウンターを作成します。

サービスを再度実行し、今回は複数の異なるリクエストを送信します。

curl http://localhost:5000/greeting  # 1
curl http://localhost:5000/greeting	 # 2
curl http://localhost:5000/greeting	 # 3
curl http://localhost:5000/greeting?user=sulun  # 4

観測結果

[root@node-138 otel-demo]# opentelemetry-instrument --traces_exporter console --                                                          metrics_exporter console flask run
...
{
    
    "resource_metrics": [{
    
    "resource": {
    
    "attributes": {
    
    "telemetry.sdk.language": "python", "telemetry.sdk.name": "opentelemetry", "telemetry.sdk.version": "1.12.0", "telemetry.auto.version": "0.33b0", "service.name": "unknown_service"}, "schema_url": ""}, "scope_metrics": [{
    
    "scope": {
    
    "name": "opentelemetry.instrumentation.flask", "version": "0.33b0", "schema_url": ""}, "metrics": [{
    
    "name": "http.server.active_requests", "description": "measures the number of concurrent HTTP requests that are currently in-flight", "unit": "requests", "data": {
    
    "data_points": [{
    
    "attributes": {
    
    "http.method": "GET", "http.host": "127.0.0.1:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1"}, "start_time_unix_nano": 1693357979607876096, "time_unix_nano": 1693357993432316672, "value": 0}, {
    
    "attributes": {
    
    "http.method": "GET", "http.host": "localhost:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1"}, "start_time_unix_nano": 1693357979607876096, "time_unix_nano": 1693357993432316672, "value": 0}], "aggregation_temporality": 2, "is_monotonic": false}}, {
    
    "name": "http.server.duration", "description": "measures the duration of the inbound HTTP request", "unit": "ms", "data": {
    
    "data_points": [{
    
    "attributes": {
    
    "http.method": "GET", "http.host": "127.0.0.1:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1", "net.host.port": 5000, "http.status_code": 200}, "start_time_unix_nano": 1693357979609903616, "time_unix_nano": 1693357993432316672, "count": 3, "sum": 4, "bucket_counts": [0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0], "explicit_bounds": [0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0], "min": 1, "max": 2}, {
    
    "attributes": {
    
    "http.method": "GET", "http.host": "localhost:5000", "http.scheme": "http", "http.flavor": "1.1", "http.server_name": "127.0.0.1", "net.host.port": 5000, "http.status_code": 200}, "start_time_unix_nano": 1693357979609903616, "time_unix_nano": 1693357993432316672, "count": 1, "sum": 1, "bucket_counts": [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], "explicit_bounds": [0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0], "min": 1, "max": 1}], "aggregation_temporality": 2}}], "schema_url": ""}, {
    
    "scope": {
    
    "name": "app", "version": "", "schema_url": ""}, "metrics": [{
    
    "name": "greeting_counter", "description": "The number of greeting times of each person", "unit": "", "data": {
    
    "data_points": [{
    
    "attributes": {
    
    "greeting.persion": "DaoCloud"}, "start_time_unix_nano": 1693357979609319424, "time_unix_nano": 1693357993432316672, "value": 3}, {
    
    "attributes": {
    
    "greeting.persion": "sulun"}, "start_time_unix_nano": 1693357979609319424, "time_unix_nano": 1693357993432316672, "value": 1}], "aggregation_temporality": 2, "is_monotonic": true}}], "schema_url": ""}], "schema_url": ""}]}

今回は、デフォルトの呼び出しが 3 件、ユーザー パラメーターを含む呼び出しが 1 件送信され、この動作は、以前に設定されたカウンターと生成されたメトリクス データによってカウントされました。

上記の手順は、OTel を導入し、トレースとメトリクス データを手動で追加するための準備プロセスです。Logs モジュールに関しては、起動方法としてコンソールへのエクスポートが選択されているため、コンソールにログを出力することは通常のログを出力するのと同じ効果があるため、このセクションでは最初に説明しません。 OTLPの内容に基づくOTelのモジュールパフォーマンス。

OTLP プロトコル データをコレクタに送信する (5/5)

Collector の主要な機能については以前に紹介しましたが、Collector によってもたらされる利点をいくつか紹介します。

  • Collector を使用すると、複数のサービスが観測データ プールを共有できるため、Exporter を切り替えるコストが削減されます。
  • コレクターは、ホストおよびサービス間で同じトレース データを集約できます。
  • Collector は、バックエンドの前にデータを吐き出す転送ステーションを提供し、事前にデータを分析およびフィルタリングする機能を提供します。

単純な Collector のドッキングを示してみましょう。

まず、app.py ファイルのパスの下に tmp/ フォルダーを作成し、otel-collector-config.yaml ファイルを作成します。

[root@node-138 tmp]# cat otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
exporters:
  logging:
    loglevel: debug
processors:
  batch:
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging]
      processors: [batch]
    metrics:
      receivers: [otlp]
      exporters: [logging]
      processors: [batch]

次に、OTel によって提供される基本的なコレクタ イメージをプルし、コレクタを起動します。

docker run -p 4317:4317 -v /opt/otel-demo/tmp/otel-collector-config.yaml:/etc/otel-collector-config.yaml  otel/opentelemetry-collector:latest  --config=/etc/otel-collector-config.yaml

コマンドは理解するのが難しくないので、構成ファイルをマウントした後、コレクタのデフォルト ポート 4317 をリッスンします。

docker run -p 4317:4317 -v /opt/otel-demo/tmp/otel-collector-config.yaml:/etc/otel-collector-config.yaml  otel/opentelemetry-collector:latest  --config=/etc/otel-collector-config.yaml
2023-08-30T01:48:04.874Z        info    service/telemetry.go:84 Setting up own telemetry...
...
2023-08-30T01:48:04.878Z        info    [email protected]/otlp.go:83 Starting GRPC server    {
    
    "kind": "receiver", "name": "otlp", "data_type": "metrics", "endpoint": "0.0.0.0:4317"}

次に、以前に自動および手動でキャプチャされた観測データを、OTLP プロトコルを通じて標準形式に変換し、コレクタに送信する必要があります。

この手順には OTLP プロトコルのエクスポーターが必要です。OTel コミュニティはユーザー用のインストール パッケージも用意しています。

pip3 install opentelemetry-exporter-otlp

ここでアプリケーションを再度起動します。

opentelemetry-instrument flask run

--traces_exporter consoleここでは自動インストルメンテーションの機能も使用されているため、このようなパラメーターを指定する必要はなくなりました。インストルメント エージェントは、新しくインストールされたパッケージを自動的に検出し、ユーザーの OTLP/gRPC プロトコルのエクスポーターに切り替えます次回の起動、デフォルトのターゲットのポートも 4317 です。

サービスが再度リクエストされると、Collector プロセスは OTLP 標準データを受信しますが、元の Flask プロセスはテレメトリ データを表示しなくなります。

  • 痕跡
Resource SchemaURL:
Resource attributes:
     -> telemetry.sdk.language: Str(python)
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.version: Str(1.12.0)
     -> telemetry.auto.version: Str(0.33b0)
     -> service.name: Str(unknown_service)
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope app
Span #0
    Trace ID       : 9d67e3b1f2e6f40a0925fd7951bc0942
    Parent ID      : f73a56bacf0c1a05
    ID             : 5e764b6a40cab9c3
    Name           : greeting
    Kind           : Internal
    Start time     : 2023-08-30 01:49:22.416530944 +0000 UTC
    End time       : 2023-08-30 01:49:22.416732416 +0000 UTC
    Status code    : Unset
    Status message :
Attributes:
     -> greeting.content: Str(hello, Cloud Native! This is DaoCloud.)
     -> greeting.person: Str(DaoCloud)
ScopeSpans #1
ScopeSpans SchemaURL:
InstrumentationScope opentelemetry.instrumentation.flask 0.33b0
Span #0
    Trace ID       : 9d67e3b1f2e6f40a0925fd7951bc0942
    Parent ID      :
    ID             : f73a56bacf0c1a05
    Name           : /greeting
    Kind           : Server
    Start time     : 2023-08-30 01:49:22.414059776 +0000 UTC
    End time       : 2023-08-30 01:49:22.417396224 +0000 UTC
    Status code    : Unset
    Status message :
Attributes:
     -> http.method: Str(GET)
     -> http.server_name: Str(127.0.0.1)
     -> http.scheme: Str(http)
     -> net.host.port: Int(5000)
     -> http.host: Str(127.0.0.1:5000)
     -> http.target: Str(/greeting)
     -> net.peer.ip: Str(127.0.0.1)
     -> http.user_agent: Str(curl/7.29.0)
     -> net.peer.port: Int(47980)
     -> http.flavor: Str(1.1)
     -> http.route: Str(/greeting)
     -> http.status_code: Int(200)
        {
    
    "kind": "exporter", "data_type": "traces", "name": "logging"}
2023-08-30T01:49:34.750Z        info    MetricsExporter {
    
    "kind": "exporter", "data_type": "metrics", "name": "logging", "resource metrics": 1, "metrics": 3, "data points": 3}
2023-08-30T01:49:34.751Z        info    ResourceMetrics #0
  • メトリクス
Resource SchemaURL:
Resource attributes:
     -> telemetry.sdk.language: Str(python)
     -> telemetry.sdk.name: Str(opentelemetry)
     -> telemetry.sdk.version: Str(1.12.0)
     -> telemetry.auto.version: Str(0.33b0)
     -> service.name: Str(unknown_service)
ScopeMetrics #0
ScopeMetrics SchemaURL:
InstrumentationScope opentelemetry.instrumentation.flask 0.33b0
Metric #0
Descriptor:
     -> Name: http.server.active_requests
     -> Description: measures the number of concurrent HTTP requests that are currently in-flight
     -> Unit: requests
     -> DataType: Sum
     -> IsMonotonic: false
     -> AggregationTemporality: Cumulative
NumberDataPoints #0
Data point attributes:
     -> http.method: Str(GET)
     -> http.host: Str(127.0.0.1:5000)
     -> http.scheme: Str(http)
     -> http.flavor: Str(1.1)
     -> http.server_name: Str(127.0.0.1)
StartTimestamp: 2023-08-30 01:49:22.414117888 +0000 UTC
Timestamp: 2023-08-30 01:49:34.58335872 +0000 UTC
Value: 0
Metric #1
Descriptor:
     -> Name: http.server.duration
     -> Description: measures the duration of the inbound HTTP request
     -> Unit: ms
     -> DataType: Histogram
     -> AggregationTemporality: Cumulative
HistogramDataPoints #0
Data point attributes:
     -> http.method: Str(GET)
     -> http.host: Str(127.0.0.1:5000)
     -> http.scheme: Str(http)
     -> http.flavor: Str(1.1)
     -> http.server_name: Str(127.0.0.1)
     -> net.host.port: Int(5000)
     -> http.status_code: Int(200)
StartTimestamp: 2023-08-30 01:49:22.417513728 +0000 UTC
Timestamp: 2023-08-30 01:49:34.58335872 +0000 UTC
Count: 1
Sum: 3.000000
Min: 3.000000
Max: 3.000000
ExplicitBounds #0: 0.000000
ExplicitBounds #1: 5.000000
ExplicitBounds #2: 10.000000
ExplicitBounds #3: 25.000000
ExplicitBounds #4: 50.000000
ExplicitBounds #5: 75.000000
ExplicitBounds #6: 100.000000
ExplicitBounds #7: 250.000000
ExplicitBounds #8: 500.000000
ExplicitBounds #9: 1000.000000
Buckets #0, Count: 0
Buckets #1, Count: 1
Buckets #2, Count: 0
Buckets #3, Count: 0
Buckets #4, Count: 0
Buckets #5, Count: 0
Buckets #6, Count: 0
Buckets #7, Count: 0
Buckets #8, Count: 0
Buckets #9, Count: 0
Buckets #10, Count: 0
ScopeMetrics #1
ScopeMetrics SchemaURL:
InstrumentationScope app
Metric #0
Descriptor:
     -> Name: greeting_counter
     -> Description: The number of greeting times of each person
     -> Unit:
     -> DataType: Sum
     -> IsMonotonic: true
     -> AggregationTemporality: Cumulative
NumberDataPoints #0
Data point attributes:
     -> greeting.persion: Str(DaoCloud)
StartTimestamp: 2023-08-30 01:49:22.416660736 +0000 UTC
Timestamp: 2023-08-30 01:49:34.58335872 +0000 UTC
Value: 1
        {
    
    "kind": "exporter", "data_type": "metrics", "name": "logging"}
  • ログ
    SDK とログの関連コンポーネントはまだ開発中であるため、アプリに接続してコレクターに接続する現在のプロセスは、他の 2 種類の観測データほど便利ではありません。

otel-collector-config.yaml ファイルを編集します。上記の手順では、 OTLP プロトコルが
ここに画像の説明を挿入します
順番に作成され(この手順は、コレクタがアプリケーションによって出力されたログを受信するために非常に重要です)、最後に log_emitter で作成されたインスタンスがロギング ハンドラに追加されます (Flask では次の点に注意してください)。 application の場合は、Stream タイプのハンドラーをロギング ハンドラーに追加する必要があります。そうしないと、werkzeug の情報出力に影響します)。log_emitter_providerexporterlog_emitterLoggingHandler

Collector コンテナとアプリケーションを再実行します。

docker run -p 4317:4317 -v /opt/otel-demo/tmp/otel-collector-config.yaml:/etc/otel-collector-config.yaml  otel/opentelemetry-collector:latest  --config=/etc/otel-collector-config.yaml

opentelemetry-instrument flask run

/greeting インターフェイスにリクエストして、コレクタ内の結果を確認します。
ここに画像の説明を挿入します
コレクタは INFO 以上のレベルのログ メッセージのみを受信することがわかりますが、これは otel-collector-config.yaml ファイルで loglevel=INFO が事前に設定されていたためです。
ここに画像の説明を挿入します
Flask と werkzeug を例に挙げると、他のライブラリ、フレームワーク、またはシステム ログも Collector に送信されます。
ここに画像の説明を挿入します
Span コンテキスト内で記録されたログは、OTLP プロトコルで処理された後、Trace ID と Span ID で処理され、すべての観測データを相互に接続することができます。

5. OpenTelemetry + Prometheus + Grafana をデプロイする

今回は、迅速なデプロイのために docker-compose を使用します。

理論: OpenTelemetry-Collector を通じてトレースおよびメトリクス データを収集し、データを自動的に観測可能な形式に変換して prometheus に提供し、最終的に grafana によって表示します。

設定ファイルの変更 (1/5)

otel-collector-config.yaml

[root@node-138 tmp]# cat otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
      http:
        cors:
          allowed_origins:
            - http://*
            - https://*
exporters:
  logging:
    loglevel: debug
  prometheus:
    endpoint: "0.0.0.0:8889"
    const_labels:
      label1: value1
processors:
  batch:
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging]
      processors: [batch]
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
      processors: [batch]
    logs:
      receivers: [otlp]
      exporters: [logging]

docker-compose.yaml

[root@node-138 tmp]# cat docker-compose.yaml
version: '3.3'

services:
    otel-collector:
        image: otel/opentelemetry-collector:0.50.0
        command: ["--config=/etc/otel-collector-config.yaml"]
        volumes:
            - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
        ports:
            - "1888:1888"   # pprof extension
            - "8888:8888"   # Prometheus metrics exposed by the collector
            - "8889:8889"   # Prometheus exporter metrics
            - "13133:13133" # health_check extension
            - "4317:4317"        # OTLP gRPC receiver
            - "4318:4318"        # OTLP http receiver
            - "55670:55679" # zpages extension
    prometheus:
        container_name: prometheus
        image: prom/prometheus:latest
        volumes:
            - ./prometheus.yaml:/etc/prometheus/prometheus.yml
        ports:
            - "9090:9090"
    grafana:
        container_name: grafana
        image: grafana/grafana
        ports:
            - "3000:3000"

プロメテウス.yaml

[root@node-138 tmp]# cat prometheus.yaml
# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

  - job_name: 'otel-collector'
    scrape_interval: 10s
    static_configs:
      - targets: ['192.168.17.138:8889']
      - targets: ['192.168.17.138:8888']

コンテナの起動(2/5)

[root@node-138 tmp]# docker-compose up -d
[root@node-138 tmp]# docker ps
CONTAINER ID   IMAGE                                 COMMAND                  CREATED       STATUS       PORTS                                                                                                                                                       NAMES
417ec6e93078   otel/opentelemetry-collector:0.50.0   "/otelcol --config=/…"   2 hours ago   Up 2 hours   0.0.0.0:1888->1888/tcp, 0.0.0.0:4317-4318->4317-4318/tcp, 0.0.0.0:8888-8889->8888-8889/tcp, 0.0.0.0:13133->13133/tcp, 55678/tcp, 0.0.0.0:55670->55679/tcp   tmp_otel-collector_1
a2a8014cb136   grafana/grafana                       "/run.sh"                2 hours ago   Up 2 hours   0.0.0.0:3000->3000/tcp                                                                                                                                      grafana
1064669ca884   prom/prometheus:latest                "/bin/prometheus --c…"   2 hours ago   Up 2 hours   0.0.0.0:9090->9090/tcp                                                                                                                                      prometheus

ビジネスサービス開始(3/5)

前のセクションの Python flask プログラムを引き続き使用します。パラメーターを指定する必要もないことに注意してください。コレクターがインジケーター データを収集します。

[root@node-138 tmp]# cat ../app.py
#!/usr/bin/python env

from flask import Flask,request
from opentelemetry import trace,metrics

app=Flask(__name__)
tracer=trace.get_tracer(__name__)
meter=metrics.get_meter(__name__)
greeting_counter=meter.create_counter(
    "greeting_counter",
    description="The number of greeting times of each person",
)

@app.route("/greeting")
def greeting():
  with tracer.start_as_current_span("greeting") as greeting_span:
    user = request.args.get("user", "DaoCloud")
    greeting_words = "hello, Cloud Native! This is %s."%user
    greeting_span.set_attribute("greeting.content",greeting_words)
    greeting_span.set_attribute("greeting.person",user)
    greeting_counter.add(1, {
    
    "greeting.persion": user})
    return greeting_words
[root@node-138 tmp]# opentelemetry-instrument flask run

アクセスサービス

curl http://localhost:5000/greeting  # 1
curl http://localhost:5000/greeting	 # 2
curl http://localhost:5000/greeting	 # 3
curl http://localhost:5000/greeting?user=sulun  # 4

データを見る プロメテウス (4/5)

prometheus の Web ページにアクセスしてhttp://192.168.17.138:9090/
ここに画像の説明を挿入しますインジケーター データを表示すると
ここに画像の説明を挿入します、カウンター情報を確認できます。

グラファナをチェックしてください (5/5)

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/u010230019/article/details/132580704