feat: track request cpu and peak memory usage and expose in caddy replacer vars
This captures request cpu (user+system) and peak memory usage similar to FPM and Apache2 SAPIs.
To propagate this back to Go we store it in FrankenPHP context first, before retrieving it in embedder / runtime (e.g. Caddy) from context.
For better compatibility with FPM logging we expose script and script filename vars as well.
- CPU usage is nanoseconds user space and system space thread runtime (only works on POSIX that supports clock_gettime(CLOCK_THREAD_CPUTIME_ID)).
- Memory usage is retrieved at the end of every request. In worker mode we reset peak memory usage before every request.
Using in Caddy:
log_append cpu_usage_human {http.frankenphp.cpu_usage_human}
log_append cpu_usage {http.frankenphp.cpu_usage}
log_append memory_usage {http.frankenphp.memory_usage}
log_append memory_usage_human {http.frankenphp.memory_usage_human}
log_append script {http.frankenphp.script}
log_append script_filename {http.frankenphp.script_filename}
I don't expect this to be merged as is, but if this is desirable, I will add tests and refactor based on feedback.
Couldn't this be implemented userland with the new frankenphp_log() function?
Kind of yes and no... unless I am missing something.
PHP cooperative way using log
- Requires modification of application
- Not sure how to work around finalizer, finish_request(), crashes, fatal errors. Adds additional log entries that require special handling.
- Not possible to get cpu usage, from what I can see PHP calls
getrusagewith RUSAGE_SELF, which is sum of all resources. - Different to existing SAPIs
FPM access log
- Single request line with resource usage summary
- Peak usage per request
- CPU usage time
We use per request memory and cpu in our observability to see outliers/ debugging, tweak configuration, alerting.
IMO I wouldn't be against exposing these stats to access logs, but they probably should only be collected if enabled. Maybe only collecting them if any of the caddy replacers exists. Also not a fan of passing information back out via context, I'd rather have a WithRequestStats() option that would write the values directly into replacers if possible.
I am not sure if it's possible to detect if replacer is used without inspecting all of the configs (especially when there are multiple caddy route handlers).
May be it could be an option on global frankenphp instance that enables resource tracking, or additional option on php directive?
I am not a fan of context abuse but I didn't see another way when I was hacking it together, good idea on WithRequestStats, I will add that.