Rails 8 での構造化ログ実装の軌跡
Rails 8 での構造化ログ実装の軌跡
English follows Japanese.
概要
- 構造化ログと Cloud Logging の組み合わせは、便利
- フィルタリング
- 一連のログのグルーピング
- Cloud Run
- traceparent ヘッダーが標準で付与される
- (隠れた)LB のログにも Trace ID が含まれる
- 標準出力で実証
- 実行環境
- Rails 8
- Ruby 3.4
- DB なし
スモールスタートで、非機能の面にはあまり時間がかけられない場合でも、動くコードを含めた先行例があれば、実装の参考になると思いました。
はじめに
本記事では、Rails 8 アプリケーションにおける構造化ログの実装例を紹介します。特に、分散トレーシングのための Trace ID をログに含める方法に焦点を当て、SemanticLogger(GitHub, Rails Semantic Logger) と連携した W3C TraceContext の活用方法を解説します。
Lograge が良く使われている印象がありますが、JSON にしつつ、request_id を付与するのが面倒という記事もいくつか見かけました。その点、SemanticLogger は構造化ログを簡単に実現そうだったので、調査も兼ねて実装してみました。
背景
マイクロサービスアーキテクチャが普及する中、複数サービス間でのリクエストの追跡が重要な課題となっています。W3C TraceContext は、サービス間でトレース情報を伝播するための標準規格で、HTTP traceparent
ヘッダーを使用して Trace ID を受け渡します。
当プロジェクトでは、この Trace ID を Rails アプリケーションのログに統合し、Google Cloud Logging での一元的な監視を可能にすることを目標としました。
まとめ
- middleware を新規実装し、使って Request Header (traceparent) から Trace ID を抽出
HTTP_TRACEPARENT
ヘッダーを抽出し、env[:traceparent]
に保存- Trace ID を
env[:trace_id]
に保存 req.request_id
に Trace ID を上書き
config.log_tags
を使って、リクエスト ID と Trace ID をログにタグ付けtraceparent
とtrace_id
をlog_tags
に追加
- 構造化ログ (JSON) を出力するためのフォーマッタを実装
SemanticLogger::Formatters::Json
とほぼ同じ実装SemanticLogger::Formatters::Raw
を継承traceparent
フィールドを、トップレベルフィールドとして出力logging.googleapis.com/trace
フィールドをトップレベルフィールドとし、projects/#{ENV["PROJECT_ID"]}/traces/#{trace_id}
とする形で Trace ID を設定
上記によって、Cloud Logging で Trace ID によるログのグルーピングが可能になります。専用のログ エージェントの導入が不要で、Cloud Run の標準出力に直接出力するだけで、Google Cloud Logging に構造化ログが送信されます。
(参考)Rails における Request ID の仕組み
まず、Rails の標準的なログに含まれる request_id
の仕組みを理解しておくことが重要です。bisque によるRailsのログに含まれるrequest_idについてコードリーディングしたメモによれば、request_id は以下のように処理されます:
- 生成:
ActionDispatch::RequestId
ミドルウェアが Request Header のX-Request-Id
を取得(ない場合は UUID を生成) - 伝播: リクエストオブジェクトの
request_id
属性として保存され、Response Header にもX-Request-Id
として設定(注: Request Header なのでは…と思うが、良く分かっていない) - ログ出力:
Rack::Logger
ミドルウェアがActiveSupport::TaggedLogging
を通じてログにrequest_id
を挿入 - スレッド管理:
ActiveSupport::TaggedLogging
はThread.current
を使ってタグを管理し、アプリケーション全体で参照可能に
この仕組みを応用して、W3C TraceContext からの Trace ID をログに統合する実装を行います。
X-Request-Id
ヘッダーは、リクエストのトレースを追跡するために使用されていました(今でも使用されています)。分散トレーシングの観点からは、Trace ID を含む traceparent
ヘッダーを使用することが推奨されます。
実装のステップ
1. 必要な Gem の導入
まず、構造化ログ出力のための Gem をインストールしました。Gemfile
に以下を追加します。JSON で出力する仕組みも含まれています。
gem "rails_semantic_logger"
2. トレースミドルウェアの実装
Request Header から Trace ID を抽出するために、専用のミドルウェアを実装しました。これは Rails の ActionDispatch::RequestId
と同様のアプローチです。
GitHub リポジトリへのリンクも付しておきます。trace_middleware.rb
# lib/trace_middleware.rb
class TraceMiddleware
def initialize(app)
@app = app
end
def call(env)
# HTTP_TRACEPARENT ヘッダーを抽出
trace_parent = extract_trace_parent(env)
if trace_parent
env[:traceparent] = trace_parent
end
# ヘッダーから trace_id を抽出、
# ない場合は SecureRandom.uuid を使用
env[:trace_id] = make_trace_id(trace_parent)
# Overwrite the request_id with the trace_id
req = ActionDispatch::Request.new env
req.request_id = insert_hyphens(env[:trace_id])
@app.call(env)
end
# ...
end
このミドルウェアは、W3C TraceContext に準拠した traceparent
ヘッダー(HTTP_TRACEPARENT
に保存される)から Trace ID を抽出し、リクエスト環境変数に保存します。ヘッダーが存在しない場合は、UUID 形式の新しい Trace ID を生成します。
Rails の Request ID と Trace ID を統一する実装も行いました。traceparent
がある場合には、それを優先しているだけなので、仕組みは同じです。
これにより、デフォルトのログ出力でも Trace ID が使われるようになり、一貫性のあるログ出力が可能になりました。insert_hyphens
メソッドは、Trace ID にハイフンを挿入して UUID 形式に変換する機能を持っています:
def insert_hyphens(trace_id)
trace_id = trace_id.dup.to_s
# 各位置にハイフンを挿入(文字列長をチェックしながら)
[8, 13, 18, 23].each do |pos|
break if trace_id.length <= pos
trace_id.insert(pos, "-")
end
trace_id
end
この実装は、ActionDispatch::RequestId
ミドルウェアの直後に配置することで、Rails が生成した request_id
を上書きします。これは bisque の記事Railsのログに含まれるrequest_idについてコードリーディングしたメモで解説されている Rails の request_id
の仕組みを利用しています。
bin/rails middleware
コマンドを実行すると、ミドルウェアの順序を確認できるんですね。
3. カスタムログフォーマッタの実装
次に、SemanticLogger のフォーマッタをカスタマイズし、Trace ID をログのトップレベルフィールドとして出力できるようにしました。これは en30 の記事Rails on GKEでも理想の構造化ログを目指すで紹介されているアプローチを参考にしています。
# lib/formatters/cloud_trace_log_json.rb
module Formatters
class CloudTraceLogJson < SemanticLogger::Formatters::Raw
# Default JSON time format is ISO8601
def initialize(time_format: :iso_8601, time_key: :timestamp, **args)
super(time_format: time_format, time_key: time_key, **args)
end
def traceparent
if log.named_tags && log.named_tags[:traceparent]
hash[:traceparent] = log.named_tags[:traceparent]
end
end
def trace
if log.named_tags && log.named_tags[:trace_id]
trace_id = log.named_tags[:trace_id]
elsif log.named_tags && log.named_tags[:request_id]
trace_id = log.named_tags[:request_id].gsub("-", "")
else
return
end
hash["logging.googleapis.com/trace"] = "projects/#{ENV["PROJECT_ID"]}/traces/#{trace_id}" if trace_id && !ENV["PROJECT_ID"].nil? && !ENV["PROJECT_ID"].empty?
end
# ...
end
end
このフォーマッタにより、ログ出力時に Trace ID が Google Cloud Logging が求める形式 構造化ロギング に変換され、UI で関連するログを Trace ID で検索できるようになります。特に Google Cloud Logging 固有の logging.googleapis.com/trace
フィールドに、PROJECT_ID
を含めた出力をしています。これで、Google Cloud のトレース機能との統合が容易になります。
参考記事では、Lograge と google-cloud-logging (ruby) を組み合わせていました。
4. Rails の設定
導入のため、いくつか Rails の設定を変更しました。特に、SemanticLogger を使用するための設定を行いました。config/application.rb
に以下を追加します:
TaggedLogging
ログエントリにタグを付けておきます。log_tags
にハッシュを指定すると、名前付きのタグを追加できます。これにより、リクエスト ID や Trace ID をログに含めることができます。
# config/application.rb
config.log_tags = {
request_id: :request_id,
trace_id: ->(request) { request.env[:trace_id] },
traceparent: ->(request) { request.env[:traceparent] }
}
このように、log_tags
を設定すると、SemanticLogger では named_tags
フィールドにタグが追加されます。これにより、リクエスト ID や Trace ID を含む構造化ログを生成できます。
config/environments/production.rb
には config.log_tags = [ :request_id ]
という行がありますが、config/application.rb
の設定を上書きしてしまいます。config/environments/production.rb
にも同様の設定を追加する必要があります。
ミドルウェアの配置順序
ミドルウェアの挿入位置は重要な検討事項でした。ActionDispatch::RequestId
ミドルウェアの直後に配置することで、Request ID をすぐに上書きするようにします。とにかく最初に抽出したければ insert_after 0
で良いのですが、RequestId
と整合性を持たせたかったので、ActionDispatch::RequestId
の直後に配置しました。
# config/application.rb
# config.middleware.insert_after 0, TraceMiddleware
config.middleware.insert_after ActionDispatch::RequestId, TraceMiddleware
この配置により、以下の処理フローが実現されます:
ActionDispatch::RequestId
ミドルウェアがデフォルトのrequest_id
を生成TraceMiddleware
が Trace ID を抽出し、必要に応じてrequest_id
を上書きRack::Logger
がrequest_id
(上書きされた場合は Trace ID)をログに出力
SemanticLogger の設定
SemanticLogger を使用し、独自フォーマッタを導入するための設定を行います。config/application.rb
に以下を追加します:
# config/application.rb
config.rails_semantic_logger.started = true
config.rails_semantic_logger.add_file_appender = false
# config.semantic_logger.add_appender(io: $stdout, formatter: :json)
config.semantic_logger.add_appender(io: $stdout, formatter: Formatters::CloudTraceLogJson.new)
開発環境でも JSON 形式で出力されるのが嫌な場合は、config/environments/production.rb
だけに追加しておくと良いかもしれません。(ごめんなさい、試していません。開発環境で JSON になることを確認しながら実装をしたのです…)
閲覧
Cloud Logging では、"243 ms" のような、処理時間を表すフィールド(横にトレースを示す記号がついている)をクリックすると、メニューが出てきて "Show entries for this trace" を選択すると、特定トレースだけを抽出して表示することができます。
Rails アプリケーションからのログは、JSON 形式で出力されています。
JSON 形式でログを出力した場合、"logging.googleapis.com/trace" フィールドは、jsonPayload には含まれず、トップレベルのフィールドとして出力されます。
おまけ: デプロイのためのコード
Terraform を使用したデプロイ
実際に Cloud Run にデプロイする際、Terraform を使用してインフラをコード化しました。terraform/environments/stg
ディレクトリに配置しています。.tfvars
ファイルを作成し、プロジェクト ID とバックエンドバケット名を指定します。
project_id = "project-id"
backend_bucket_name = "tfstate-bucket"
あとは terraform apply -var-file=".tfvars"
を実行するだけで、Cloud Run 環境が構築されます。ただし、イメージのビルドと、Secret Manager へのシークレットの登録は手動で行う必要があります。
イメージのビルド
PROJECT_ID
を指定して、Cloud Build を使用してイメージをビルドします。
export PROJECT_ID="project-id"
gcloud builds submit . --project=$PROJECT_ID --config build_image.yaml
正しい書き方か自信はありませんが、build_image.yaml として置いておきます。
まとめ
この実装により、以下のことが達成されれました:
- 分散トレーシングのサポート - W3C TraceContext に準拠したトレース情報の伝播が可能に
- 構造化ログの実現 - JSON フォーマットでの出力により、検索・分析が容易に
- Google Cloud Logging との統合 - Trace ID を Cloud Logging のフォーマットで出力することで、ログのフィルタリングが改善
- アプリケーションの可観測性向上 - リクエスト全体を通した追跡が可能に
- 標準ログとの互換性 - 既存のログ収集ツールや分析ツールとの互換性を維持
Rails 8 での構造化ログ実装を通じて、SemanticLogger とカスタムミドルウェアを活用した Trace ID 統合の方法を紹介しました。この実装は、マイクロサービスアーキテクチャにおけるログの統合と追跡性向上に貢献し、デバッグやパフォーマンス分析の効率化に役立ちます。
bisque によるコードリーディングで解説されているように、Rails の request_id 機構は、ミドルウェア、スレッドローカル変数、タグ付けロガーの連携により実現されています。今回の実装では、その仕組みを活かしつつ、W3C TraceContext との統合を図りました。
この文章の一部は LLM に書かせたのですが、LLM は『今後の展望としては、より詳細なメトリクスの収集やアラート設定との連携など、モニタリング機能の強化を検討しています。また、OpenTelemetry との統合も視野に入れています。』と書いていました。そんなことするかは分かりません。
人間個人としては、他に、Cloud Logging 構造化ログの特別な JSON フィールドまとめを参考にしてフィールドを追加しても良いかなぁと思いました。
参考リソース
- W3C Trace Context仕様
- Semantic Logger 公式ドキュメント
- GitHub SemanticLogger
- GitHub RailsSemanticLogger
- Google Cloud Loggingドキュメント
- Rails on GKEでも理想の構造化ログを目指す last modified: 2021-04-28
- en30 による Rails on GKE での構造化ログ実装に関する記事。特に Google Cloud Logging との統合方法について参考になります。
- Railsのログに含まれるrequest_idについてコードリーディングしたメモ 2022-09-28
- bisque による Rails の request_id の詳細な解説記事。ActionDispatch::RequestId ミドルウェアや ActiveSupport::TaggedLogging の内部実装について詳しく説明しています。
- Fargate上のRailsからJSON形式でログをrequest_idと一緒に出力 2020-12-22
- logrageではRails.loggerのログ出力がJSON形式にならない問題 last modified: 2020-08-12
- tmimura39/rails_json_log_formatter.rb 2020-11-13
- Cloud Logging 構造化ログの特別な JSON フィールドまとめ 2023-10-23
- Cloud Logging 構造化ロギング
The Path to Implementing Structured Logging in Rails 8
Overview
- The combination of structured logging and Cloud Logging is convenient
- Filtering
- Grouping of a series of logs
- Cloud Run
- The
traceparent
header is added by default - Trace ID is also included in the logs of the (hidden) LB
- Demonstrated with standard output
- The
- Execution Environment
- Rails 8
- Ruby 3.4
- No DB
I thought that even in cases of a small start where not much time can be spent on non-functional aspects, having a preceding example including working code would be helpful as a reference for implementation.
Introduction
In this article, I will introduce an example of implementing structured logging in a Rails 8 application. In particular, I will focus on how to include Trace IDs for distributed tracing in logs, and explain how to utilize W3C TraceContext in conjunction with SemanticLogger(GitHub, Rails Semantic Logger).
I have the impression that Lograge is often used, but I've also seen some articles mentioning that it's cumbersome to convert to JSON and add a request_id
. In that regard, SemanticLogger seemed to make it easy to achieve structured logging, so I tried implementing it, partly as an investigation.
Background
As microservice architecture becomes more prevalent, tracking requests across multiple services has become an important issue. W3C TraceContext is a standard for propagating trace information between services, using the HTTP traceparent
header to pass Trace IDs.
In this project, the goal was to integrate this Trace ID into the logs of the Rails application and enable centralized monitoring with Google Cloud Logging.
Summary
- Implement new middleware to extract Trace ID from Request Header (
traceparent
)- Extract the
HTTP_TRACEPARENT
header and save it toenv[:traceparent]
- Save the Trace ID to
env[:trace_id]
- Overwrite
req.request_id
with the Trace ID
- Extract the
- Use
config.log_tags
to tag logs with Request ID and Trace ID- Add
traceparent
andtrace_id
tolog_tags
- Add
- Implement a formatter to output structured logs (JSON)
- Almost the same implementation as
SemanticLogger::Formatters::Json
- Inherit from
SemanticLogger::Formatters::Raw
- Output the
traceparent
field as a top-level field - Set the
logging.googleapis.com/trace
field as a top-level field, and configure the Trace ID in the formatprojects/#{ENV["PROJECT_ID"]}/traces/#{trace_id}
- Almost the same implementation as
With the above, grouping logs by Trace ID in Cloud Logging becomes possible. There is no need to install a dedicated log agent; structured logs are sent to Google Cloud Logging simply by outputting directly to Cloud Run's standard output.
(Reference) How Request ID works in Rails
First, it is important to understand the mechanism of request_id
included in standard Rails logs. According to Notes on code reading about request_id included in Rails logs by bisque, request_id
is processed as follows:
- Generation: The
ActionDispatch::RequestId
middleware retrievesX-Request-Id
from the Request Header (generates a UUID if not present) - Propagation: Saved as the
request_id
attribute of the request object and also set asX-Request-Id
in the Response Header (Note: I think it might be a Request Header... but I don't understand it well) - Log Output: The
Rack::Logger
middleware insertsrequest_id
into logs viaActiveSupport::TaggedLogging
- Thread Management:
ActiveSupport::TaggedLogging
usesThread.current
to manage tags, making them accessible throughout the application
We will implement the integration of Trace ID from W3C TraceContext into logs by applying this mechanism.
The X-Request-Id
header was used (and is still used) to track request traces. From a distributed tracing perspective, it is recommended to use the traceparent
header, which includes the Trace ID.
Implementation Steps
1. Installing Necessary Gems
First, I installed the gem for structured log output. Add the following to your Gemfile
. It also includes a mechanism for outputting in JSON.
gem "rails_semantic_logger"
2. Implementing Trace Middleware
To extract the Trace ID from the Request Header, I implemented dedicated middleware. This is a similar approach to Rails' ActionDispatch::RequestId
.
I'll also include a link to the GitHub repository: trace_middleware.rb
# lib/trace_middleware.rb
class TraceMiddleware
def initialize(app)
@app = app
end
def call(env)
# Extract HTTP_TRACEPARENT header
trace_parent = extract_trace_parent(env)
if trace_parent
env[:traceparent] = trace_parent
end
# Extract trace_id from the header,
# if not present, use SecureRandom.uuid
env[:trace_id] = make_trace_id(trace_parent)
# Overwrite the request_id with the trace_id
req = ActionDispatch::Request.new env
req.request_id = insert_hyphens(env[:trace_id])
@app.call(env)
end
# ...
end
This middleware extracts the Trace ID from the W3C TraceContext compliant traceparent
header (saved in HTTP_TRACEPARENT
) and stores it in the request environment variables. If the header does not exist, it generates a new Trace ID in UUID format.
I also implemented a way to unify Rails' Request ID and Trace ID. If traceparent
exists, it is prioritized, so the mechanism is the same.
This allows the Trace ID to be used even in default log outputs, enabling consistent log output. The insert_hyphens
method has the function of inserting hyphens into the Trace ID to convert it to UUID format:
def insert_hyphens(trace_id)
trace_id = trace_id.dup.to_s
# Insert hyphens at each position (while checking string length)
[8, 13, 18, 23].each do |pos|
break if trace_id.length <= pos
trace_id.insert(pos, "-")
end
trace_id
end
This implementation is placed immediately after the ActionDispatch::RequestId
middleware to overwrite the request_id
generated by Rails. This utilizes the Rails request_id
mechanism explained in bisque's article Railsのログに含まれるrequest_idについてコードリーディングしたメモ(Notes on code reading about request_id included in Rails logs).
It turns out you can check the order of middleware by running the bin/rails middleware
command.
3. Implementing a Custom Log Formatter
Next, I customized SemanticLogger's formatter to output the Trace ID as a top-level field in the logs. This references the approach introduced in en30's article Rails on GKEでも理想の構造化ログを目指す(Aiming for Ideal Structured Logging even with Rails on GKE).
# lib/formatters/cloud_trace_log_json.rb
module Formatters
class CloudTraceLogJson < SemanticLogger::Formatters::Raw
# Default JSON time format is ISO8601
def initialize(time_format: :iso_8601, time_key: :timestamp, **args)
super(time_format: time_format, time_key: time_key, **args)
end
def traceparent
if log.named_tags && log.named_tags[:traceparent]
hash[:traceparent] = log.named_tags[:traceparent]
end
end
def trace
if log.named_tags && log.named_tags[:trace_id]
trace_id = log.named_tags[:trace_id]
elsif log.named_tags && log.named_tags[:request_id]
trace_id = log.named_tags[:request_id].gsub("-", "")
else
return
end
hash["logging.googleapis.com/trace"] = "projects/#{ENV["PROJECT_ID"]}/traces/#{trace_id}" if trace_id && !ENV["PROJECT_ID"].nil? && !ENV["PROJECT_ID"].empty?
end
# ...
end
end
With this formatter, when logs are output, the Trace ID is converted to the format required by Google Cloud Logging Structured logging, allowing related logs to be searched by Trace ID in the UI. In particular, it outputs to the Google Cloud Logging specific logging.googleapis.com/trace
field, including the PROJECT_ID
. This facilitates integration with Google Cloud's tracing features.
The reference article combined Lograge and google-cloud-logging (ruby).
4. Rails Configuration
For introduction, I changed some Rails settings. In particular, I configured settings for using SemanticLogger. Add the following to config/application.rb
:
TaggedLogging
Add tags to log entries. If you specify a hash for log_tags
, you can add named tags. This allows you to include Request ID and Trace ID in the logs.
# config/application.rb
config.log_tags = {
request_id: :request_id,
trace_id: ->(request) { request.env[:trace_id] },
traceparent: ->(request) { request.env[:traceparent] }
}
By setting log_tags
in this way, tags are added to the named_tags
field in SemanticLogger. This allows you to generate structured logs that include Request ID and Trace ID.
config/environments/production.rb
has a line config.log_tags = [ :request_id ]
, but this will overwrite the settings in config/application.rb
. You need to add similar settings to config/environments/production.rb
as well.
Middleware Placement Order
The insertion position of the middleware was an important consideration. By placing it just after the ActionDispatch::RequestId
middleware, the Request ID is overwritten immediately. If you just want to extract it first, insert_after 0
would be fine, but I wanted to maintain consistency with RequestId
, so I placed it just after ActionDispatch::RequestId
.
# config/application.rb
# config.middleware.insert_after 0, TraceMiddleware
config.middleware.insert_after ActionDispatch::RequestId, TraceMiddleware
This placement achieves the following processing flow:
- The
ActionDispatch::RequestId
middleware generates the defaultrequest_id
TraceMiddleware
extracts the Trace ID and overwritesrequest_id
if necessaryRack::Logger
outputsrequest_id
(or Trace ID if overwritten) to the log
SemanticLogger Configuration
Configure settings to use SemanticLogger and introduce a custom formatter. Add the following to config/application.rb
:
# config/application.rb
config.rails_semantic_logger.started = true
config.rails_semantic_logger.add_file_appender = false
# config.semantic_logger.add_appender(io: $stdout, formatter: :json)
config.semantic_logger.add_appender(io: $stdout, formatter: Formatters::CloudTraceLogJson.new)
If you don't want JSON format output in the development environment, it might be good to add this only to config/environments/production.rb
. (I'm sorry, I haven't tried it. I implemented it while confirming that it becomes JSON in the development environment...)
Viewing
In Cloud Logging, if you click on a field representing processing time, like "243 ms" (which has a trace symbol next to it), a menu will appear, and selecting "Show entries for this trace" allows you to extract and display only that specific trace.
Logs from the Rails application are output in JSON format.
When logs are output in JSON format, the "logging.googleapis.com/trace" field is not included in jsonPayload
but is output as a top-level field.
Bonus: Code for Deployment
Deployment using Terraform
When actually deploying to Cloud Run, I used Terraform to codify the infrastructure. It is placed in the terraform/environments/stg
directory. Create a .tfvars
file and specify the project ID and backend bucket name.
project_id = "project-id"
backend_bucket_name = "tfstate-bucket"
Then, just by running terraform apply -var-file=".tfvars"
, the Cloud Run environment will be built. However, building the image and registering secrets to Secret Manager need to be done manually.
Image Building
Specify the PROJECT_ID
and build the image using Cloud Build.
export PROJECT_ID="project-id"
gcloud builds submit . --project=$PROJECT_ID --config build_image.yaml
I'm not sure if this is the correct way to write it, but I'll put it as build_image.yaml.
Summary
With this implementation, the following were achieved:
- Support for Distributed Tracing - Propagation of trace information compliant with W3C TraceContext becomes possible
- Realization of Structured Logging - Output in JSON format makes searching and analysis easier
- Integration with Google Cloud Logging - Outputting Trace ID in Cloud Logging's format improves log filtering
- Improved Application Observability - Tracking across the entire request becomes possible
- Compatibility with Standard Logs - Maintains compatibility with existing log collection and analysis tools
Through the implementation of structured logging in Rails 8, I introduced a method for Trace ID integration utilizing SemanticLogger and custom middleware. This implementation contributes to the integration of logs and improvement of traceability in microservice architecture, and is useful for streamlining debugging and performance analysis.
As explained in the code reading by bisque, Rails' request_id
mechanism is realized by the cooperation of middleware, thread-local variables, and tagged loggers. In this implementation, while utilizing that mechanism, I aimed to integrate it with W3C TraceContext.
Part of this article was written by an LLM, and the LLM wrote, "As for future prospects, we are considering enhancing monitoring functions, such as collecting more detailed metrics and linking with alert settings. We are also considering integration with OpenTelemetry." I don't know if I will do such things.
As an individual human, I also thought it might be good to add fields by referring to Cloud Logging 構造化ログの特別な JSON フィールドまとめ(Summary of Special JSON Fields for Cloud Logging Structured Logs).
Reference Resources
- W3C Trace Context Specification
- Semantic Logger Official Documentation
- GitHub SemanticLogger
- GitHub RailsSemanticLogger
- Google Cloud Logging Documentation
- Rails on GKEでも理想の構造化ログを目指す(Aiming for Ideal Structured Logging even with Rails on GKE) last modified: 2021-04-28
- An article by en30 regarding structured logging implementation with Rails on GKE. Particularly helpful for how to integrate with Google Cloud Logging.
- Railsのログに含まれるrequest_idについてコードリーディングしたメモ(Notes on code reading about request_id included in Rails logs) 2022-09-28
- A detailed explanatory article by bisque on Rails'
request_id
. It explains in detail the internal implementation ofActionDispatch::RequestId
middleware andActiveSupport::TaggedLogging
.
- A detailed explanatory article by bisque on Rails'
- Fargate上のRailsからJSON形式でログをrequest_idと一緒に出力(Outputting logs in JSON format with request_id from Rails on Fargate) 2020-12-22
- logrageではRails.loggerのログ出力がJSON形式にならない問題(The issue where Rails.logger log output does not become JSON format with lograge) last modified: 2020-08-12
- tmimura39/rails_json_log_formatter.rb 2020-11-13
- Cloud Logging 構造化ログの特別な JSON フィールドまとめ(Summary of Special JSON Fields for Cloud Logging Structured Logs) 2023-10-23
- Cloud Logging Structured Logging
ディスカッション
コメント一覧
まだ、コメントがありません