ワンクリックで
arc-go-gin-ssr-fmt-tracing
Add low-cost fmt/time or log.Printf timing probes to Go Gin SSR request paths.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Add low-cost fmt/time or log.Printf timing probes to Go Gin SSR request paths.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | arc:go-gin-ssr-fmt-tracing |
| description | Add low-cost fmt/time or log.Printf timing probes to Go Gin SSR request paths. |
Use this skill to add coarse performance timing to Go/Gin SSR code paths with minimal dependencies. Treat fmt + time as a low-cost instrumentation method, not as a profiler: it helps answer "which stage is slow", not "which function, allocation, goroutine, or lock is slow".
Use this skill when the user asks to:
Skip this skill when the user needs CPU, heap, allocation, goroutine scheduling, blocking, or lock analysis. Use pprof or go tool trace for those deeper runtime questions.
Use stage timing for:
Do not present this as sufficient for:
Escalate to pprof for CPU/heap detail and to go tool trace for goroutine scheduling and runtime behavior.
log.Printf or fmt.Fprintf(os.Stderr, ...), not plain fmt.Println.Use a helper like this when the project has no existing trace/log helper:
type Trace struct {
name string
start time.Time
}
func NewTrace(name string) *Trace {
return &Trace{
name: name,
start: time.Now(),
}
}
func (t *Trace) Done() {
log.Printf("[TRACE] stage=%s cost_ms=%d", t.name, time.Since(t.start).Milliseconds())
}
For AI-readable logs, prefer JSON lines:
func (t *Trace) Done() {
log.Printf(`{"event":"ssr_trace","stage":"%s","cost_ms":%d}`,
t.name,
time.Since(t.start).Milliseconds(),
)
}
If stage names can contain quotes or user-controlled values, use encoding/json or a structured logger instead of formatting JSON by hand.
When Gin context already contains a request ID, thread it into each trace:
func NewTraceWithID(reqID, stage string) *Trace {
return NewTrace(fmt.Sprintf("[%s] %s", reqID, stage))
}
For cleaner structured output, keep request ID as a separate key:
type Trace struct {
reqID string
stage string
start time.Time
}
func NewTrace(reqID, stage string) *Trace {
return &Trace{reqID: reqID, stage: stage, start: time.Now()}
}
func (t *Trace) Done() {
log.Printf(`{"event":"ssr_trace","request_id":"%s","stage":"%s","cost_ms":%d}`,
t.reqID,
t.stage,
time.Since(t.start).Milliseconds(),
)
}
If request IDs are missing and middleware is in scope:
func RequestID() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("req_id", uuid.NewString())
c.Next()
}
}
Instrument the standard SSR path like this, adapting names to the repo:
func GetArticle(c *gin.Context) {
reqID, _ := c.Get("req_id")
trace := NewTrace(fmt.Sprint(reqID), "TOTAL")
defer trace.Done()
t1 := NewTrace(fmt.Sprint(reqID), "FETCH")
data, err := service.GetData(c.Request.Context())
t1.Done()
if err != nil {
// Return using the repo's existing error response pattern.
return
}
t2 := NewTrace(fmt.Sprint(reqID), "BUILD_VIEW")
vm := buildViewModel(data)
t2.Done()
t3 := NewTrace(fmt.Sprint(reqID), "RENDER_TEMPLATE")
html, err := renderTemplate(vm)
t3.Done()
if err != nil {
// Return using the repo's existing error response pattern.
return
}
t4 := NewTrace(fmt.Sprint(reqID), "WRITE_RESPONSE")
c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(html))
t4.Done()
}
Use defer only for the total request timer or for stages with multiple returns. For short linear stages, call Done() immediately after the operation so the measured range is obvious.
Prefer one log line per stage:
{"event":"ssr_trace","request_id":"abc","stage":"FETCH","cost_ms":12}
{"event":"ssr_trace","request_id":"abc","stage":"BUILD_VIEW","cost_ms":3}
{"event":"ssr_trace","request_id":"abc","stage":"RENDER_TEMPLATE","cost_ms":45}
{"event":"ssr_trace","request_id":"abc","stage":"TOTAL","cost_ms":67}
Use stable stage names such as TOTAL, FETCH, DB_QUERY, RPC_CALL, BUILD_VIEW, RENDER_TEMPLATE, and WRITE_RESPONSE. Include route, handler, tenant, or user only when safe and useful; never log secrets, tokens, raw authorization headers, full payloads, or sensitive personal data.
log or fmt, time, and possibly os.Use .ai-code-index for local search, symbols, profiles, files, stats, refresh, and diagnostics.
Read-only project/AppSec audit: assets, data map, vuln review; Lark risks via arc:docs.
Local SAST/SCA/secrets/DAST automation with data-value re-ranking and Arc handoffs.
Current-state task docs; security/audit handoff to detailed subtasks with roles and caliber.
Apply backend architecture, DIP, usecase result boundaries, zap logging, Go constants, and helper limits.
Apply Chinese comment conventions; avoid noisy parameter/return boilerplate on obvious usecase contracts.