[インデックス 10866] ファイルの概要
このコミットは、Goプロジェクトのダッシュボードシステムにおける変更を扱っています。具体的には、ビルダがダッシュボードにコミット情報を送信する際に、コミット時刻を正確に含めるように修正されています。
コミット
commit 9b3799aa89449798c978c1c6d276a193d91a4701
Author: Andrew Gerrand <adg@golang.org>
Date: Mon Dec 19 16:57:03 2011 +1100
builder: send commit time to dashboard
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5489084
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9b3799aa89449798c978c1c6d276a193d91a4701
元コミット内容
builder: send commit time to dashboard
このコミットは、Goプロジェクトのビルダがダッシュボードにコミット情報を送信する際に、コミット時刻を含めるようにするものです。
変更の背景
Goプロジェクトでは、継続的インテグレーション(CI)とテスト結果を可視化するために「Goダッシュボード」と呼ばれるシステムが運用されていました。このダッシュボードは、様々なプラットフォームや環境でのビルドおよびテストのステータスをリアルタイムで表示し、開発者がコードの健全性を迅速に把握できるようにする重要なツールです。
以前のシステムでは、コミット情報の一部としてコミットハッシュ、親ハッシュ、作者、説明などは送信されていましたが、コミットが作成された正確な時刻がダッシュボードに送信されていませんでした。コミット時刻は、ビルドの履歴を追跡したり、特定の時点でのシステムの健全性を分析したり、パフォーマンスの傾向を把握したりする上で非常に重要なメタデータです。例えば、特定のコミットが原因でビルドが失敗し始めた場合、そのコミットがいつ行われたかを知ることで、問題の特定とデバッグが容易になります。
このコミットの背景には、ダッシュボードの機能強化と、より詳細なビルド履歴の追跡を可能にするという目的がありました。特に、TODO(adg): l.Date as int64 unix epoch secs in Time field
というコメントがコード内に存在していたことから、この機能は以前から計画されており、今回実装されたものと考えられます。
前提知識の解説
Goダッシュボード (Go Dashboard)
Goダッシュボードは、Go言語プロジェクトの公式な継続的インテグレーションおよびテスト結果の可視化システムです。世界中の様々な環境でGoのコードベースがビルドされ、テストされる様子をリアルタイムで表示します。これにより、開発者はGoのコードベースが常に健全な状態にあることを確認し、問題が発生した場合には迅速に特定して対処することができます。ダッシュボードは、各コミットに対するビルド結果(成功/失敗)、テスト結果、ベンチマーク結果などを集約して表示します。
ビルダ (Builder)
Goダッシュボードの文脈における「ビルダ」とは、Goのソースコードを特定の環境(OS、アーキテクチャ、コンパイラバージョンなど)でビルドし、テストを実行し、その結果をGoダッシュボードに報告する自動化されたエージェントまたはシステムを指します。これらのビルダは、Goプロジェクトの様々なリポジトリ(例: go
、tools
、blog
など)の変更を監視し、新しいコミットがプッシュされるたびに自動的にビルドとテストのサイクルを開始します。
Mercurial (Hg)
Mercurialは、Goプロジェクトが初期に採用していた分散型バージョン管理システム(DVCS)です。Gitと同様に、リポジトリのクローン、コミット、ブランチ、マージなどの機能を提供します。Goプロジェクトは後にGitに移行しましたが、このコミットが作成された2011年時点ではMercurialが主要なバージョン管理システムとして使用されていました。そのため、コミット情報(HgLog
)はMercurialのログ形式に準拠しています。
RFC3339
RFC3339は、インターネット標準のデータと時刻の形式を定義する仕様です。ISO 8601のプロファイルをベースにしており、人間が読みやすく、かつ機械が解析しやすい形式を提供します。例: 2011-12-19T16:57:03+11:00
。この形式は、異なるタイムゾーンやシステム間で時刻情報を正確に交換するために広く利用されます。
Unixエポックタイム (Unix Epoch Time)
Unixエポックタイムは、協定世界時(UTC)の1970年1月1日00:00:00からの経過秒数(またはミリ秒、マイクロ秒、ナノ秒)で時間を表現する方法です。これは、コンピュータシステムで時間を表現する際の標準的な方法の一つであり、タイムゾーンの影響を受けずに一意の時点を特定できる利点があります。このコミットでは、マイクロ秒単位で時間を表現しています。これは、より高い精度で時刻を記録するためです。
time.Parse
関数 (Go言語)
Go言語の標準ライブラリtime
パッケージに含まれるtime.Parse
関数は、指定されたレイアウト(フォーマット文字列)と時刻文字列からtime.Time
型の値を解析するために使用されます。この関数は、異なる形式の時刻文字列をGoの内部時刻表現に変換する際に不可欠です。
time.Time.Unix()
メソッド (Go言語)
time.Time
型のUnix()
メソッドは、その時刻をUnixエポックからの経過秒数(int64
型)として返します。このコミットでは、さらに* 1e6
(100万倍)することで、秒単位からマイクロ秒単位に変換しています。
技術的詳細
このコミットの主要な目的は、Goダッシュボードのビルダがコミット情報を送信する際に、コミット時刻を正確に含めることです。これを実現するために、以下の技術的な変更が加えられました。
-
時刻情報の取得と解析:
misc/dashboard/builder/http.go
内のpostCommit
関数が変更されました。この関数は、ビルダがダッシュボードにコミットデータをHTTP POSTリクエストで送信する役割を担っています。- 以前は、
HgLog
構造体から取得したl.Date
(コミット日付の文字列)を直接使用せず、TODO
コメントが存在していました。 - 変更後、
l.Date
文字列をtime.Parse(time.RFC3339, l.Date)
を使用してtime.Time
オブジェクトに解析するようになりました。これにより、RFC3339形式の文字列がGoの内部時刻表現に変換されます。 - 解析中にエラーが発生した場合(例: 日付文字列の形式が不正な場合)、
fmt.Errorf
を使用してエラーを返し、ログに記録されるように変更されました。これにより、不正な日付データがダッシュボードに送信されることを防ぎ、デバッグを容易にします。
-
時刻情報の形式変換と送信:
- 解析された
time.Time
オブジェクトt
から、t.Unix() * 1e6
という計算によってUnixエポックからの経過マイクロ秒数を取得しています。 - このマイクロ秒単位の数値が、
obj
マップの"Time"
フィールドの値としてダッシュボードに送信されるデータに追加されます。ダッシュボード側では、このマイクロ秒単位のタイムスタンプを解釈して、コミット時刻として表示・利用します。 1e6
を乗算しているのは、Goダッシュボードが時刻情報をマイクロ秒単位で期待しているためです。これは、より高精度な時刻情報が必要とされる場合に用いられる一般的な手法です。
- 解析された
-
エラーハンドリングの改善:
postCommit
関数の戻り値がbool
(成功/失敗)からerror
型に変更されました。これにより、関数呼び出し元は具体的なエラー情報を取得し、より詳細なエラー処理を行うことができるようになりました。misc/dashboard/builder/main.go
内のaddCommit
関数では、postCommit
の戻り値がerror
になったことに合わせて、エラーチェックとログ出力のロジックが修正されました。これにより、ダッシュボードへのコミット送信が失敗した場合に、その原因がより明確にログに記録されるようになります。
-
XMLログテンプレートの更新:
misc/dashboard/builder/main.go
内のxmlLogTemplate
が更新され、<date>{date}</date>
が<date>{date|rfc3339date}</date>
に変更されました。これは、Mercurialのログから日付を取得する際に、その日付がRFC3339形式であることを明示的に指定するためのテンプレート構文の変更です。これにより、HgLog.Date
フィールドが確実にRFC3339形式で提供されるようになり、time.Parse
での解析が安定します。
これらの変更により、Goダッシュボードは各コミットの正確な時刻情報を取得できるようになり、ビルド履歴の追跡と分析の精度が向上しました。
コアとなるコードの変更箇所
misc/dashboard/builder/http.go
--- a/misc/dashboard/builder/http.go
+++ b/misc/dashboard/builder/http.go
@@ -8,10 +8,12 @@ import (
"bytes"
"encoding/json"
"errors"
+ "fmt"
"io"
"log"
"net/http"
"net/url"
+ "time"
)
type obj map[string]interface{}
@@ -147,20 +149,19 @@ func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) erro
*/
}
-func postCommit(key, pkg string, l *HgLog) bool {
- err := dash("POST", "commit", url.Values{"key": {key}}, obj{
+func postCommit(key, pkg string, l *HgLog) error {
+ t, err := time.Parse(time.RFC3339, l.Date)
+ if err != nil {
+ return fmt.Errorf("parsing %q: %v", l.Date, t)
+ }
+ return dash("POST", "commit", url.Values{"key": {key}}, obj{
"PackagePath": pkg,
"Hash": l.Hash,
"ParentHash": l.Parent,
- // TODO(adg): l.Date as int64 unix epoch secs in Time field
- "User": l.Author,
- "Desc": l.Desc,
+ "Time": t.Unix() * 1e6, // in microseconds, yuck!
+ "User": l.Author,
+ "Desc": l.Desc,
}, nil)
- if err != nil {
- log.Printf("failed to add %s to dashboard: %v", key, err)
- return false
- }
- return true
}
func dashboardCommit(pkg, hash string) bool {
misc/dashboard/builder/main.go
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -536,7 +536,7 @@ const xmlLogTemplate = `
<hash>{node|escape}</hash>
<parent>{parent|escape}</parent>
<author>{author|escape}</author>
- <date>{date}</date>
+ <date>{date|rfc3339date}</date>
<desc>{desc|escape}</desc>
</log>
`
@@ -652,7 +652,11 @@ func addCommit(pkg, hash, key string) bool {
}
// Create commit.
- return postCommit(key, pkg, l)
+ if err := postCommit(key, pkg, l); err != nil {
+ log.Printf("failed to add %s to dashboard: %v", key, err)
+ return false
+ }
+ return true
}
// fullHash returns the full hash for the given Mercurial revision.
コアとなるコードの解説
misc/dashboard/builder/http.go
の変更点
-
インポートの追加:
"fmt"
: フォーマットされたI/O操作(特にエラーメッセージの生成)のために追加されました。"time"
: 日付と時刻の解析および操作のために追加されました。
-
postCommit
関数のシグネチャ変更:func postCommit(key, pkg string, l *HgLog) bool
からfunc postCommit(key, pkg string, l *HgLog) error
に変更されました。これにより、関数が成功/失敗のブール値ではなく、具体的なエラー情報を返すことができるようになり、呼び出し元でのエラーハンドリングが改善されます。
-
コミット時刻の解析と変換:
t, err := time.Parse(time.RFC3339, l.Date)
:l.Date
(HgLog
構造体から取得されるコミット日付の文字列)をRFC3339形式として解析し、time.Time
オブジェクトt
に変換します。time.RFC3339
は、Go言語のtime
パッケージが提供するRFC3339形式のレイアウト定数です。if err != nil { return fmt.Errorf("parsing %q: %v", l.Date, t) }
: 日付文字列の解析に失敗した場合、fmt.Errorf
を使用してエラーメッセージを生成し、それを返します。これにより、不正な日付形式が原因でダッシュボードへの送信が失敗した場合に、具体的なエラー内容がログに記録されます。"Time": t.Unix() * 1e6
: 解析されたtime.Time
オブジェクトt
のUnixエポックからの経過秒数をUnix()
メソッドで取得し、それに1e6
(100万)を乗算してマイクロ秒単位に変換しています。このマイクロ秒単位のタイムスタンプが、ダッシュボードに送信されるコミットデータの"Time"
フィールドとして設定されます。コメント// in microseconds, yuck!
は、マイクロ秒単位での表現が一般的ではないことへの開発者のユーモラスな言及です。
-
エラーハンドリングの簡素化:
- 以前のバージョンでは、
dash
関数の呼び出し後にエラーが発生した場合、log.Printf
でエラーをログに出力し、false
を返していました。 - 新しいバージョンでは、
postCommit
関数自体がエラーを返すようになったため、このエラーハンドリングロジックは削除され、dash
関数の戻り値(error
型)が直接返されるようになりました。これにより、エラー処理の責任が呼び出し元に委譲され、関数の責務が明確になります。
- 以前のバージョンでは、
misc/dashboard/builder/main.go
の変更点
-
xmlLogTemplate
の変更:const xmlLogTemplate = ...
内の<date>{date}</date>
が<date>{date|rfc3339date}</date>
に変更されました。これは、Mercurialのログから日付情報を抽出する際に、その日付がRFC3339形式であることを明示的に指定するためのテンプレート構文です。これにより、HgLog.Date
フィールドに格納される日付文字列が、http.go
のpostCommit
関数で期待されるRFC3339形式であることが保証されます。
-
addCommit
関数のエラーハンドリング更新:if err := postCommit(key, pkg, l); err != nil { ... }
:postCommit
関数がerror
を返すようになったため、その戻り値をerr
変数で受け取り、エラーが発生したかどうかをチェックするようになりました。- エラーが発生した場合、
log.Printf
でエラーメッセージをログに出力し、false
を返します。これは、postCommit
がbool
を返していた時と同じ最終的な動作ですが、postCommit
から返される具体的なエラー情報に基づいてログメッセージを生成できるため、デバッグが容易になります。
これらの変更により、Goダッシュボードのビルダは、コミットの正確な時刻情報をRFC3339形式で解析し、Unixエポックからのマイクロ秒単位のタイムスタンプとしてダッシュボードに送信できるようになりました。これにより、ダッシュボードのデータ精度と分析能力が向上します。
関連リンク
- Go言語公式ウェブサイト: https://go.dev/
- Goダッシュボード (現在のGo CI/CDシステム): https://build.go.dev/ (このコミット当時のダッシュボードとは異なる可能性がありますが、概念は同じです)
- RFC 3339 - Date and Time on the Internet: Timestamps: https://datatracker.ietf.org/doc/html/rfc3339
- Unix時間 - Wikipedia: https://ja.wikipedia.org/wiki/Unix%E6%99%82%E9%96%93
参考にした情報源リンク
- Go言語の公式ドキュメント(
time
パッケージ): https://pkg.go.dev/time - Mercurial公式ドキュメント: https://www.mercurial-scm.org/
- Goプロジェクトの歴史に関する情報(MercurialからGitへの移行など)は、Goのブログやメーリングリストのアーカイブから得られる可能性があります。