Files

112 lines
8.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
orbit "git.yuntuo.hk/k2safe/orbit/sdk/go"
"math"
"runtime"
"sort"
"time"
)
// distribution 仅统计已逐项核验的任务;空集合百分位为null,单位毫秒。
type distribution struct {
Count int `json:"count"` // Count 统计分母。
P50 *float64 `json:"p50_ms"` // P50 最近秩中位数。
P95 *float64 `json:"p95_ms"` // P95 最近秩95百分位。
P99 *float64 `json:"p99_ms"` // P99 最近秩99百分位。
Max *float64 `json:"max_ms"` // Max 最大耗时。
}
// planReport 保存原操作身份;请求结果不明时只能按原键和原请求核查。
type planReport struct {
CalendarVersion string `json:"calendar_version,omitempty"` // CalendarVersion 创建回执中的时区快照标识,后续读取不得变化。
EffectiveAt time.Time `json:"effective_at"` // EffectiveAt 固定计划版本生效时间。
Index int `json:"index"` // Index 从零开始的计划序号。
ID string `json:"id,omitempty"` // ID 已取得的计划身份;空不证明创建未提交。
CreateKey string `json:"create_key"` // CreateKey 创建键,同时作为计划名称。
ResumeKey string `json:"resume_key,omitempty"` // ResumeKey 原恢复键。
ResumeRevision uint64 `json:"resume_revision,string"` // ResumeRevision 原恢复请求版本,零表示尚未发送。
Resumed bool `json:"resumed"` // Resumed 已收到且核对恢复回执。
Exhausted bool `json:"exhausted"` // Exhausted 已观察到固定版本无下个触发点和扫描工作。
PauseKey string `json:"pause_key,omitempty"` // PauseKey 最后发送的暂停键,仅明确版本冲突才换键。
PauseRevision uint64 `json:"pause_revision,string"` // PauseRevision 最后暂停请求的预期版本。
PauseConfirmed bool `json:"pause_confirmed"` // PauseConfirmed 已确认计划暂停;不取消已生成任务。
Occurrences int `json:"occurrences"` // Occurrences 已观察唯一触发点数。
Fired int `json:"fired"` // Fired 已关联唯一任务的单点触发数。
VerifiedSuccess int `json:"verified_success"` // VerifiedSuccess 完成任务/尝试/来源核对数。
}
// scheduleReport 是隔离环境有界样本,不作为生产容量或高可用承诺。
type scheduleReport struct {
RunID string `json:"run_id"` // RunID 计划、处理器和操作键的隔离身份。
GoVersion string `json:"go_version"` // GoVersion 实际编译工具链。
GOOS string `json:"goos"` // GOOS 运行系统。
GOARCH string `json:"goarch"` // GOARCH 运行架构。
StartedAt time.Time `json:"started_at"` // StartedAt 预检开始本机时间。
FinishedAt time.Time `json:"finished_at"` // FinishedAt 全部有界收尾完成本机时间。
Requests int `json:"requests_per_schedule"` // Requests 每计划预期触发数。
Schedules int `json:"schedules"` // Schedules 预期计划数。
Expected int `json:"expected_occurrences"` // Expected 总计划触发数,包含未观察的触发点。
Workers int `json:"workers"` // Workers 本进程独立WSS Worker数。
Capacity int `json:"capacity_per_worker"` // Capacity 每Worker并行槽数。
IntervalMS int64 `json:"interval_ms"` // IntervalMS 固定间隔毫秒。
StartDelayMS int64 `json:"start_delay_ms"` // StartDelayMS 创建/恢复的预留时间毫秒。
RunTimeoutMS int64 `json:"run_timeout_ms"` // RunTimeoutMS 整个测量截止毫秒。
PollIntervalMS int64 `json:"poll_interval_ms"` // PollIntervalMS 历史查询间隔毫秒。
HTTPTimeoutMS int64 `json:"http_timeout_ms"` // HTTPTimeoutMS 每HTTP请求截止毫秒。
Queue *orbit.Queue `json:"queue,omitempty"` // Queue 预检队列快照,只读配置。
ScheduleStart time.Time `json:"schedule_start"` // ScheduleStart 所有计划共同起点,包含边界。
ScheduleEnd time.Time `json:"schedule_end"` // ScheduleEnd 所有计划共同截止,排除边界。
Plans []planReport `json:"plans"` // Plans 已尝试创建的固定身份和收尾证据。
Occurrences int `json:"occurrences"` // Occurrences 已观察唯一触发数。
Fired int `json:"fired"` // Fired 单点生成且关联唯一任务数,不代表成功。
VerifiedSuccess int `json:"verified_success"` // VerifiedSuccess 持久化结果/唯一尝试/来源全部通过数。
Unobserved int `json:"unobserved"` // Unobserved 预期但未观察到的触发点数。
Unverified int `json:"unverified"` // Unverified 已触发但未核验成功的任务数。
HandlerCalls int `json:"handler_calls"` // HandlerCalls 通过输入核对的处理器调用总数。
DuplicateInvocations int `json:"duplicate_invocations"` // DuplicateInvocations 同一任务的额外调用数。
UnconfirmedInvocations int `json:"unconfirmed_invocations"` // UnconfirmedInvocations 未对应到已核验任务及尝试的调用数。
WorkerStarted uint64 `json:"worker_started"` // WorkerStarted SDK实际调用处理器数。
Reconnects uint64 `json:"worker_reconnects"` // Reconnects SDK连接重建次数。
Renewals uint64 `json:"worker_renewals_confirmed"` // Renewals 已确认租约续期次数。
TriggerLag distribution `json:"trigger_lag"` // TriggerLag 计划时间至任务受理数据库耗时。
QueueWait distribution `json:"queue_wait"` // QueueWait 任务受理至开始授权数据库耗时。
Execution distribution `json:"authorized_execution"` // Execution 授权至结果落库耗时,包含网络和事务。
Completion distribution `json:"completion"` // Completion 计划时间至结果落库耗时。
Errors map[string]int `json:"errors"` // Errors 有限分类,不含凭据或原异常正文。
Complete bool `json:"complete"` // Complete 全部计数、证据和收尾满足时为真。
}
func newReport(c config, runID string) scheduleReport {
return scheduleReport{RunID: runID, GoVersion: runtime.Version(), GOOS: runtime.GOOS, GOARCH: runtime.GOARCH, StartedAt: time.Now().UTC(), Requests: c.Requests, Schedules: c.Schedules, Expected: c.Requests * c.Schedules, Workers: c.Workers, Capacity: c.Capacity, IntervalMS: c.Interval.Milliseconds(), StartDelayMS: c.StartDelay.Milliseconds(), RunTimeoutMS: c.RunTimeout.Milliseconds(), PollIntervalMS: c.PollInterval.Milliseconds(), HTTPTimeoutMS: c.Timeout.Milliseconds(), Plans: []planReport{}, Errors: map[string]int{}}
}
func (r scheduleReport) finish() scheduleReport {
for code, n := range r.Errors {
if n == 0 {
delete(r.Errors, code)
}
}
r.FinishedAt = time.Now().UTC()
r.Unobserved = r.Expected - r.Occurrences
r.Unverified = r.Fired - r.VerifiedSuccess
plansReady := len(r.Plans) == r.Schedules
for _, p := range r.Plans {
plansReady = plansReady && p.Resumed && p.Exhausted && p.PauseConfirmed && p.VerifiedSuccess == r.Requests
}
r.Complete = r.Expected > 0 && plansReady && r.Occurrences == r.Expected && r.Fired == r.Expected && r.VerifiedSuccess == r.Expected && r.HandlerCalls == r.Expected && r.WorkerStarted == uint64(r.Expected) && r.DuplicateInvocations == 0 && r.UnconfirmedInvocations == 0 && len(r.Errors) == 0
return r
}
func distributionOf(values []time.Duration) distribution {
d := distribution{Count: len(values)}
if len(values) == 0 {
return d
}
sort.Slice(values, func(i, j int) bool { return values[i] < values[j] })
percentile := func(q float64) *float64 {
v := float64(values[int(math.Ceil(float64(len(values))*q))-1]) / float64(time.Millisecond)
return &v
}
d.P50, d.P95, d.P99, d.Max = percentile(.5), percentile(.95), percentile(.99), percentile(1)
return d
}