github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/lib/html/header.go (about) 1 package html 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "runtime" 8 "strings" 9 "time" 10 11 "github.com/Cloud-Foundations/Dominator/lib/format" 12 ) 13 14 type cpuStats struct { 15 realTime time.Time 16 userTime time.Time 17 sysTime time.Time 18 } 19 20 var ( 21 startCpuStats *cpuStats = getCpuStats() 22 lastCpuStats *cpuStats = startCpuStats 23 ) 24 25 func handleFunc(serveMux *http.ServeMux, pattern string, 26 handler func(w http.ResponseWriter, req *http.Request)) { 27 serveMux.HandleFunc(pattern, 28 func(w http.ResponseWriter, req *http.Request) { 29 SetSecurityHeaders(w) // Compliance checkbox. 30 handler(w, req) 31 }) 32 } 33 34 func setSecurityHeaders(w http.ResponseWriter) { 35 w.Header().Set("X-Frame-Options", "DENY") 36 w.Header().Set("X-XSS-Protection", "1") 37 w.Header().Set("Content-Security-Policy", 38 "default-src 'self' ;style-src 'self' 'unsafe-inline'") 39 w.Header().Set("X-Content-Type-Options", "nosniff") 40 } 41 42 func writeCpuStats(writer io.Writer, prefix string, start, current *cpuStats) { 43 userCpuTime := current.userTime.Sub(start.userTime) 44 sysCpuTime := current.sysTime.Sub(start.sysTime) 45 realTime := current.realTime.Sub(start.realTime) 46 cpuTime := userCpuTime + sysCpuTime 47 fmt.Fprintf(writer, 48 " <td>%s CPU Time: %.1f%% (User: %s Sys: %s)</td>\n", 49 prefix, float64(cpuTime*100)/float64(realTime), userCpuTime, sysCpuTime) 50 } 51 52 func writeHeader(writer io.Writer, req *http.Request, noGC bool) { 53 currentCpuStats := getCpuStats() 54 fmt.Fprintln(writer, 55 `<table border="1" bordercolor=#e0e0e0 style="border-collapse: collapse">`) 56 fmt.Fprintf(writer, " <tr>\n") 57 fmt.Fprintf(writer, " <td>Start time: %s</td>\n", 58 startCpuStats.realTime.Format(format.TimeFormatSeconds)) 59 uptime := currentCpuStats.realTime.Sub(startCpuStats.realTime) 60 uptime += time.Millisecond * 50 61 uptime = (uptime / time.Millisecond / 100) * time.Millisecond * 100 62 fmt.Fprintf(writer, " <td>Uptime: %s</td>\n", format.Duration(uptime)) 63 fmt.Fprintf(writer, " </tr>\n") 64 fmt.Fprintf(writer, " <tr>\n") 65 writeCpuStats(writer, "Total", startCpuStats, currentCpuStats) 66 writeCpuStats(writer, "Recent", lastCpuStats, currentCpuStats) 67 lastCpuStats = currentCpuStats 68 fmt.Fprintf(writer, " </tr>\n") 69 fmt.Fprintf(writer, " <tr>\n") 70 var memStatsBeforeGC runtime.MemStats 71 runtime.ReadMemStats(&memStatsBeforeGC) 72 if noGC { 73 fmt.Fprintf(writer, " <td>Allocated memory: %s</td>\n", 74 format.FormatBytes(memStatsBeforeGC.Alloc)) 75 fmt.Fprintf(writer, " <td>System memory: %s</td>\n", 76 format.FormatBytes( 77 memStatsBeforeGC.Sys-memStatsBeforeGC.HeapReleased)) 78 } else { 79 var memStatsAfterGC runtime.MemStats 80 runtime.GC() 81 runtime.ReadMemStats(&memStatsAfterGC) 82 fmt.Fprintf(writer, " <td>Allocated memory: %s (%s after GC)</td>\n", 83 format.FormatBytes(memStatsBeforeGC.Alloc), 84 format.FormatBytes(memStatsAfterGC.Alloc)) 85 fmt.Fprintf(writer, " <td>System memory: %s (%s after GC)</td>\n", 86 format.FormatBytes( 87 memStatsBeforeGC.Sys-memStatsBeforeGC.HeapReleased), 88 format.FormatBytes( 89 memStatsAfterGC.Sys-memStatsAfterGC.HeapReleased)) 90 } 91 fmt.Fprintf(writer, " </tr>\n") 92 fmt.Fprintf(writer, "</table>\n") 93 fmt.Fprintln(writer, "Raw <a href=\"metrics\">metrics</a><br>") 94 if req != nil { 95 protocol := "http" 96 if req.TLS != nil { 97 protocol = "https" 98 } 99 host := strings.Split(req.Host, ":")[0] 100 fmt.Fprintf(writer, 101 "Local <a href=\"%s://%s:6910/\">system health agent</a>", 102 protocol, host) 103 } 104 } 105 106 func getCpuStats() *cpuStats { 107 uTime, sTime := getRusage() 108 return &cpuStats{ 109 realTime: time.Now(), 110 userTime: uTime, 111 sysTime: sTime, 112 } 113 }