@@ -18,13 +18,11 @@ package frankenphp
1818// #include <php_variables.h>
1919// #include <zend_llist.h>
2020// #include <SAPI.h>
21- // static inline const char *frankenphp_get_build_version() {
22- // return TOSTRING(FRANKENPHP_VERSION);
23- // }
2421import "C"
2522import (
2623 "bytes"
2724 "context"
25+ "debug/buildinfo"
2826 "errors"
2927 "fmt"
3028 "io"
@@ -33,6 +31,7 @@ import (
3331 "os"
3432 "os/signal"
3533 "runtime"
34+ runtimeDebug "runtime/debug"
3635 "strings"
3736 "sync"
3837 "sync/atomic"
7372 // atomic: read by in-flight requests while a reload may rewrite it
7473 maxWaitTime atomic.Int64
7574 maxRequestsPerThread int
75+
76+ frankenPHPVersion = sync .OnceValues (func () (string , error ) {
77+ return frankenPHPVersionFromExecutable (os .Executable , buildinfo .ReadFile )
78+ })
7679)
7780
7881type ErrRejected struct {
@@ -97,6 +100,24 @@ const (
97100 syslogLevelDebug // debug-level messages
98101)
99102
103+ const (
104+ frankenPHPModulePath = "github.com/dunglas/frankenphp"
105+ unknownModuleVersion = "(devel)"
106+
107+ startupLogMessage = "FrankenPHP started 🐘"
108+ startupLogVersionUnavailableMessage = "FrankenPHP version unavailable"
109+ startupLogAttrVersion = "version"
110+ startupLogAttrPHPVersion = "php_version"
111+ startupLogAttrNumThreads = "num_threads"
112+ startupLogAttrMaxThreads = "max_threads"
113+ startupLogAttrMaxRequests = "max_requests"
114+ startupLogAttrError = "error"
115+ startupLogAttrCapacity = 5
116+
117+ executablePathErrorMessage = "getting executable path: %w"
118+ buildInfoReadErrorMessage = "reading build info: %w"
119+ )
120+
100121func (l syslogLevel ) String () string {
101122 switch l {
102123 case syslogLevelEmerg :
@@ -148,8 +169,46 @@ func Version() PHPVersion {
148169 }
149170}
150171
151- func frankenPHPVersion () string {
152- return C .GoString (C .frankenphp_get_build_version ())
172+ func frankenPHPVersionFromExecutable (executablePathFunc func () (string , error ), readBuildInfoFunc func (string ) (* runtimeDebug.BuildInfo , error )) (string , error ) {
173+ executablePath , err := executablePathFunc ()
174+ if err != nil {
175+ return "" , fmt .Errorf (executablePathErrorMessage , err )
176+ }
177+
178+ info , err := readBuildInfoFunc (executablePath )
179+ if err != nil {
180+ return "" , fmt .Errorf (buildInfoReadErrorMessage , err )
181+ }
182+
183+ return frankenPHPVersionFromBuildInfo (info ), nil
184+ }
185+
186+ func frankenPHPVersionFromBuildInfo (info * runtimeDebug.BuildInfo ) string {
187+ if info == nil {
188+ return ""
189+ }
190+ if info .Main .Path == frankenPHPModulePath && moduleVersionIsKnown (info .Main .Version ) {
191+ return info .Main .Version
192+ }
193+ for _ , dep := range info .Deps {
194+ if dep .Path == frankenPHPModulePath && moduleVersionIsKnown (dep .Version ) {
195+ return dep .Version
196+ }
197+ }
198+ return ""
199+ }
200+
201+ func moduleVersionIsKnown (version string ) bool {
202+ return version != "" && version != unknownModuleVersion
203+ }
204+
205+ func startupLogAttrs (frankenPHPVersion string , phpVersion string , numThreads int , maxThreads int , maxRequests int ) []slog.Attr {
206+ attrs := make ([]slog.Attr , 0 , startupLogAttrCapacity )
207+ if frankenPHPVersion != "" {
208+ attrs = append (attrs , slog .String (startupLogAttrVersion , frankenPHPVersion ))
209+ }
210+
211+ return append (attrs , slog .String (startupLogAttrPHPVersion , phpVersion ), slog .Int (startupLogAttrNumThreads , numThreads ), slog .Int (startupLogAttrMaxThreads , maxThreads ), slog .Int (startupLogAttrMaxRequests , maxRequests ))
153212}
154213
155214func Config () PHPConfig {
@@ -349,7 +408,13 @@ func Init(options ...Option) error {
349408 initAutoScaling (mainThread )
350409
351410 if globalLogger .Enabled (globalCtx , slog .LevelInfo ) {
352- globalLogger .LogAttrs (globalCtx , slog .LevelInfo , startupLogMessage , startupLogAttrs (Version ().Version , mainThread .numThreads , mainThread .maxThreads , maxRequestsPerThread )... )
411+ frankenPHPBuildVersion := ""
412+ if version , err := frankenPHPVersion (); err != nil {
413+ globalLogger .LogAttrs (globalCtx , slog .LevelDebug , startupLogVersionUnavailableMessage , slog .Any (startupLogAttrError , err ))
414+ } else {
415+ frankenPHPBuildVersion = version
416+ }
417+ globalLogger .LogAttrs (globalCtx , slog .LevelInfo , startupLogMessage , startupLogAttrs (frankenPHPBuildVersion , Version ().Version , mainThread .numThreads , mainThread .maxThreads , maxRequestsPerThread )... )
353418
354419 if EmbeddedAppPath != "" {
355420 globalLogger .LogAttrs (globalCtx , slog .LevelInfo , "embedded PHP app 📦" , slog .String ("path" , EmbeddedAppPath ))
0 commit comments