Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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プロジェクトの様々なリポジトリ(例: gotoolsblogなど)の変更を監視し、新しいコミットがプッシュされるたびに自動的にビルドとテストのサイクルを開始します。

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ダッシュボードのビルダがコミット情報を送信する際に、コミット時刻を正確に含めることです。これを実現するために、以下の技術的な変更が加えられました。

  1. 時刻情報の取得と解析:

    • 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を使用してエラーを返し、ログに記録されるように変更されました。これにより、不正な日付データがダッシュボードに送信されることを防ぎ、デバッグを容易にします。
  2. 時刻情報の形式変換と送信:

    • 解析されたtime.Timeオブジェクトtから、t.Unix() * 1e6という計算によってUnixエポックからの経過マイクロ秒数を取得しています。
    • このマイクロ秒単位の数値が、objマップの"Time"フィールドの値としてダッシュボードに送信されるデータに追加されます。ダッシュボード側では、このマイクロ秒単位のタイムスタンプを解釈して、コミット時刻として表示・利用します。
    • 1e6を乗算しているのは、Goダッシュボードが時刻情報をマイクロ秒単位で期待しているためです。これは、より高精度な時刻情報が必要とされる場合に用いられる一般的な手法です。
  3. エラーハンドリングの改善:

    • postCommit関数の戻り値がbool(成功/失敗)からerror型に変更されました。これにより、関数呼び出し元は具体的なエラー情報を取得し、より詳細なエラー処理を行うことができるようになりました。
    • misc/dashboard/builder/main.go 内の addCommit 関数では、postCommitの戻り値がerrorになったことに合わせて、エラーチェックとログ出力のロジックが修正されました。これにより、ダッシュボードへのコミット送信が失敗した場合に、その原因がより明確にログに記録されるようになります。
  4. 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 の変更点

  1. インポートの追加:

    • "fmt": フォーマットされたI/O操作(特にエラーメッセージの生成)のために追加されました。
    • "time": 日付と時刻の解析および操作のために追加されました。
  2. postCommit 関数のシグネチャ変更:

    • func postCommit(key, pkg string, l *HgLog) bool から func postCommit(key, pkg string, l *HgLog) error に変更されました。これにより、関数が成功/失敗のブール値ではなく、具体的なエラー情報を返すことができるようになり、呼び出し元でのエラーハンドリングが改善されます。
  3. コミット時刻の解析と変換:

    • t, err := time.Parse(time.RFC3339, l.Date): l.DateHgLog構造体から取得されるコミット日付の文字列)を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!は、マイクロ秒単位での表現が一般的ではないことへの開発者のユーモラスな言及です。
  4. エラーハンドリングの簡素化:

    • 以前のバージョンでは、dash関数の呼び出し後にエラーが発生した場合、log.Printfでエラーをログに出力し、falseを返していました。
    • 新しいバージョンでは、postCommit関数自体がエラーを返すようになったため、このエラーハンドリングロジックは削除され、dash関数の戻り値(error型)が直接返されるようになりました。これにより、エラー処理の責任が呼び出し元に委譲され、関数の責務が明確になります。

misc/dashboard/builder/main.go の変更点

  1. xmlLogTemplate の変更:

    • const xmlLogTemplate = ... 内の <date>{date}</date><date>{date|rfc3339date}</date> に変更されました。これは、Mercurialのログから日付情報を抽出する際に、その日付がRFC3339形式であることを明示的に指定するためのテンプレート構文です。これにより、HgLog.Dateフィールドに格納される日付文字列が、http.gopostCommit関数で期待されるRFC3339形式であることが保証されます。
  2. addCommit 関数のエラーハンドリング更新:

    • if err := postCommit(key, pkg, l); err != nil { ... }: postCommit関数がerrorを返すようになったため、その戻り値をerr変数で受け取り、エラーが発生したかどうかをチェックするようになりました。
    • エラーが発生した場合、log.Printfでエラーメッセージをログに出力し、falseを返します。これは、postCommitboolを返していた時と同じ最終的な動作ですが、postCommitから返される具体的なエラー情報に基づいてログメッセージを生成できるため、デバッグが容易になります。

これらの変更により、Goダッシュボードのビルダは、コミットの正確な時刻情報をRFC3339形式で解析し、Unixエポックからのマイクロ秒単位のタイムスタンプとしてダッシュボードに送信できるようになりました。これにより、ダッシュボードのデータ精度と分析能力が向上します。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(timeパッケージ): https://pkg.go.dev/time
  • Mercurial公式ドキュメント: https://www.mercurial-scm.org/
  • Goプロジェクトの歴史に関する情報(MercurialからGitへの移行など)は、Goのブログやメーリングリストのアーカイブから得られる可能性があります。