@@ -14,6 +14,7 @@ import (
1414 "io"
1515 "log"
1616 "math"
17+ "net" // Added net import
1718 "net/http"
1819 "os"
1920 "strings"
@@ -127,6 +128,9 @@ type QueueManager struct {
127128 // Cleanup routine
128129 cleanupTicker * time.Ticker
129130 stopCleanup chan bool // Channel to signal the cleanup goroutine to stop
131+
132+ // Log file handle if a log file is used
133+ logFileHandle * os.File
130134}
131135
132136// logf provides leveled logging for the plugin.
@@ -162,7 +166,6 @@ func (qm *QueueManager) logf(level string, format string, v ...interface{}) {
162166 }
163167 }
164168
165-
166169 if shouldLog {
167170 qm .logger .Printf (logPrefix + strings .ToUpper (level )+ ": " + format , v ... )
168171 }
@@ -189,6 +192,7 @@ func New(_ context.Context, next http.Handler, config *Config, name string) (htt
189192 stopCleanup : make (chan bool ),
190193 inactivityTimeoutDur : time .Duration (config .InactivityTimeoutSeconds ) * time .Second ,
191194 cleanupIntervalDur : time .Duration (config .CleanupIntervalSeconds ) * time .Second ,
195+ logFileHandle : logFileHandle , // Store the file handle
192196 }
193197
194198 if config .HardSessionLimitSeconds > 0 {
@@ -216,14 +220,6 @@ func New(_ context.Context, next http.Handler, config *Config, name string) (htt
216220 if config .Debug {
217221 qm .logf ("debug" , "Full configuration: %+v" , config )
218222 }
219-
220- // If a log file was opened, defer its closure (though plugin stop lifecycle isn't guaranteed by Traefik)
221- if logFileHandle != nil {
222- // This defer might not execute if Traefik exits abruptly.
223- // For long-running plugins, a more robust stop mechanism would be needed if Traefik provided it.
224- // defer logFileHandle.Close() // Cannot defer here, as New returns. See Stop() method.
225- }
226-
227223
228224 return qm , nil
229225}
@@ -559,7 +555,7 @@ func getClientIP(req *http.Request) string {
559555 if xrip != "" {
560556 return strings .TrimSpace (xrip )
561557 }
562-
558+
563559 // 3. Fly-Client-IP: Header used by Fly.io
564560 flyIP := req .Header .Get ("Fly-Client-IP" )
565561 if flyIP != "" {
@@ -571,15 +567,15 @@ func getClientIP(req *http.Request) string {
571567 if cfIP != "" {
572568 return strings .TrimSpace (cfIP )
573569 }
574-
570+
575571 // 5. Fallback to RemoteAddr: This might be the IP of the immediate upstream proxy.
576572 // RemoteAddr is typically in "ip:port" format.
577573 remoteAddr := req .RemoteAddr
578- host , _ , err := net .SplitHostPort (remoteAddr )
574+ host , _ , err := net .SplitHostPort (remoteAddr ) // net is not imported, need to import "net"
579575 if err == nil && host != "" {
580576 return host
581577 }
582-
578+
583579 // If SplitHostPort fails (e.g. RemoteAddr is just an IP), return RemoteAddr as is.
584580 return remoteAddr
585581}
@@ -640,7 +636,6 @@ func (qm *QueueManager) prepareQueuePageData(positionInQueue int) QueuePageData
640636 estimatedWaitTime = qm .config .MinWaitTimeMinutes
641637 }
642638
643-
644639 // Calculate progress percentage
645640 progressPercentage := 0
646641 if queueSize > 0 {
@@ -660,9 +655,12 @@ func (qm *QueueManager) prepareQueuePageData(positionInQueue int) QueuePageData
660655 progressPercentage = 99 // Almost there
661656 }
662657 // Clamp percentage
663- if progressPercentage > 100 { progressPercentage = 100 }
664- if progressPercentage < 0 { progressPercentage = 0 }
665-
658+ if progressPercentage > 100 {
659+ progressPercentage = 100
660+ }
661+ if progressPercentage < 0 {
662+ progressPercentage = 0
663+ }
666664
667665 var debugInfo string
668666 if qm .config .Debug {
@@ -788,19 +786,18 @@ func (qm *QueueManager) CleanupExpiredSessions() {
788786 qm .cache .Set (promotedClientSession .ID , promotedClientSession , qm .inactivityTimeoutDur )
789787 promotedCount ++
790788 }
791-
789+
792790 // 4. After promotions, re-index positions for the remaining items in the queue
793791 for i := range qm .queue {
794792 qm .queue [i ].Position = i
795793 // Optionally update cache for these items if position is critical there,
796794 // but it's mainly for display from this function's perspective.
797795 if s , found := qm .getSessionFromCache (qm .queue [i ].ID ); found {
798- s .Position = i
799- qm .cache .Set (s .ID , s , qm .inactivityTimeoutDur ) // Keep it fresh in cache
796+ s .Position = i
797+ qm .cache .Set (s .ID , s , qm .inactivityTimeoutDur ) // Keep it fresh in cache
800798 }
801799 }
802800
803-
804801 if removedActiveCount > 0 || removedQueueCount > 0 || promotedCount > 0 {
805802 qm .logf ("info" , "Cleanup results: Removed Active: %d, Removed Queued: %d, Promoted: %d. Current State -> Active: %d, Queue: %d" ,
806803 removedActiveCount , removedQueueCount , promotedCount , len (qm .activeSessionIDs ), len (qm .queue ))
@@ -871,18 +868,15 @@ func (qm *QueueManager) Stop() {
871868 qm .logf ("debug" , "Cache cleanup routine signaled to stop." )
872869 }
873870
874- // Close log file if it was opened
875- if qm .logger != nil {
876- if closer , ok := qm .logger .Writer ().(io.Closer ); ok {
877- // Check if it's os.Stderr before trying to close, to avoid closing stderr.
878- // This check is a bit tricky as logger.Writer() returns io.Writer.
879- // A simpler way is to store the file handle if one was opened.
880- // Assuming setupLogOutput returns the file handle if used:
881- // if qm.logFileHandle != nil { qm.logFileHandle.Close() }
882- // For now, this is a placeholder as direct access to the file handle from here isn't set up.
883- // If the writer is a file, it should be closed.
884- // This requires qm to store the file handle if it opens one.
871+ // Close log file if it was opened and stored
872+ if qm .logFileHandle != nil {
873+ qm .logf ("info" , "Closing log file: %s" , qm .config .LogFile )
874+ err := qm .logFileHandle .Close ()
875+ if err != nil {
876+ // Log to stderr if log file closing fails, as qm.logger might be using the file.
877+ log .Printf (logPrefix + "ERROR: Failed to close log file %s: %v" , qm .config .LogFile , err )
885878 }
879+ qm .logFileHandle = nil // Avoid double closing
886880 }
887881 qm .logf ("info" , "QueueManager plugin has been signaled to stop." )
888- }
882+ }
0 commit comments