既存のRedisと並行してOpenTelemetry Collectorをコンテナとしてデプロイすることにより、Docker Composeを使用してRedisインスタンスをモニターします。
あなたが始める前に
コレクターを設定する前に、以下のものが必要です:
- DockerおよびDocker Compose(v2以降)がインストールされていること
- あなたのNew Relic
- Redisが実行中でアクセス可能であること — バージョン6.0以降を推奨(4.0以降は削減されたメトリクスセットで動作します)
- New RelicのOTLPエンドポイントへのアウトバウンドHTTPS(ポート443)
インストレーションオプションでコレクターのディストリビューションを選択します:NRDOTコレクター、OpenTelemetry Collector Contrib、またはPrometheusレシーバー。各パスのDocker Composeファイルは、Prometheusレシーバーパス用のredis_exporterを含め、必要なイメージをプルします。
インストールオプション
コレクターの設定を作成します
この設定は、コレクターにRedisメトリクスを収集してNew Relicに送信する方法を指示します。3つの主なジョブを処理します:
redisレシーバーを通じてRedisからメトリクスを収集します。データを形成します — カーディナリティを削減し、カウンターをデルタに変換し、エンティティ合成のためにタグ付けします。
処理されたメトリクスをOTLP経由でNew Relicにエクスポートする
プロジェクトディレクトリに
otel-collector-config.yamlを作成します:extensions:health_check:endpoint: "0.0.0.0:13133"receivers:redis:endpoint: "redis:6379" # Update with your Redis service name:portcollection_interval: 10smetrics:redis.maxmemory:enabled: trueredis.role:enabled: falseredis.cmd.calls:enabled: trueredis.cmd.usec:enabled: trueredis.clients.max_input_buffer:enabled: falseredis.clients.max_output_buffer:enabled: falseredis.replication.backlog_first_byte_offset:enabled: falseresource_attributes:server.address:enabled: trueserver.port:enabled: trueprocessors:memory_limiter:check_interval: 5slimit_mib: 512spike_limit_mib: 128resource_detection:detectors: [env, system]timeout: 5soverride: falsesystem:resource_attributes:host.name:enabled: truehost.id:enabled: true# Uncomment the section below to use a custom human-readable name for your# Redis entity instead of the default server.address:server.port identifier.# resource/redis:# attributes:# - key: redis.instance.id# value: "my-redis-instance"# action: upsertattributes/entity_tags:actions:- key: instrumentation.providervalue: opentelemetryaction: upsertcumulativetodelta:include:match_type: regexpmetrics:- redis\.commands\.processed- redis\.connections\.received- redis\.connections\.rejected- redis\.keys\.evicted- redis\.keys\.expired- redis\.keyspace\.hits- redis\.keyspace\.misses- redis\.net\.input- redis\.net\.output- redis\.cpu\.time- redis\.cmd\.calls- redis\.cmd\.usec- redis\.uptimefilter/cardinality:metrics:datapoint:- 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'- 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'- 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'transform/metadata_nullify:metric_statements:- context: metricstatements:- set(description, "")- set(unit, "")batch:send_batch_size: 2048send_batch_max_size: 4096timeout: 10sexporters:otlp_http:endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}headers:api-key: ${env:NEW_RELIC_LICENSE_KEY}compression: gzipservice:extensions: [health_check]pipelines:metrics/redis:receivers: [redis]# If using resource/redis for custom name, add it to the processors list:# processors: [memory_limiter, resource_detection, resource/redis, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]exporters: [otlp_http]この設定で行うこと
パイプラインの各コンポーネントには特定の役割があります:
コンポーネント 説明 health_checkコレクターが実行されていることを確認できるように、 0.0.0.0:13133でヘルスエンドポイントを公開します。redisレシーバー10秒ごとにRedisエンドポイントに接続し、Redisの INFOコマンドからメトリクスを読み取ります。server.addressとserver.portはエンティティのIDになります。memory_limiterコンテナを保護するために、コレクターのメモリ使用量に上限を設定します(ソフトリミット512 MiB、スパイク128 MiB)。 resource_detectionホストを検出し、 host.nameとhost.idを追加して、Redisメトリクスを基盤となるホストエンティティにリンクします。attributes/entity_tagsクエリをOpenTelemetryパスにスコープできるように、すべてのメトリクスに instrumentation.provider: opentelemetryをスタンプします。cumulativetodeltaNew Relicがレートを正しくチャート化できるように、Redisの累積カウンター — コマンド、キースペースヒット、エビクションなど — をデルタ値に変換します。 filter/cardinality取り込みコストを制御するために、高いカーディナリティのデータポイント( userとsys以外のCPUステータス、および一般的ではないコマンドのコマンドごとのメトリクス)をドロップします。transform/metadata_nullifyペイロードのサイズを縮小するために、メトリクスの説明と単位をクリアします。 batchネットワークのオーバーヘッドを削減するために、エクスポートする前にデータポイントをグループ化し(バッチあたり2,048、最大4,096)、少なくとも10秒ごとにフラッシュします。 otlp_http処理されたメトリクスを、ライセンスキーで認証し、gzip圧縮を使用してOTLP経由でNew Relicにエクスポートします。 ヒント
ユーザーフレンドリーなエンティティ名をご希望ですか?デフォルトでは、Redisエンティティは
server.address:server.portの組み合わせを使用して名前が付けられます。代わりに人間が読めるカスタム名を使用するには、上記の設定のresource/redisセクションのコメントを解除し、redis.instance.idの値に希望する名前を設定して、プロセッサパイプラインにresource/redisを追加します。
オプション:認証を構成する
デフォルトでは、コレクターは資格情報なしでRedisに接続します。Redisインスタンスに認証が必要な場合は、一致する資格情報をredisレシーバーに追加します。設定に一致するオプションを選択してください:
オプション:Redisログの収集
メトリクスに加えて、コレクターはRedisのログファイルをNew Relicに転送できるため、ログイベント — 再起動、永続化イベント、またはエラー — を同じエンティティ上のメトリクスのスパイクと関連付けることができます。
重要
デフォルトでは、DockerのRedisはstdoutにログを出力します(ファイルには出力しません)。filelogレシーバーでログを収集するには、ログファイルに書き込むようにRedisを構成し、Redisコンテナとコレクターコンテナ間でDockerボリュームを介して共有する必要があります。
docker-compose.ymlのRedisサービスに以下を追加します:
redis: image: redis:7 command: > sh -c "touch /data/redis.log && chmod 644 /data/redis.log && redis-server --logfile /data/redis.log" volumes: - redis-logs:/dataそして、共有ボリュームをコレクターサービスに追加します:
otel-collector: volumes: - redis-logs:/var/log/redis:ro次に、docker-compose.ymlの一番下に追加します:
volumes: redis-logs:filelogレシーバーをotel-collector-config.yamlに追加します:
receivers: # ... existing redis receiver ... file_log/redis: include: - /var/log/redis/redis.log start_at: end operators: - type: regex_parser regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) ' on_error: send resource: db.system: redisファイルからのログ行には、それ自体にRedis接続コンテキストがありません—New RelicがログをRedisエンティティに関連付けるように、ID属性を明示的にアタッチする必要があります。RedisエンティティのIDに一致するハードコードされた値を使用して、resource/redis_logsプロセッサを追加します:
processors: # ... existing processors ... resource/redis_logs: attributes: - key: server.address value: "redis" # Must match your redis receiver endpoint host action: upsert - key: server.port value: 6379 # Must match your redis receiver endpoint port action: upsert - key: instrumentation.provider value: opentelemetry action: upsertヒント
カスタムインスタンスIDを使用していますか?カスタムエンティティの命名のためにresource/redisプロセッサーを有効にした場合は、上記のserver.addressとserver.portをredis.instance.idに置き換えます:
resource/redis_logs: attributes: - key: redis.instance.id value: "my-redis-instance" # Must match the value in resource/redis action: upsert - key: instrumentation.provider value: opentelemetry action: upsertserviceセクションに別のログパイプラインを追加します:
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] logs/redis: receivers: [file_log/redis] processors: [memory_limiter, resource/redis_logs, batch] exporters: [otlp_http]重要
コレクターコンテナは、Redisログファイルへの読み取りアクセス権を持っている必要があります。ログディレクトリをコンテナにマウントするときは、コレクタープロセスがファイルを読み取れることを確認してください。ホストで次を実行します:
$sudo chmod 755 /var/log/redis$sudo chmod 644 /var/log/redis/redis.logオプション:ホストメトリクスの収集
Redisのパフォーマンスは、多くの場合、ホストのリソースの圧迫 — CPUの飽和、メモリの枯渇、またはディスクI/Oの競合に連動します。New Relicで両者を関連付けることができるように、Redisとともにシステムメトリクスを収集するhostmetricsレシーバーを追加します。コレクターがコンテナのファイルシステムではなくホストのファイルシステムを読み取るようにするため、Dockerコンテナ内で実行する場合はroot_path: /hostfs設定が必須です:
receivers: # ... existing receivers ... host_metrics: collection_interval: 10s root_path: /hostfs scrapers: cpu: metrics: system.cpu.utilization: {enabled: true} system.cpu.time: {enabled: true} load: metrics: system.cpu.load_average.1m: {enabled: true} system.cpu.load_average.5m: {enabled: true} system.cpu.load_average.15m: {enabled: true} memory: metrics: system.memory.usage: {enabled: true} system.memory.utilization: {enabled: true} disk: metrics: system.disk.io: {enabled: true} system.disk.operations: {enabled: true} filesystem: metrics: system.filesystem.usage: {enabled: true} system.filesystem.utilization: {enabled: true} network: metrics: system.network.io: {enabled: true} system.network.packets: {enabled: true}ホストメトリクス用に別のmetrics/hostパイプラインを追加します(Redisパイプラインにhost_metricsを追加しないでください):
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] metrics/host: receivers: [host_metrics] processors: [memory_limiter, resource_detection, attributes/entity_tags, batch] exporters: [otlp_http]オプション:カスタムメタデータの追加
カスタムリソース属性によって、すべてのRedisメトリクスにコンテキスト — 環境、チーム、またはティア — のタグが付けられるため、New Relicでデータをフィルタリングおよびグループ化できます。必要なタグを含むresource/customプロセッサを追加します:
processors: # ... existing processors ... resource/custom: attributes: - key: environment value: "production" action: upsert - key: team value: "platform" action: upsertパイプラインにプロセッサを含めます:
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, resource/custom, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http]オプション:Redis Clusterの監視を有効にする
現在、Redis Clusterの監視にはPrometheusレシーバーのアプローチ(redis_exporterを使用)が必要です。NRDOT CollectorのネイティブRedisレシーバーは、クラスタメトリクスに必要なCLUSTER INFOコマンドをまだサポートしていません。クラスタ監視のセットアップには、Prometheusレシーバータブを使用します。
Docker Composeファイルの作成
既存のRedisと並行してコレクターを実行するためのdocker-compose.ymlを作成します。同じディレクトリにある.envファイルは、Docker Composeによって自動的に読み込まれます:
services: otel-collector: image: newrelic/nrdot-collector:latest env_file: .env volumes: - ./otel-collector-config.yaml:/etc/otel/config.yaml:ro - /etc/machine-id:/etc/machine-id:ro # Uncomment if collecting Redis logs (requires shared volume — see logs step above): # - redis-logs:/var/log/redis:ro # Uncomment if collecting host metrics: # - /:/hostfs:ro # Uncomment if using TLS: # - ./certs:/etc/ssl/redis:ro environment: - NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY} - OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT} # Uncomment if collecting host metrics: # - HOST_PROC=/hostfs/proc # - HOST_SYS=/hostfs/sys # - HOST_ETC=/hostfs/etc # Uncomment if using Redis authentication: # - REDIS_PASSWORD=${REDIS_PASSWORD} # - REDIS_USERNAME=${REDIS_USERNAME} command: ["--config=/etc/otel/config.yaml"] ports: - "13133:13133" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:13133"] interval: 10s timeout: 5s retries: 3
# Uncomment if collecting Redis logs:# volumes:# redis-logs:ヒント
前の手順でオプション機能(ログ、ホストメトリクス、TLS、または認証)を有効にした場合は、上記のDocker Composeファイル内の対応する行のコメントを解除してください。
環境ファイルを作成します
Docker Composeは、docker-compose.ymlと同じディレクトリにある.envファイルからデプロイメント固有の値を読み取ります。これにより、ライセンスキーをcomposeファイルから除外できます。.envファイルを作成します:
$NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY$OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT$# Set the New Relic OTLP endpoint for your region.$# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlpプレースホルダーを独自の値に置き換えます:
| 変数 | 必須 | 説明 |
|---|---|---|
NEW_RELIC_LICENSE_KEY | はい | New Relic取り込みライセンスキー。 |
OTEL_EXPORTER_OTLP_ENDPOINT | はい | ご利用のリージョンのNew Relic OTLPエンドポイント。詳細については、New Relic OTLPエンドポイントを参照してください。 |
開始・検証する
バックグラウンドでコレクターを開始します:
$docker compose up -ddocker compose psでコンテナが実行されていることを確認します — コレクターはrunningステータスを表示するはずです。終了した場合は、docker compose logs otel-collectorでログを確認します — 最も一般的な原因は、YAMLのインデントエラーと到達不可能なRedisエンドポイントです。
次に、メトリクスがNew Relicに到達していることを確認します。起動後約1分待ってから、クエリビルダーで次のクエリを実行します:
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes agoゼロ以外のカウントにより、Redisメトリクスが流れていることが確認できます。0が返される場合は、Redisのトラブルシューティング(OpenTelemetry)を参照してください。
コレクターの設定を作成します
この設定は、コレクターにRedisメトリクスを収集してNew Relicに送信する方法を指示します。3つの主なジョブを処理します:
redisレシーバーを通じてRedisからメトリクスを収集します。データを形成します — カーディナリティを削減し、カウンターをデルタに変換し、エンティティ合成のためにタグ付けします。
処理されたメトリクスをOTLP経由でNew Relicにエクスポートする
プロジェクトディレクトリに
otel-collector-config.yamlを作成します:extensions:health_check:endpoint: "0.0.0.0:13133"receivers:redis:endpoint: "redis:6379" # Update with your Redis service name:portcollection_interval: 10smetrics:redis.maxmemory:enabled: trueredis.role:enabled: falseredis.cmd.calls:enabled: trueredis.cmd.usec:enabled: trueredis.clients.max_input_buffer:enabled: falseredis.clients.max_output_buffer:enabled: falseredis.replication.backlog_first_byte_offset:enabled: falseresource_attributes:server.address:enabled: trueserver.port:enabled: trueprocessors:memory_limiter:check_interval: 5slimit_mib: 512spike_limit_mib: 128resource_detection:detectors: [env, system]timeout: 5soverride: falsesystem:resource_attributes:host.name:enabled: truehost.id:enabled: true# Uncomment the section below to use a custom human-readable name for your# Redis entity instead of the default server.address:server.port identifier.# resource/redis:# attributes:# - key: redis.instance.id# value: "my-redis-instance"# action: upsertattributes/entity_tags:actions:- key: instrumentation.providervalue: opentelemetryaction: upsertcumulativetodelta:include:match_type: regexpmetrics:- redis\.commands\.processed- redis\.connections\.received- redis\.connections\.rejected- redis\.keys\.evicted- redis\.keys\.expired- redis\.keyspace\.hits- redis\.keyspace\.misses- redis\.net\.input- redis\.net\.output- redis\.cpu\.time- redis\.cmd\.calls- redis\.cmd\.usec- redis\.uptimefilter/cardinality:metrics:datapoint:- 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'- 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'- 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'transform/metadata_nullify:metric_statements:- context: metricstatements:- set(description, "")- set(unit, "")batch:send_batch_size: 2048send_batch_max_size: 4096timeout: 10sexporters:otlp_http:endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}headers:api-key: ${env:NEW_RELIC_LICENSE_KEY}compression: gzipservice:extensions: [health_check]pipelines:metrics/redis:receivers: [redis]# If using resource/redis for custom name, add it to the processors list:# processors: [memory_limiter, resource_detection, resource/redis, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]exporters: [otlp_http]この設定で行うこと
パイプラインの各コンポーネントには特定の役割があります:
コンポーネント 説明 health_checkコレクターが実行されていることを確認できるように、 0.0.0.0:13133でヘルスエンドポイントを公開します。redisレシーバー10秒ごとにRedisエンドポイントに接続し、Redisの INFOコマンドからメトリクスを読み取ります。server.addressとserver.portはエンティティのIDになります。memory_limiterコンテナを保護するために、コレクターのメモリ使用量に上限を設定します(ソフトリミット512 MiB、スパイク128 MiB)。 resource_detectionホストを検出し、 host.nameとhost.idを追加して、Redisメトリクスを基盤となるホストエンティティにリンクします。attributes/entity_tagsクエリをOpenTelemetryパスにスコープできるように、すべてのメトリクスに instrumentation.provider: opentelemetryをスタンプします。cumulativetodeltaNew Relicがレートを正しくチャート化できるように、Redisの累積カウンター — コマンド、キースペースヒット、エビクションなど — をデルタ値に変換します。 filter/cardinality取り込みコストを制御するために、高いカーディナリティのデータポイント( userとsys以外のCPUステータス、および一般的ではないコマンドのコマンドごとのメトリクス)をドロップします。transform/metadata_nullifyペイロードのサイズを縮小するために、メトリクスの説明と単位をクリアします。 batchネットワークのオーバーヘッドを削減するために、エクスポートする前にデータポイントをグループ化し(バッチあたり2,048、最大4,096)、少なくとも10秒ごとにフラッシュします。 otlp_http処理されたメトリクスを、ライセンスキーで認証し、gzip圧縮を使用してOTLP経由でNew Relicにエクスポートします。 ヒント
ユーザーフレンドリーなエンティティ名をご希望ですか?デフォルトでは、Redisエンティティは
server.address:server.portの組み合わせを使用して名前が付けられます。代わりに人間が読めるカスタム名を使用するには、上記の設定のresource/redisセクションのコメントを解除し、redis.instance.idの値に希望する名前を設定して、プロセッサパイプラインにresource/redisを追加します。
オプション:認証を構成する
デフォルトでは、コレクターは資格情報なしでRedisに接続します。Redisインスタンスに認証が必要な場合は、一致する資格情報をredisレシーバーに追加します。設定に一致するオプションを選択してください:
オプション:Redisログの収集
メトリクスに加えて、コレクターはRedisのログファイルをNew Relicに転送できるため、ログイベント — 再起動、永続化イベント、またはエラー — を同じエンティティ上のメトリクスのスパイクと関連付けることができます。
重要
デフォルトでは、DockerのRedisはstdoutにログを出力します(ファイルには出力しません)。filelogレシーバーでログを収集するには、ログファイルに書き込むようにRedisを構成し、Redisコンテナとコレクターコンテナ間でDockerボリュームを介して共有する必要があります。
docker-compose.ymlのRedisサービスに以下を追加します:
redis: image: redis:7 command: > sh -c "touch /data/redis.log && chmod 644 /data/redis.log && redis-server --logfile /data/redis.log" volumes: - redis-logs:/dataそして、共有ボリュームをコレクターサービスに追加します:
otel-collector: volumes: - redis-logs:/var/log/redis:ro次に、docker-compose.ymlの一番下に追加します:
volumes: redis-logs:filelogレシーバーをotel-collector-config.yamlに追加します:
receivers: # ... existing redis receiver ... file_log/redis: include: - /var/log/redis/redis.log start_at: end operators: - type: regex_parser regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) ' on_error: send resource: db.system: redisファイルからのログ行には、それ自体にRedis接続コンテキストがありません—New RelicがログをRedisエンティティに関連付けるように、ID属性を明示的にアタッチする必要があります。RedisエンティティのIDに一致するハードコードされた値を使用して、resource/redis_logsプロセッサを追加します:
processors: # ... existing processors ... resource/redis_logs: attributes: - key: server.address value: "redis" # Must match your redis receiver endpoint host action: upsert - key: server.port value: 6379 # Must match your redis receiver endpoint port action: upsert - key: instrumentation.provider value: opentelemetry action: upsertヒント
カスタムインスタンスIDを使用していますか?カスタムエンティティの命名のためにresource/redisプロセッサーを有効にした場合は、上記のserver.addressとserver.portをredis.instance.idに置き換えます:
resource/redis_logs: attributes: - key: redis.instance.id value: "my-redis-instance" # Must match the value in resource/redis action: upsert - key: instrumentation.provider value: opentelemetry action: upsertserviceセクションに別のログパイプラインを追加します:
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] logs/redis: receivers: [file_log/redis] processors: [memory_limiter, resource/redis_logs, batch] exporters: [otlp_http]重要
コレクターコンテナは、Redisログファイルへの読み取りアクセス権を持っている必要があります。ログディレクトリをコンテナにマウントするときは、コレクタープロセスがファイルを読み取れることを確認してください。ホストで次を実行します:
$sudo chmod 755 /var/log/redis$sudo chmod 644 /var/log/redis/redis.logオプション:ホストメトリクスの収集
Redisのパフォーマンスは、多くの場合、ホストのリソースの圧迫 — CPUの飽和、メモリの枯渇、またはディスクI/Oの競合に連動します。New Relicで両者を関連付けることができるように、Redisとともにシステムメトリクスを収集するhostmetricsレシーバーを追加します。コレクターがコンテナのファイルシステムではなくホストのファイルシステムを読み取るようにするため、Dockerコンテナ内で実行する場合はroot_path: /hostfs設定が必須です:
receivers: # ... existing receivers ... host_metrics: collection_interval: 10s root_path: /hostfs scrapers: cpu: metrics: system.cpu.utilization: {enabled: true} system.cpu.time: {enabled: true} load: metrics: system.cpu.load_average.1m: {enabled: true} system.cpu.load_average.5m: {enabled: true} system.cpu.load_average.15m: {enabled: true} memory: metrics: system.memory.usage: {enabled: true} system.memory.utilization: {enabled: true} disk: metrics: system.disk.io: {enabled: true} system.disk.operations: {enabled: true} filesystem: metrics: system.filesystem.usage: {enabled: true} system.filesystem.utilization: {enabled: true} network: metrics: system.network.io: {enabled: true} system.network.packets: {enabled: true}ホストメトリクス用に別のmetrics/hostパイプラインを追加します(Redisパイプラインにhost_metricsを追加しないでください):
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] metrics/host: receivers: [host_metrics] processors: [memory_limiter, resource_detection, attributes/entity_tags, batch] exporters: [otlp_http]オプション:カスタムメタデータの追加
カスタムリソース属性によって、すべてのRedisメトリクスにコンテキスト — 環境、チーム、またはティア — のタグが付けられるため、New Relicでデータをフィルタリングおよびグループ化できます。必要なタグを含むresource/customプロセッサを追加します:
processors: # ... existing processors ... resource/custom: attributes: - key: environment value: "production" action: upsert - key: team value: "platform" action: upsertパイプラインにプロセッサを含めます:
service: pipelines: metrics/redis: receivers: [redis] processors: [memory_limiter, resource_detection, resource/custom, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http]オプション:Redis Clusterの監視を有効にする
Redis Clusterの監視には、現在Prometheusレシーバーのアプローチ(redis_exporterを使用)が必要です。OTel Collector ContribのネイティブRedisレシーバーは、クラスタメトリクスに必要なCLUSTER INFOコマンドをまだサポートしていません。クラスタ監視のセットアップには、Prometheusレシーバータブを使用します。
Docker Composeファイルの作成
既存のRedisと並行してコレクターを実行するためのdocker-compose.ymlを作成します。同じディレクトリにある.envファイルは、Docker Composeによって自動的に読み込まれます:
services: otel-collector: image: otel/opentelemetry-collector-contrib:latest env_file: .env volumes: - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro - /etc/machine-id:/etc/machine-id:ro # Uncomment if collecting Redis logs (requires shared volume — see logs step above): # - redis-logs:/var/log/redis:ro # Uncomment if collecting host metrics: # - /:/hostfs:ro # Uncomment if using TLS: # - ./certs:/etc/ssl/redis:ro environment: - NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY} - OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT} # Uncomment if collecting host metrics: # - HOST_PROC=/hostfs/proc # - HOST_SYS=/hostfs/sys # - HOST_ETC=/hostfs/etc # Uncomment if using Redis authentication: # - REDIS_PASSWORD=${REDIS_PASSWORD} # - REDIS_USERNAME=${REDIS_USERNAME} command: ["--config=/etc/otelcol-contrib/config.yaml"] ports: - "13133:13133" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:13133"] interval: 10s timeout: 5s retries: 3
# Uncomment if collecting Redis logs:# volumes:# redis-logs:ヒント
前の手順でオプション機能(ログ、ホストメトリクス、TLS、または認証)を有効にした場合は、上記のDocker Composeファイル内の対応する行のコメントを解除してください。
環境ファイルを作成します
Docker Composeは、docker-compose.ymlと同じディレクトリにある.envファイルからデプロイメント固有の値を読み取ります。これにより、ライセンスキーをcomposeファイルから除外できます。.envファイルを作成します:
$NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY$OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT$# Set the New Relic OTLP endpoint for your region.$# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlpプレースホルダーを独自の値に置き換えます:
| 変数 | 必須 | 説明 |
|---|---|---|
NEW_RELIC_LICENSE_KEY | はい | New Relic取り込みライセンスキー。 |
OTEL_EXPORTER_OTLP_ENDPOINT | はい | ご利用のリージョンのNew Relic OTLPエンドポイント。詳細については、New Relic OTLPエンドポイントを参照してください。 |
開始・検証する
バックグラウンドでコレクターを開始します:
$docker compose up -ddocker compose psでコンテナが実行されていることを確認します — コレクターはrunningステータスを表示するはずです。終了した場合は、docker compose logs otel-collectorでログを確認します — 最も一般的な原因は、YAMLのインデントエラーと到達不可能なRedisエンドポイントです。
次に、メトリクスがNew Relicに到達していることを確認します。起動後約1分待ってから、クエリビルダーで次のクエリを実行します:
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes agoゼロ以外のカウントにより、Redisメトリクスが流れていることが確認できます。0が返される場合は、Redisのトラブルシューティング(OpenTelemetry)を参照してください。
コレクターの設定を作成します
この設定は、redis_exporterからメトリクスをスクレイピングし、それらをNew Relicに送信します。これは以下の主なジョブを処理します:
prometheusレシーバーを介してredis_exporterPrometheusエンドポイントをスクレイプしますPrometheusのメトリクスをNew RelicのRedisメトリクス名に名前変更します
データを形成します — カーディナリティを削減し、カウンターをデルタに変換し、エンティティ合成のためにタグ付けします。
処理されたメトリクスをOTLP経由でNew Relicにエクスポートする
プロジェクトディレクトリに
otel-collector-config.yamlを作成します:extensions:health_check:endpoint: "0.0.0.0:13133"receivers:prometheus:config:scrape_configs:- job_name: 'redis'scrape_interval: 10sstatic_configs:- targets: ['redis-exporter:9121'] # Update with your Redis exporter host:portmetric_relabel_configs:- source_labels: [__name__]regex: '(go_|process_|promhttp_|redis_exporter_).*'action: dropprocessors:memory_limiter:check_interval: 5slimit_mib: 512spike_limit_mib: 128resource_detection:detectors: [env, system]timeout: 5soverride: falsesystem:resource_attributes:host.name:enabled: truehost.id:enabled: true# Required: Set a unique identifier for your Redis entity.# The Prometheus receiver does not provide server.address/server.port,# so redis.instance.id is required for entity creation in New Relic.resource/redis_identity:attributes:- key: redis.instance.idvalue: "my-redis-instance:6379" # Update with a unique name for this Redis instanceaction: upsertattributes/entity_tags:actions:- key: instrumentation.providervalue: opentelemetryaction: upsertmetricstransform:transforms:- include: redis_uptime_in_secondsaction: updatenew_name: redis.uptime- include: redis_connected_clientsaction: updatenew_name: redis.clients.connected- include: redis_blocked_clientsaction: updatenew_name: redis.clients.blocked- include: redis_memory_used_bytesaction: updatenew_name: redis.memory.used- include: redis_memory_max_bytesaction: updatenew_name: redis.maxmemory- include: redis_mem_fragmentation_ratioaction: updatenew_name: redis.memory.fragmentation_ratio- include: redis_memory_used_rss_bytesaction: updatenew_name: redis.memory.rss- include: redis_memory_used_peak_bytesaction: updatenew_name: redis.memory.peak- include: redis_memory_used_lua_bytesaction: updatenew_name: redis.memory.lua- include: redis_connections_received_totalaction: updatenew_name: redis.connections.received- include: redis_rejected_connections_totalaction: updatenew_name: redis.connections.rejected- include: redis_commands_processed_totalaction: updatenew_name: redis.commands.processed- include: redis_keyspace_hits_totalaction: updatenew_name: redis.keyspace.hits- include: redis_keyspace_misses_totalaction: updatenew_name: redis.keyspace.misses- include: redis_evicted_keys_totalaction: updatenew_name: redis.keys.evicted- include: redis_expired_keys_totalaction: updatenew_name: redis.keys.expired- include: redis_net_input_bytes_totalaction: updatenew_name: redis.net.input- include: redis_net_output_bytes_totalaction: updatenew_name: redis.net.output- include: redis_connected_slavesaction: updatenew_name: redis.slaves.connected- include: redis_db_keysaction: updatenew_name: redis.db.keys- include: redis_db_keys_expiringaction: updatenew_name: redis.db.expires- include: redis_rdb_changes_since_last_saveaction: updatenew_name: redis.rdb.changes_since_last_save- include: redis_db_avg_ttl_secondsaction: updatenew_name: redis.db.avg_ttl- include: redis_latest_fork_secondsaction: updatenew_name: redis.latest_fork- include: redis_master_repl_offsetaction: updatenew_name: redis.replication.offset- include: redis_repl_backlog_first_byte_offsetaction: updatenew_name: redis.replication.backlog_first_byte_offset- include: redis_commands_totalaction: updatenew_name: redis.cmd.calls- include: redis_commands_duration_seconds_totalaction: updatenew_name: redis.cmd.usec- include: redis_cpu_sys_seconds_totalaction: updatenew_name: redis.cpu.timeoperations:- action: add_labelnew_label: statenew_value: sys- include: redis_cpu_user_seconds_totalaction: updatenew_name: redis.cpu.timeoperations:- action: add_labelnew_label: statenew_value: usercumulativetodelta:include:match_type: regexpmetrics:- redis\.commands\.processed- redis\.connections\.received- redis\.connections\.rejected- redis\.keys\.evicted- redis\.keys\.expired- redis\.keyspace\.hits- redis\.keyspace\.misses- redis\.net\.input- redis\.net\.output- redis\.cpu\.time- redis\.cmd\.calls- redis\.cmd\.usec- redis\.uptimefilter/cardinality:metrics:datapoint:- 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'- 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'- 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'transform/metadata_nullify:metric_statements:- context: metricstatements:- set(description, "")- set(unit, "")batch:send_batch_size: 2048send_batch_max_size: 4096timeout: 10sexporters:otlp_http:endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}headers:api-key: ${env:NEW_RELIC_LICENSE_KEY}compression: gzipservice:extensions: [health_check]pipelines:metrics/redis:receivers: [prometheus]processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]exporters: [otlp_http]この設定で行うこと
パイプラインの各コンポーネントには特定の役割があります:
コンポーネント 説明 health_checkコレクターが実行されていることを確認できるように、 0.0.0.0:13133でヘルスエンドポイントを公開します。prometheusレシーバー10秒ごとに redis_exporterエンドポイント(デフォルトはredis-exporter:9121)をスクレイピングし、エクスポーター自身のgo_*、process_*、promhttp_*、およびredis_exporter_*メトリクスを破棄します。memory_limiterコンテナを保護するために、コレクターのメモリ使用量に上限を設定します(ソフトリミット512 MiB、スパイク128 MiB)。 resource_detectionホストを検出し、 host.nameとhost.idを追加して、Redisメトリクスを基盤となるホストエンティティにリンクします。resource/redis_identityNew RelicでRedisエンティティを識別する redis.instance.idを設定します。Prometheusレシーバーはserver.addressやserver.portを提供しないため、ここではこれが必要です。attributes/entity_tagsクエリをOpenTelemetryパスにスコープできるように、すべてのメトリクスに instrumentation.provider: opentelemetryをスタンプします。metricstransformエクスポーターのPrometheusメトリクス(たとえば redis_uptime_in_seconds)をNew RelicのRedis名(redis.uptime)に名前変更し、CPUメトリクスにstateラベルを追加します。cumulativetodeltaNew Relicがレートを正確にグラフ化できるように、累積カウンター — コマンド、キースペースヒット、エビクションなど — をデルタ値に変換します。 filter/cardinality取り込みコストを制御するために、高いカーディナリティのデータポイント( userとsys以外のCPUステータス、および一般的ではないコマンドのコマンドごとのメトリクス)をドロップします。transform/metadata_nullifyペイロードのサイズを縮小するために、メトリクスの説明と単位をクリアします。 batchネットワークのオーバーヘッドを削減するために、エクスポートする前にデータポイントをグループ化し(バッチあたり2,048、最大4,096)、少なくとも10秒ごとにフラッシュします。 otlp_http処理されたメトリクスを、ライセンスキーで認証し、gzip圧縮を使用してOTLP経由でNew Relicにエクスポートします。 重要
Prometheusレシーバーのアプローチでは、
redis.instance.idを使用するresource/redis_identityプロセッサが必須です。ネイティブのRedisレシーバーとは異なり、Prometheusレシーバーはserver.addressやserver.portを提供しないため、New RelicでRedisエンティティを識別する唯一の方法はredis.instance.idです。各インスタンスに対して、一意で分かりやすい名前(例:prod-redis-cache:6379)を設定します。
オプション:Redis Clusterの監視を有効にする
RedisがClusterモードで実行されている場合、すべてのノードからクラスタのヘルスメトリクスを自動的に収集するために、--is-clusterフラグを付けてredis_exporterを開始します:
$redis_exporter --redis.addr=redis://localhost:7000 --is-cluster上記のPrometheusレシーバーの設定では、すでにクラスタメトリクスの名前が変更されています(例:redis_cluster_state→redis.cluster.state)。New Relicで別のクラスタエンティティを作成するには、redis.instance.idを含まない別のパイプラインにredis.cluster.nameリソース属性を追加します:
resource/cluster: attributes: - key: redis.cluster.name value: "my-redis-cluster" # Update with your cluster name action: upsertサービスセクションにクラスタパイプラインを追加します:
metrics/cluster: receivers: [prometheus] processors: [memory_limiter, resource_detection, resource/cluster, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http]重要
クラスタエンティティは、redis.cluster.nameが存在し、かつredis.instance.idが存在しないことを必要とします。両方が同じメトリクスに設定されている場合、インスタンスエンティティのみが作成されます。インスタンスとクラスタのメトリクスには、別々のパイプラインを使用します。
オプション:Redisログの収集
メトリクスに加えて、コレクターはRedisのログファイルをNew Relicに転送できるため、ログイベント — 再起動、永続化イベント、またはエラー — を同じエンティティ上のメトリクスのスパイクと関連付けることができます。
重要
デフォルトでは、DockerのRedisはstdoutにログを出力します(ファイルには出力しません)。filelogレシーバーでログを収集するには、ログファイルに書き込むようにRedisを構成し、Redisコンテナとコレクターコンテナ間でDockerボリュームを介して共有する必要があります。
docker-compose.ymlのRedisサービスに以下を追加します:
redis: image: redis:7 command: > sh -c "touch /data/redis.log && chmod 644 /data/redis.log && redis-server --logfile /data/redis.log" volumes: - redis-logs:/dataそして、共有ボリュームをコレクターサービスに追加します:
otel-collector: volumes: - redis-logs:/var/log/redis:ro次に、docker-compose.ymlの一番下に追加します:
volumes: redis-logs:filelogレシーバーをotel-collector-config.yamlに追加します:
receivers: # ... existing prometheus receiver ... file_log/redis: include: - /var/log/redis/redis.log start_at: end operators: - type: regex_parser regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) ' on_error: send resource: db.system: redisファイルからのログ行には、それ自体にRedis接続コンテキストがありません—New RelicがログをRedisエンティティに関連付けるように、ID属性を明示的にアタッチする必要があります。RedisエンティティのIDに一致するハードコードされた値を使用して、resource/redis_logsプロセッサを追加します:
processors: # ... existing processors ... resource/redis_logs: attributes: - key: redis.instance.id value: "my-redis-instance:6379" # Must match the value in resource/redis_identity action: upsert - key: instrumentation.provider value: opentelemetry action: upsertserviceセクションに別のログパイプラインを追加します:
service: pipelines: metrics/redis: receivers: [prometheus] processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] logs/redis: receivers: [file_log/redis] processors: [memory_limiter, resource/redis_logs, batch] exporters: [otlp_http]オプション:ホストメトリクスの収集
Redisのパフォーマンスは、多くの場合、ホストのリソースの圧迫 — CPUの飽和、メモリの枯渇、またはディスクI/Oの競合に連動します。New Relicで両者を関連付けることができるように、Redisとともにシステムメトリクスを収集するhostmetricsレシーバーを追加します。コレクターがコンテナのファイルシステムではなくホストのファイルシステムを読み取るようにするため、Dockerコンテナ内で実行する場合はroot_path: /hostfs設定が必須です:
receivers: # ... existing receivers ... host_metrics: collection_interval: 10s root_path: /hostfs scrapers: cpu: metrics: system.cpu.utilization: {enabled: true} system.cpu.time: {enabled: true} load: metrics: system.cpu.load_average.1m: {enabled: true} system.cpu.load_average.5m: {enabled: true} system.cpu.load_average.15m: {enabled: true} memory: metrics: system.memory.usage: {enabled: true} system.memory.utilization: {enabled: true} disk: metrics: system.disk.io: {enabled: true} system.disk.operations: {enabled: true} filesystem: metrics: system.filesystem.usage: {enabled: true} system.filesystem.utilization: {enabled: true} network: metrics: system.network.io: {enabled: true} system.network.packets: {enabled: true}ホストメトリクス用に別のmetrics/hostパイプラインを追加します(Redisパイプラインにhost_metricsを追加しないでください):
service: pipelines: metrics/redis: receivers: [prometheus] processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch] exporters: [otlp_http] metrics/host: receivers: [host_metrics] processors: [memory_limiter, resource_detection, attributes/entity_tags, batch] exporters: [otlp_http]Docker Composeファイルの作成
既存のRedisと並行してredis_exporterとコレクターを実行するために、docker-compose.ymlを作成します。同じディレクトリにある.envファイルは、Docker Composeによって自動的に読み込まれます:
services: redis-exporter: image: oliver006/redis_exporter:latest environment: - REDIS_ADDR=redis://redis:6379 # Update with your Redis service name:port # Uncomment if using Redis authentication: # - REDIS_PASSWORD=${REDIS_PASSWORD} # - REDIS_USER=${REDIS_USERNAME} ports: - "9121:9121" healthcheck: test: ["CMD-SHELL", "redis_exporter --version || exit 1"] interval: 10s timeout: 5s retries: 3
otel-collector: image: otel/opentelemetry-collector-contrib:latest env_file: .env volumes: - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro - /etc/machine-id:/etc/machine-id:ro environment: - NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY} - OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT} command: ["--config=/etc/otelcol-contrib/config.yaml"] ports: - "13133:13133" depends_on: redis-exporter: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:13133"] interval: 10s timeout: 5s retries: 3ヒント
代わりにNRDOTコレクターを使用するには、otel-collectorイメージをnewrelic/nrdot-collector:latestに置き換え、設定のマウントパスを/etc/otel/config.yamlに更新します。
環境ファイルを作成します
Docker Composeは、docker-compose.ymlと同じディレクトリにある.envファイルからデプロイメント固有の値を読み取ります。これにより、ライセンスキーをcomposeファイルから除外できます。.envファイルを作成します:
$NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY$OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT$# Set the New Relic OTLP endpoint for your region.$# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlpプレースホルダーを独自の値に置き換えます:
| 変数 | 必須 | 説明 |
|---|---|---|
NEW_RELIC_LICENSE_KEY | はい | New Relic取り込みライセンスキー。 |
OTEL_EXPORTER_OTLP_ENDPOINT | はい | ご利用のリージョンのNew Relic OTLPエンドポイント。詳細については、New Relic OTLPエンドポイントを参照してください。 |
開始・検証する
バックグラウンドでコレクターとredis_exporterを開始します:
$docker compose up -ddocker compose psでコンテナが実行されていることを確認します — コレクターとredis-exporterの両方がrunningステータスを示しているはずです。コレクターが終了した場合は、docker compose logs otel-collectorでログを確認してください — 最も一般的な原因は、YAMLのインデントエラー、到達不能なredis_exporter、またはエクスポーターが実行されていないことです。
次に、メトリクスがNew Relicに到達していることを確認します。起動後約1分待ってから、クエリビルダーで次のクエリを実行します:
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes agoゼロ以外のカウントにより、Redisメトリクスが流れていることが確認できます。0が返される場合は、Redisのトラブルシューティング(OpenTelemetry)を参照してください。
ヒント
APMとRedisを関連付ける: サービスマップでAPMアプリケーションとRedisインスタンスを接続するには、選択したエンティティ識別子パターン — redis.instance.id、またはserver.addressとserver.portのいずれか — とともにdb.system="redis"をAPMメトリクスのリソース属性として含めます。この値は、コレクターで設定したものと一致する必要があります。これにより、New Relic内でのサービス間の可視性が向上し、トラブルシューティングが迅速化されます。
次のステップ
- セルフホスト型インストレーション: VM/ベアメタル上のRedisをモニターする
- Kubernetesインストレーション: DaemonSetを使用してKubernetesにデプロイします
- データの表示: ダッシュボードを探索してアラートを設定します
- メトリクスリファレンス: 利用可能なメトリクスの完全なリスト
- トラブルシューティング: 一般的な問題と解決策