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  }