Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions admin/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,7 @@ func ConsoleHandler(w http.ResponseWriter, r *http.Request) {
hi=-1;
out.innerHTML+='<span style="color:#888">&gt; '+esc(cmd)+'</span>\n';
input.value='';
var fd=new FormData();
fd.append('cmd',cmd);
fetch('/admin/console',{method:'POST',body:fd,headers:{'Accept':'application/json'}})
fetch('/admin/console',{method:'POST',body:'cmd='+encodeURIComponent(cmd),headers:{'Accept':'application/json','Content-Type':'application/x-www-form-urlencoded'}})
.then(function(r){return r.json()})
.then(function(j){
out.innerHTML+=esc(j.output)+'\n';
Expand Down
48 changes: 36 additions & 12 deletions internal/app/apilog.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,55 @@
package app

import (
"encoding/json"
"sync"
"time"

"mu/internal/data"
)

const apiLogMaxEntries = 200
const apiLogMaxEntries = 500

// APILogEntry records a single external API call.
type APILogEntry struct {
Time time.Time
Service string
Method string
URL string
Status int
Duration time.Duration
Error string
RequestBody string
ResponseBody string
Time time.Time `json:"time"`
Service string `json:"service"`
Method string `json:"method"`
URL string `json:"url"`
Status int `json:"status"`
Duration time.Duration `json:"duration"`
Error string `json:"error,omitempty"`
RequestBody string `json:"-"` // not persisted — too large
ResponseBody string `json:"-"` // not persisted — too large
}

var (
apiLogMu sync.Mutex
apiLogEntries []*APILogEntry
apiLogDirty bool
)

// RecordAPICall appends an external API call record to the in-memory log.
// When the log exceeds apiLogMaxEntries the oldest entry is dropped.
func init() {
b, err := data.LoadFile("api_log.json")
if err == nil && len(b) > 0 {
json.Unmarshal(b, &apiLogEntries)
}
// Start background saver
go func() {
for {
time.Sleep(10 * time.Second)
apiLogMu.Lock()
if apiLogDirty {
data.SaveJSON("api_log.json", apiLogEntries)
apiLogDirty = false
}
apiLogMu.Unlock()
}
}()
}

// RecordAPICall appends an external API call record.
// Persisted to disk every 10 seconds, capped at 500 entries.
func RecordAPICall(service, method, url string, status int, duration time.Duration, callErr error, reqBody, respBody string) {
entry := &APILogEntry{
Time: time.Now(),
Expand All @@ -46,6 +69,7 @@ func RecordAPICall(service, method, url string, status int, duration time.Durati
if len(apiLogEntries) > apiLogMaxEntries {
apiLogEntries = apiLogEntries[len(apiLogEntries)-apiLogMaxEntries:]
}
apiLogDirty = true
apiLogMu.Unlock()
}

Expand Down
Loading