Help us shape the future of Go! Take the 2026 Go Developer Survey

analysis

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package analysis は1回の走行(収集グループ)について、種類をまたいだ集計を出す。

alp / slow log / pprof は「サーバーの中で何が遅いか」を教えてくれるが、 「ベンチの利用者が何をしていて、得点がいつ・どこで生まれたか」は教えてくれない。 ここでは httplog の生ログと dbquery の結果を時刻で揃え、次の3つを出す。

  • 時系列: 一定幅の区間ごとのリクエスト数・エラー・応答時間と、SQL で取った系列(得点・母集団)
  • ライフサイクル: エンティティ(利用者・ライドなど)が状態を順に進む様子。区間ごとの到達数と所要時間
  • 内訳: SQL の結果表(配信者別の得点など)

回ごとの知識(どの SQL が得点か、どの状態を順に進むか)は analysis.yml と dbquery.yml に置き、 このパッケージには持たない。

Index

Constants

This section is empty.

Variables

View Source
var Types = []string{"httplog", "dbquery", "score"}

Types は analyze が読む収集タイプ。

Functions

func LatestGroup added in v0.2.1

func LatestGroup(api *client.Client) (string, error)

LatestGroup は最新の収集グループを返す(client.Latest。pprotein-cli の latest と同じ)。

func NormalizeUnixTime

func NormalizeUnixTime(x float64) float64

NormalizeUnixTime は秒・ミリ秒・マイクロ秒の unix 時刻を秒に揃える。 SQL 側で単位を揃えなくてよいように、桁で判定する。

func RenderDiffMarkdown added in v0.3.0

func RenderDiffMarkdown(w io.Writer, d *Diff)

RenderDiffMarkdown は Diff を Markdown にする。

func RenderEndpointsMarkdown added in v0.5.2

func RenderEndpointsMarkdown(w io.Writer, rep *Report)

RenderEndpointsMarkdown は走行全体のエンドポイント別の集計を表にする(CLI)。

func RenderMarkdown

func RenderMarkdown(w io.Writer, rep *Report)

RenderMarkdown は Report をエージェントの文脈にそのまま貼れる Markdown にする。

func RenderRunsMarkdown added in v0.4.0

func RenderRunsMarkdown(w io.Writer, resp *RunsResponse)

RenderRunsMarkdown は走行を1行ずつ並べた表にする。 系列は役割(score / driver / penalty)が付いたものを優先し、無ければ先頭から最大6本。

func RenderSessionMarkdown added in v0.5.1

func RenderSessionMarkdown(w io.Writer, d *SessionDetail)

func RenderSessionsMarkdown added in v0.5.1

func RenderSessionsMarkdown(w io.Writer, s *SessionsResponse)

func RenderTransitionsMarkdown added in v0.5.1

func RenderTransitionsMarkdown(w io.Writer, t *TransitionsResponse)

Types

type BreakdownDef

type BreakdownDef struct {
	Name  string `yaml:"name"`
	Query string `yaml:"query"`
}

BreakdownDef は dbquery の結果表をそのまま出す。value 列があれば構成比を付ける。

type BreakdownDiff added in v0.3.0

type BreakdownDiff struct {
	Name string
	// Keyed は key / value 列があって行ごとに突き合わせられたか。false なら行数だけ比べる。
	Keyed      bool
	RowsBefore *int `json:",omitempty"`
	RowsAfter  *int `json:",omitempty"`
	// Top1 / Top3 は上位1件・3件の構成比(偏りの変化を見る)。
	Top1Before float64
	Top1After  float64
	Top3Before float64
	Top3After  float64
	// NewInTop は after で上位に入り、before の上位に無かった key。
	NewInTop []string `json:",omitempty"`
	Rows     []KeyDiff
}

type BreakdownResult

type BreakdownResult struct {
	Name    string
	Columns []string
	Rows    [][]string
	// Share は value 列があるときの構成比(Rows と同じ並び)。
	Share     []float64 `json:",omitempty"`
	TotalRows int
	Error     string `json:",omitempty"`
}

type Bucket

type Bucket struct {
	// Offset は区間の開始(Origin からの秒)。
	Offset   int `json:"OffsetSec"`
	Requests int
	S2xx     int
	S3xx     int
	S4xx     int
	S5xx     int
	// Canceled は 499(クライアントが待ちきれずに切った)。S4xx には入れない。
	Canceled  int                `json:"S499"`
	P50       float64            `json:"P50Sec"`
	P99       float64            `json:"P99Sec"`
	Endpoints map[string]int     `json:",omitempty"`
	Series    map[string]float64 `json:",omitempty"`
}

type Config

type Config struct {
	// Bucket は時系列の区間幅(秒)。
	Bucket int `yaml:"bucket"`
	// Top は内訳・エンドポイント表に出す件数。
	Top int `yaml:"top"`

	HTTPLog HTTPLogConfig `yaml:"httplog"`

	Series     []SeriesDef    `yaml:"series"`
	Breakdowns []BreakdownDef `yaml:"breakdowns"`
	Lifecycles []LifecycleDef `yaml:"lifecycles"`
}

Config は analysis.yml。

func ParseConfig

func ParseConfig(raw []byte) (*Config, error)

type ConfigHash added in v0.3.0

type ConfigHash struct {
	// Analysis は集計したときの analysis.yml。
	Analysis string
	// DBQuery は dbquery を実行したときの dbquery.yml(dbquery の結果に記録されている)。
	DBQuery string
}

ConfigHash の各値は設定ファイルの中身の SHA-256 の先頭12桁。取れなかったものは空。

type Diff added in v0.3.0

type Diff struct {
	Before string
	After  string
	Score  *score.Diff `json:",omitempty"`
	Commit *git.Diff   `json:",omitempty"`
	// Warnings は比較の前提が崩れているもの(設定の食い違い、片方の警告など)。
	Warnings []string `json:",omitempty"`

	Series     []SeriesDiff
	Requests   []MetricDiff
	Endpoints  []EndpointDiff
	Lifecycles []LifecycleDiff
	Breakdowns []BreakdownDiff
}

func Compare added in v0.3.0

func Compare(before, after *Report, top int) *Diff

Compare は before → after の差を出す。top はエンドポイント構成比の行数の上限(0 なら全部)。

type EndpointDiff added in v0.3.0

type EndpointDiff struct {
	Key         string
	CountBefore int
	CountAfter  int
	ShareBefore float64
	ShareAfter  float64
}

type EndpointSeries added in v0.5.2

type EndpointSeries struct {
	Key    string
	Count  []int
	P50Sec []float64
	P99Sec []float64
	Errors []int
	S499   []int
}

type EndpointShare added in v0.4.0

type EndpointShare struct {
	Key   string
	Count int
	// Share は全リクエストに占める割合(0〜1)。
	Share float64
}

type EndpointStat added in v0.5.2

type EndpointStat struct {
	Key   string
	Count int
	// Share は走行全体のリクエストに占める割合(0〜1)。
	Share float64
	P50   float64 `json:"P50Sec"`
	P99   float64 `json:"P99Sec"`
	// Sum は応答時間の合計(alp の SUM と同じもの)。
	Sum    float64 `json:"SumSec"`
	Errors int     // 4xx + 5xx(499 を除く)
	S499   int
}

type EndpointTimeline added in v0.5.2

type EndpointTimeline struct {
	GroupId   string
	BucketSec int
	OffsetSec []int
	// Endpoints は件数の多い順。値の並びは OffsetSec と同じ。
	Endpoints []EndpointSeries
}

type HTTPLogConfig

type HTTPLogConfig struct {
	// Label は使う httplog の Label。空なら同じ収集の httplog を全部まとめる。
	Label string `yaml:"label"`
	// TimeKey は時刻の LTSV キー。msec(nginx の $msec)か time($time_local)。
	// 既定は msec で、行に無ければ time を見る。
	TimeKey string `yaml:"time_key"`
	// EntityKey はライフサイクルの識別子に使う LTSV キー(セッション cookie など)。
	EntityKey string `yaml:"entity_key"`
}

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler は /api/analysis を提供する。 trend と同じく自分自身の API から材料を読むので、収集タイプの実装には手を入れない。

func NewHandler

func NewHandler(selfURL string, store storage.Storage) (*Handler, error)

func (*Handler) RegisterHandlers

func (h *Handler) RegisterHandlers(g *echo.Group)

type Input

type Input struct {
	GroupId string
	// Origin は時系列の 0 秒(unix 秒)。GroupId の時刻 = 収集開始 = initialize の直後。
	Origin   float64
	Requests []Request
	// SkippedLines は時刻が読めず捨てた LTSV の行数。
	SkippedLines int
	Queries      map[string]*dbquery.QueryResult
	// Warnings は材料を集める段階で見つかった問題(収集中・収集失敗のエントリなど)。
	Warnings []string

	// Score はこの収集に紐づいたベンチのスコア。無ければ nil。
	Score *score.Brief
	// ConfigHash は集計に使った設定のハッシュ。走行間の比較で定義の食い違いを見つけるのに使う。
	ConfigHash ConfigHash
	// Commit は httplog に記録されたアプリのコミット。無ければ nil。
	Commit *git.Commit
}

Input は1回の収集から集めた材料。

func Load

func Load(api *client.Client, cfg *Config, groupId string) (*Input, error)

Load は収集グループの httplog(生ログ)と dbquery の結果を集める。

type KeyDiff added in v0.3.0

type KeyDiff struct {
	Key    string
	Before *float64 `json:",omitempty"`
	After  *float64 `json:",omitempty"`
}

type LifecycleDef

type LifecycleDef struct {
	Name string `yaml:"name"`
	// Source は httplog(識別子 = httplog.entity_key、状態 = "METHOD 正規化済みURI")か、
	// query:<dbquery の name>(列 entity, state, t)。
	Source string `yaml:"source"`
	Steps  []Step `yaml:"steps"`
}

LifecycleDef はエンティティが順に進む状態の列。

type LifecycleDiff added in v0.3.0

type LifecycleDiff struct {
	Name           string
	EntitiesBefore *int `json:",omitempty"`
	EntitiesAfter  *int `json:",omitempty"`
	Steps          []StepDiff
}

type LifecycleResult

type LifecycleResult struct {
	Name string
	// Entities は最初の状態に到達したエンティティの数。
	Entities int
	Steps    []StepResult
	Error    string `json:",omitempty"`
}

type LifecycleSteps added in v0.5.1

type LifecycleSteps struct {
	Name  string
	Steps []string
}

type LifecycleSummary added in v0.4.0

type LifecycleSummary struct {
	Name     string
	Entities int
	// Reached は状態ごとの到達数(Steps の順)。
	Steps []StepReached
}

type MetricDiff added in v0.3.0

type MetricDiff struct {
	Name   string
	Before float64
	After  float64
}

type Normalizer

type Normalizer struct {
	// contains filtered or unexported fields
}

Normalizer は alp.yml の matching_groups で URI をまとめる。 alp と同じく、クエリ文字列を落としてから先頭から順に当て、最初に当たった正規表現を返す。

func NewNormalizer

func NewNormalizer(alpConfig []byte) (*Normalizer, error)

func (*Normalizer) Normalize

func (n *Normalizer) Normalize(uri string) string

type Quantiles

type Quantiles struct {
	P50 float64
	P90 float64
	P99 float64
	Max float64
}

type Report

type Report struct {
	GroupId    string
	Origin     time.Time
	Bucket     int          `json:"BucketSec"`
	Warnings   []string     `json:",omitempty"`
	Score      *score.Brief `json:",omitempty"`
	Commit     *git.Commit  `json:",omitempty"`
	ConfigHash ConfigHash

	// Totals は走行全体のリクエストの集計(収集開始より後のもの)。
	Totals Totals
	// SeriesStats は時系列の系列ごとの集計(累積の系列は除く)。
	SeriesStats []SeriesStat
	// EndpointStats は全エンドポイントの走行全体の集計(件数の多い順)。
	EndpointStats []EndpointStat

	Timeline   Timeline
	Lifecycles []LifecycleResult
	Breakdowns []BreakdownResult
}

JSON のキーには単位を付ける(…Sec は秒、Rate… / Share は 0〜1 の割合)。 AI がドキュメントを読まずに解釈できるようにするため。

func Analyze

func Analyze(cfg *Config, in *Input) *Report

Analyze は材料から Report を作る。

type Request

type Request struct {
	// T は unix 秒(小数あり)。
	T        float64
	Method   string
	Endpoint string // matching_groups でまとめた URI
	// URI はまとめる前の URI(クエリ文字列を含む)、Host は vhost(配信者のサブドメインなど)。
	// セッションの導線を1件ずつ見るときに使う。
	URI     string
	Host    string
	Status  int
	ReqTime float64
	Entity  string
}

Request は LTSV 1行ぶん。

func ParseLTSV

func ParseLTSV(data []byte, n *Normalizer, timeKey, entityKey string) ([]Request, int)

ParseLTSV は nginx の LTSV ログを読む。時刻が読めない行は飛ばし、その件数を返す。

func (*Request) Key

func (r *Request) Key() string

Key はライフサイクルの状態に使う文字列。

type RequestSummary added in v0.4.0

type RequestSummary struct {
	Requests     int
	S4xx         int
	S5xx         int
	S499         int
	P50          float64 `json:"P50Sec"`
	P99          float64 `json:"P99Sec"`
	PeakRequests int
}

type RunSummary added in v0.4.0

type RunSummary struct {
	GroupId    string
	Score      *score.Brief `json:",omitempty"`
	Commit     *git.Commit  `json:",omitempty"`
	ConfigHash ConfigHash
	// Warnings は収集中・失敗のエントリなど、この走行の集計が欠けている理由。
	Warnings []string `json:",omitempty"`

	Requests   RequestSummary
	Series     []SeriesStat
	Lifecycles []LifecycleSummary
	// TopEndpoints は件数の多いエンドポイント(構成の変化を追う)。
	TopEndpoints []EndpointShare
	// Endpoints は全エンドポイントの集計。?endpoints=1 のときだけ入る(走行数 × エンドポイント数で大きくなるため)。
	Endpoints []EndpointStat `json:",omitempty"`
}

func Summarize added in v0.4.0

func Summarize(rep *Report) RunSummary

Summarize は Report から推移を見るのに要る値だけを抜き出す。

type RunsResponse added in v0.4.0

type RunsResponse struct {
	// Runs は古い順(グラフの左から右)。
	Runs []RunSummary
}

type SeriesDef

type SeriesDef struct {
	Name  string `yaml:"name"`
	Query string `yaml:"query"`
	// Role は系列の役割。score(得点の項)/ driver(得点を生む母数)/ penalty(得点を減らすもの)。
	// 出力に載るだけで集計は変わらない。AI や比較で「どれが得点か」を設定から引けるようにする。
	Role string `yaml:"role"`
	// Agg は区間内の集約方法。sum(既定)/ count / max / last。
	Agg string `yaml:"agg"`
	// Cumulative を true にすると区間ごとの値に加えて累積を出す(得点の積み上がりを見る)。
	Cumulative bool `yaml:"cumulative"`
}

SeriesDef は dbquery の結果から作る時系列。 クエリの列: t(unix 時刻。秒/ミリ秒/マイクロ秒は桁で判定)、value(省略時は件数)、 series(任意。あれば値ごとに別系列 "<name>:<series>" になる)。

type SeriesDiff added in v0.3.0

type SeriesDiff struct {
	Name      string
	Role      string   `json:",omitempty"`
	Before    *float64 `json:",omitempty"`
	After     *float64 `json:",omitempty"`
	T50Before *int     `json:"T50SecBefore,omitempty"`
	T50After  *int     `json:"T50SecAfter,omitempty"`
	T90Before *int     `json:"T90SecBefore,omitempty"`
	T90After  *int     `json:"T90SecAfter,omitempty"`
}

SeriesDiff は系列1本。片方にしか無い系列は Before / After の片方が nil。

type SeriesStat added in v0.3.0

type SeriesStat struct {
	Name string
	// Role は系列の役割(score: 得点の項 / driver: 得点を生む母数 / penalty: 得点を減らすもの)。未設定なら空。
	Role string `json:",omitempty"`
	// Query は元の dbquery の name。ライフサイクルの開始・完了数は lifecycle:<name>。
	Query string `json:",omitempty"`
	// Agg は区間内の集約方法(sum / count / max / last)。ライフサイクルの開始・完了数は count。
	Agg string
	// Total は走行全体の値。sum / count は合計、max は最大、last は最後の区間の値。
	Total float64
	// T50 / T90 は sum / count の系列が合計の 50% / 90% に達した区間の終わり(収集開始からの秒)。
	// 得点が前倒しで積み上がるようになったか(終盤の失速が直ったか)を見る。
	T50 *int `json:"T50Sec,omitempty"`
	T90 *int `json:"T90Sec,omitempty"`
}

type SessionDetail added in v0.5.1

type SessionDetail struct {
	GroupId  string
	Summary  SessionSummary
	Requests []SessionRequest
}

type SessionReach added in v0.5.1

type SessionReach struct {
	Name string
	// Reached は順に到達した状態の数(0 ならこのライフサイクルに入っていない)。
	Reached int
	// LastStep は最後に到達した状態の名前。
	LastStep string `json:",omitempty"`
}

type SessionRequest added in v0.5.1

type SessionRequest struct {
	OffsetSec  float64
	Method     string
	Endpoint   string
	URI        string
	Host       string `json:",omitempty"`
	Status     int
	ReqTimeSec float64
	// Steps はこの要求で進んだライフサイクルの状態("viewer:enter" の形)。
	Steps []string `json:",omitempty"`
}

type SessionSummary added in v0.5.1

type SessionSummary struct {
	// ID は開始時刻順の連番(s001, s002, ...)。同じ材料なら同じ番号になる。
	ID string
	// Hosts は訪れた vhost(多い順、最大3件)。ISUCON13 なら配信者のサブドメイン。
	Hosts      []string `json:",omitempty"`
	StartSec   float64
	EndSec     float64
	Requests   int
	Errors     int // 4xx + 5xx(499 を除く)
	S499       int
	MaxReqSec  float64
	Lifecycles []SessionReach
}

type SessionsResponse added in v0.5.1

type SessionsResponse struct {
	GroupId string
	// Lifecycles は source: httplog のライフサイクルと状態名(Sessions[].Lifecycles の並び)。
	Lifecycles []LifecycleSteps
	// Total はセッションの総数(lifecycle で絞る前)、Matched は lifecycle で絞ったあとの数(limit で切る前)。
	Total    int
	Matched  int
	Sessions []SessionSummary
}

type Step

type Step struct {
	Name string `yaml:"name"`
	// Match は状態に当てる正規表現。
	Match string `yaml:"match"`
	// contains filtered or unexported fields
}

type StepDiff added in v0.3.0

type StepDiff struct {
	Name   string
	Before *StepResult `json:",omitempty"`
	After  *StepResult `json:",omitempty"`
}

type StepReached added in v0.4.0

type StepReached struct {
	Name    string
	Reached int
}

type StepResult

type StepResult struct {
	Name string
	// Reached はこの状態まで順に到達したエンティティの数。
	Reached int
	// Rate は1つ前の状態に到達したうち、この状態まで進んだ割合。
	Rate float64 `json:"RateFromPrev"`
	// StoppedHere はこの状態を最後に先へ進まなかったエンティティの数(離脱・途中で走行終了の両方を含む)。
	StoppedHere int
	// PerEntity は到達したエンティティ1つあたり、この状態のイベントが何回あったか(順序を問わない)。
	PerEntity float64
	// FromPrev は1つ前の状態からの所要秒数。
	FromPrev *Quantiles `json:"FromPrevSec,omitempty"`
}

type Timeline

type Timeline struct {
	// Series は Buckets[].Series に入っている系列名(表示順)。
	Series []string
	// Endpoints は件数の多いエンドポイント(Buckets[].Endpoints のキー)。
	Endpoints []string
	Buckets   []Bucket
}

func (Timeline) MarshalJSON added in v0.4.0

func (tl Timeline) MarshalJSON() ([]byte, error)

func (*Timeline) UnmarshalJSON added in v0.4.0

func (tl *Timeline) UnmarshalJSON(data []byte) error

type Totals added in v0.3.0

type Totals struct {
	Requests int
	S2xx     int
	S3xx     int
	S4xx     int
	S5xx     int
	Canceled int     `json:"S499"`
	P50      float64 `json:"P50Sec"`
	P99      float64 `json:"P99Sec"`
	// PeakRequests は区間あたりの最大リクエスト数、PeakOffset はその区間の開始。
	PeakRequests int
	PeakOffset   int `json:"PeakOffsetSec"`
	// Endpoints は全エンドポイントの件数(Timeline.Endpoints と違って上位に絞らない)。
	Endpoints map[string]int `json:",omitempty"`
}

type Transition added in v0.5.1

type Transition struct {
	From  string
	To    string
	Count int
	// ShareOfFrom は From の次の要求のうち、To が占める割合(0〜1)。
	ShareOfFrom float64
	// GapP50Sec は From から To までの間隔の中央値。
	GapP50Sec float64
}

Transition は「From の次に To を叩いた」回数。From が (開始) なら最初の要求、To が (終了) なら最後の要求。

type TransitionsResponse added in v0.5.1

type TransitionsResponse struct {
	GroupId   string
	Lifecycle string `json:",omitempty"`
	// Sessions は集計したセッションの数。
	Sessions    int
	Transitions []Transition
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL