Repository navigation
chore: Add opt-in unused-stub logging via ?logUnusedMappings #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 0.13.0 | ||
| 0.14.0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,10 @@ func handleReplayRequest(s *types.Server, ctx *fasthttp.RequestCtx) { | |
| } | ||
|
|
||
| m := result.Mapping | ||
| s.Mu.Lock() | ||
| m.Matched = true | ||
|
Comment on lines
+124
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: rg -n 'func .*MatchRequest|Mappings = append|func .*ClearMappings|func .*AddMapping|Matched' internal
sed -n '100,250p' internal/replay/replay.goRepository: gooddata/gooddata-goodmock Length of output: 5269 🏁 Script executed: printf '%s\n' '--- internal/matching/matching.go ---'
nl -ba internal/matching/matching.go | sed -n '1,210p'
printf '%s\n' '--- internal/server/server.go ---'
nl -ba internal/server/server.go | sed -n '1,100p'
printf '%s\n' '--- internal/types/types.go ---'
nl -ba internal/types/types.go | sed -n '1,115p'
printf '%s\n' '--- mapping mutation and MatchRequest callers ---'
rg -n -F --glob '*.go' -e 'MatchRequest(' -e 'LoadMappings(' -e 'AddMapping(' -e 'Mappings = append' -e 's.Mappings' internalRepository: gooddata/gooddata-goodmock Length of output: 15514 🏁 Script executed: nl -ba internal/replay/replay.go | sed -n '175,290p'Repository: gooddata/gooddata-goodmock Length of output: 3958 Mark the mapping before releasing the matching lock.
Move the marking into Suggested fix--- a/internal/matching/matching.go
+++ b/internal/matching/matching.go
@@
- s.Mu.RLock()
- defer s.Mu.RUnlock()
+ s.Mu.Lock()
+ defer s.Mu.Unlock()
@@
+ if bestMatch.Matched && bestMatch.Mapping != nil {
+ bestMatch.Mapping.Matched = true
+ }
return bestMatch--- a/internal/replay/replay.go
+++ b/internal/replay/replay.go
@@
m := result.Mapping
- s.Mu.Lock()
- m.Matched = true
- s.Mu.Unlock()
applyResponseHeaders(ctx, m.Response.Headers)🤖 Prompt for AI Agents |
||
| s.Mu.Unlock() | ||
|
|
||
| applyResponseHeaders(ctx, m.Response.Headers) | ||
|
|
||
| ctx.SetStatusCode(m.Response.Status) | ||
|
|
@@ -170,6 +174,9 @@ func applyResponseHeaders(ctx *fasthttp.RequestCtx, headers map[string]any) { | |
|
|
||
| func handleReplayAdmin(s *types.Server, ctx *fasthttp.RequestCtx, path, method string) { | ||
| if path == "/__admin/reset" && method == "POST" { | ||
| if wantsUnusedLog(ctx) { | ||
| logUnusedMappings(s) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Make logging and clearing one reset operation. If a request matches a stub after 🤖 Prompt for AI Agents |
||
| } | ||
| server.ClearMappings(s) | ||
| log.Println("All mappings reset") | ||
| ctx.SetStatusCode(fasthttp.StatusOK) | ||
|
|
@@ -202,7 +209,11 @@ func handleReplayAdmin(s *types.Server, ctx *fasthttp.RequestCtx, path, method s | |
| } | ||
|
|
||
| if path == "/__admin/mappings/reset" && method == "POST" { | ||
| if wantsUnusedLog(ctx) { | ||
| logUnusedMappings(s) | ||
| } | ||
| server.ClearMappings(s) | ||
| log.Println("All mappings reset") | ||
| ctx.SetStatusCode(fasthttp.StatusOK) | ||
| return | ||
| } | ||
|
|
@@ -211,6 +222,25 @@ func handleReplayAdmin(s *types.Server, ctx *fasthttp.RequestCtx, path, method s | |
| server.HandleAdmin(ctx, path, method) | ||
| } | ||
|
|
||
| // wantsUnusedLog reports whether the reset request carries a logUnusedMappings | ||
| // query parameter. Presence alone enables it, e.g. /__admin/mappings/reset?logUnusedMappings | ||
| func wantsUnusedLog(ctx *fasthttp.RequestCtx) bool { | ||
| return ctx.QueryArgs().Has("logUnusedMappings") | ||
| } | ||
|
|
||
| // logUnusedMappings logs every loaded stub that no replayed request has matched. | ||
| func logUnusedMappings(s *types.Server) { | ||
| s.Mu.RLock() | ||
| defer s.Mu.RUnlock() | ||
|
Comment on lines
+233
to
+234
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '220,250p' internal/replay/replay.go
rg -n 'os.Stdout|SetOutput|fmt.Printf' internal/logging/logging.go | headRepository: gooddata/gooddata-goodmock Length of output: 1642 🏁 Script executed: set -eu
printf '%s\n' '--- references ---'
rg -n -F --glob '*.go' -e 'logUnusedMappings' -e 'wantsUnusedLog' -e 'HandleAdmin' -e 'Mu.Lock()' -e 'Mu.RLock()' internal types || true
printf '%s\n' '--- replay.go admin and replay paths ---'
sed -n '1,280p' internal/replay/replay.go
printf '%s\n' '--- server type and lock declarations ---'
rg -n -F --glob '*.go' -e 'type Server struct' -e 'sync.RWMutex' -e 'Mappings []' .
sed -n '1,180p' internal/types/server.go 2>/dev/null || true
printf '%s\n' '--- repository references and docs ---'
rg -n -F --hidden --glob '!**/.git/**' -e 'logUnusedMappings' -e 'logUnused' -e '__admin/mappings/reset' -e '__admin/reset' . || trueRepository: gooddata/gooddata-goodmock Length of output: 13532 Release the mapping lock before writing logs. When an admin caller uses Copy the unmatched mappings while holding the read lock, then call Suggested fix--- "a/internal/replay/replay.go"
+++ "b/internal/replay/replay.go"
@@ -229,17 +229,20 @@
}
// logUnusedMappings logs every loaded stub that no replayed request has matched.
func logUnusedMappings(s *types.Server) {
s.Mu.RLock()
- defer s.Mu.RUnlock()
-
+ unused := make([]types.Mapping, 0)
for i := range s.Mappings {
- m := &s.Mappings[i]
- if !m.Matched {
- logging.LogUnused(*m)
+ if !s.Mappings[i].Matched {
+ unused = append(unused, s.Mappings[i])
}
}
+ s.Mu.RUnlock()
+
+ for _, m := range unused {
+ logging.LogUnused(m)
+ }
}
func handleMappings(s *types.Server, ctx *fasthttp.RequestCtx, method string) {
switch method {🤖 Prompt for AI Agents |
||
|
|
||
| for i := range s.Mappings { | ||
| m := &s.Mappings[i] | ||
| if !m.Matched { | ||
| logging.LogUnused(*m) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func handleMappings(s *types.Server, ctx *fasthttp.RequestCtx, method string) { | ||
| switch method { | ||
| case "POST": | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Escape line breaks before printing table cells.
If a stub has a multiline response body,
truncateleaves short line breaks intact. The body then splits one table row into several unlabelled log lines. Escape control characters in both cells before truncation so each criterion stays on one row.🤖 Prompt for AI Agents