2025-02-19 20:39:33 +01:00
|
|
|
package frankenphp
|
|
|
|
|
|
2026-03-26 11:37:24 +01:00
|
|
|
// #include "frankenphp.h"
|
|
|
|
|
import "C"
|
2025-12-02 23:10:12 +01:00
|
|
|
import (
|
|
|
|
|
"github.com/dunglas/frankenphp/internal/state"
|
|
|
|
|
)
|
|
|
|
|
|
2025-02-19 20:39:33 +01:00
|
|
|
// EXPERIMENTAL: ThreadDebugState prints the state of a single PHP thread - debugging purposes only
|
|
|
|
|
type ThreadDebugState struct {
|
|
|
|
|
Index int
|
|
|
|
|
Name string
|
|
|
|
|
State string
|
|
|
|
|
IsWaiting bool
|
|
|
|
|
IsBusy bool
|
|
|
|
|
WaitingSinceMilliseconds int64
|
2026-03-26 11:37:24 +01:00
|
|
|
CurrentURI string
|
|
|
|
|
CurrentMethod string
|
|
|
|
|
RequestStartedAt int64
|
|
|
|
|
RequestCount int64
|
|
|
|
|
MemoryUsage int64
|
2025-02-19 20:39:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EXPERIMENTAL: FrankenPHPDebugState prints the state of all PHP threads - debugging purposes only
|
|
|
|
|
type FrankenPHPDebugState struct {
|
|
|
|
|
ThreadDebugStates []ThreadDebugState
|
|
|
|
|
ReservedThreadCount int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EXPERIMENTAL: DebugState prints the state of all PHP threads - debugging purposes only
|
|
|
|
|
func DebugState() FrankenPHPDebugState {
|
|
|
|
|
fullState := FrankenPHPDebugState{
|
|
|
|
|
ThreadDebugStates: make([]ThreadDebugState, 0, len(phpThreads)),
|
|
|
|
|
ReservedThreadCount: 0,
|
|
|
|
|
}
|
|
|
|
|
for _, thread := range phpThreads {
|
2025-12-02 23:10:12 +01:00
|
|
|
if thread.state.Is(state.Reserved) {
|
2025-02-19 20:39:33 +01:00
|
|
|
fullState.ReservedThreadCount++
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
fullState.ThreadDebugStates = append(fullState.ThreadDebugStates, threadDebugState(thread))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fullState
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// threadDebugState creates a small jsonable status message for debugging purposes
|
|
|
|
|
func threadDebugState(thread *phpThread) ThreadDebugState {
|
2026-03-26 11:37:24 +01:00
|
|
|
isBusy := !thread.state.IsInWaitingState()
|
|
|
|
|
|
|
|
|
|
s := ThreadDebugState{
|
2025-02-19 20:39:33 +01:00
|
|
|
Index: thread.threadIndex,
|
2025-03-19 13:10:02 +01:00
|
|
|
Name: thread.name(),
|
2025-12-02 23:10:12 +01:00
|
|
|
State: thread.state.Name(),
|
|
|
|
|
IsWaiting: thread.state.IsInWaitingState(),
|
2026-03-26 11:37:24 +01:00
|
|
|
IsBusy: isBusy,
|
2025-12-02 23:10:12 +01:00
|
|
|
WaitingSinceMilliseconds: thread.state.WaitTime(),
|
2025-02-19 20:39:33 +01:00
|
|
|
}
|
2026-03-26 11:37:24 +01:00
|
|
|
|
|
|
|
|
s.RequestCount = thread.requestCount.Load()
|
|
|
|
|
s.MemoryUsage = int64(C.frankenphp_get_thread_memory_usage(C.uintptr_t(thread.threadIndex)))
|
|
|
|
|
|
|
|
|
|
if !isBusy {
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thread.handlerMu.RLock()
|
|
|
|
|
handler := thread.handler
|
|
|
|
|
thread.handlerMu.RUnlock()
|
|
|
|
|
|
|
|
|
|
if handler == nil {
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thread.contextMu.RLock()
|
|
|
|
|
defer thread.contextMu.RUnlock()
|
|
|
|
|
|
|
|
|
|
fc := handler.frankenPHPContext()
|
|
|
|
|
if fc == nil || fc.request == nil || fc.responseWriter == nil {
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fc.originalRequest == nil {
|
|
|
|
|
s.CurrentURI = fc.requestURI
|
|
|
|
|
s.CurrentMethod = fc.request.Method
|
|
|
|
|
} else {
|
|
|
|
|
s.CurrentURI = fc.originalRequest.URL.RequestURI()
|
|
|
|
|
s.CurrentMethod = fc.originalRequest.Method
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !fc.startedAt.IsZero() {
|
|
|
|
|
s.RequestStartedAt = fc.startedAt.UnixMilli()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s
|
2025-02-19 20:39:33 +01:00
|
|
|
}
|