frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

feat: track request cpu and peak memory usage and expose in caddy replacer vars

Open ikrestov opened this issue 2 months ago • 3 comments

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}

ikrestov avatar Dec 17 '25 14:12 ikrestov

I don't expect this to be merged as is, but if this is desirable, I will add tests and refactor based on feedback.

ikrestov avatar Dec 18 '25 14:12 ikrestov

Couldn't this be implemented userland with the new frankenphp_log() function?

dunglas avatar Dec 18 '25 14:12 dunglas

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 getrusage with 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.

ikrestov avatar Dec 18 '25 16:12 ikrestov

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.

AlliBalliBaba avatar Dec 31 '25 14:12 AlliBalliBaba

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.

ikrestov avatar Jan 04 '26 17:01 ikrestov