| 1 | {{define "app_errors"}}{{template "top" .}} |
| 2 | {{if .Flash}}<p class="banner">{{.Flash}}</p>{{end}} |
| 3 | {{if .FlashErr}}<p class="banner error">{{.FlashErr}}</p>{{end}} |
| 4 | {{template "appnav" .}} |
| 5 | {{template "lognav" .}} |
| 6 | |
| 7 | <h2 class="visually-hidden">Errors</h2> |
| 8 | {{if .ErrsErr}}<p class="banner error">{{.ErrsErr}}</p>{{end}} |
| 9 | <form method="get" class="small"> |
| 10 | <label>from the last |
| 11 | <select name="since"> |
| 12 | <option value="1h"{{if eq .ErrSince "1h"}} selected{{end}}>hour</option> |
| 13 | <option value="24h"{{if eq .ErrSince "24h"}} selected{{end}}>day</option> |
| 14 | <option value="168h"{{if eq .ErrSince "168h"}} selected{{end}}>week</option> |
| 15 | </select> |
| 16 | </label> |
| 17 | <label>source |
| 18 | <select name="source"> |
| 19 | <option value=""{{if eq .ErrSource ""}} selected{{end}}>all</option> |
| 20 | <option value="log"{{if eq .ErrSource "log"}} selected{{end}}>log</option> |
| 21 | <option value="edge"{{if eq .ErrSource "edge"}} selected{{end}}>edge</option> |
| 22 | <option value="server"{{if eq .ErrSource "server"}} selected{{end}}>server</option> |
| 23 | <option value="browser"{{if eq .ErrSource "browser"}} selected{{end}}>browser</option> |
| 24 | </select> |
| 25 | </label> |
| 26 | <label>log level |
| 27 | <select name="level"> |
| 28 | <option value=""{{if eq .ErrLevel ""}} selected{{end}}>setting ({{.ErrWin.LogLevel}})</option> |
| 29 | <option value="error"{{if eq .ErrLevel "error"}} selected{{end}}>error</option> |
| 30 | <option value="warn"{{if eq .ErrLevel "warn"}} selected{{end}}>warn and above</option> |
| 31 | </select> |
| 32 | </label> |
| 33 | <label>host <input name="host" value="{{.ErrHost}}" size="24"></label> |
| 34 | <button type="submit">Update</button> |
| 35 | </form> |
| 36 | <p class="small">Sources live: {{if .ErrWin.Sources}}{{range $i, $s := .ErrWin.Sources}}{{if $i}}, {{end}}{{$s}}{{end}}{{else}}none yet{{end}}. |
| 37 | Counts are to the nearest flush. Messages are redacted for addresses and credentials before they are stored; treat that as a floor, not a guarantee.</p> |
| 38 | |
| 39 | {{if .ErrFP}} |
| 40 | {{with .ErrWin.Records}} |
| 41 | <h3>Occurrences of <code>{{$.ErrFP}}</code></h3> |
| 42 | <p class="small"><a href="?since={{$.ErrSince}}{{if $.ErrSource}}&source={{$.ErrSource}}{{end}}{{if $.ErrHost}}&host={{$.ErrHost}}{{end}}{{if $.ErrLevel}}&level={{$.ErrLevel}}{{end}}">All groups</a></p> |
| 43 | {{if $.ErrWin.Truncated}}<p class="small">Showing the newest {{len $.ErrWin.Records}} occurrences of a larger window — narrow the window, or use <code>carlos errors</code> for all of them.</p>{{end}} |
| 44 | {{range .}} |
| 45 | <div class="tablewrap"><table> |
| 46 | <tr><th>Last</th><td>{{.Last.UTC.Format "2006-01-02 15:04:05"}}</td></tr> |
| 47 | <tr><th>Count</th><td>{{.Count}}</td></tr> |
| 48 | <tr><th>Source</th><td>{{.Source}}{{if .Kind}} / {{.Kind}}{{end}}</td></tr> |
| 49 | <tr><th>Host</th><td>{{.Host}}</td></tr> |
| 50 | {{if .Release}}<tr><th>Release</th><td>{{.Release}}</td></tr>{{end}} |
| 51 | {{if .Path}}<tr><th>Path</th><td><code>{{.Path}}</code>{{if .Status}} → {{.Status}}{{end}}</td></tr>{{end}} |
| 52 | <tr><th>Message</th><td>{{.Name}}</td></tr> |
| 53 | {{if .Stack}}<tr><th>Stack</th><td><pre>{{.Stack}}</pre></td></tr>{{end}} |
| 54 | {{if .Fields}}<tr><th>Fields</th><td>{{range $k, $v := .Fields}}<code>{{$k}}={{$v}}</code> {{end}}</td></tr>{{end}} |
| 55 | <tr><th>Logs</th><td><a href="{{$.Nav}}/apps/{{$.AppName}}/logs?since=1h&host={{.Host}}">around this time</a></td></tr> |
| 56 | </table></div> |
| 57 | {{end}} |
| 58 | {{else}}<p>No occurrences of this group in the window.</p>{{end}} |
| 59 | {{else if .ErrWin.Groups}} |
| 60 | {{if .ErrWin.Truncated}}<p class="small">Showing {{len .ErrWin.Groups}} groups of a larger window — counts are within what was read. Narrow the window, or use <code>carlos errors</code> for all of them.</p>{{end}} |
| 61 | <div class="tablewrap"> |
| 62 | <table> |
| 63 | <tr><th>Last seen</th><th>First seen</th><th>Count</th><th>Source</th><th>Error</th><th>Hosts</th><th>Releases</th></tr> |
| 64 | {{range .ErrWin.Groups}}<tr> |
| 65 | <td>{{.Last.UTC.Format "2006-01-02 15:04"}}</td> |
| 66 | <td>{{.First.UTC.Format "2006-01-02 15:04"}}</td> |
| 67 | <td>{{.Count}}{{if eq .FP "_overflow"}} <span class="small" title="occurrences beyond the hourly cap on distinct errors">(overflow)</span>{{end}}</td> |
| 68 | <td>{{.Source}}{{if .Kind}} <span class="small">{{.Kind}}</span>{{end}}{{if .Level}} <span class="small">{{.Level}}</span>{{end}}</td> |
| 69 | <td><a href="?since={{$.ErrSince}}&fp={{.FP}}{{if $.ErrSource}}&source={{$.ErrSource}}{{end}}{{if $.ErrHost}}&host={{$.ErrHost}}{{end}}{{if $.ErrLevel}}&level={{$.ErrLevel}}{{end}}">{{.Name}}</a></td> |
| 70 | <td>{{range $i, $h := .Hosts}}{{if $i}}, {{end}}{{$h}}{{end}}</td> |
| 71 | <td>{{range $i, $r := .Releases}}{{if $i}}, {{end}}<code>{{$r}}</code>{{end}}</td> |
| 72 | </tr>{{end}} |
| 73 | </table> |
| 74 | </div> |
| 75 | <p class="small">Times are UTC. The same view from a terminal: <code>carlos errors --app {{.AppName}} --since {{.ErrSince}}</code>.</p> |
| 76 | {{else if not .ErrsErr}} |
| 77 | <p>No errors in this window.</p> |
| 78 | <p class="small">Log lines at <code>{{.ErrWin.LogLevel}}</code> and above and the app's own 500s appear here on their own (a 502, 503 or 504 is on <a href="{{.Nav}}/apps/{{.AppName}}/availability">Availability</a>); a JavaScript or server-side error needs the hook (coming in a later step). The level is set on the Settings tab. The same view from a terminal: <code>carlos errors --app {{.AppName}}</code>.</p> |
| 79 | {{end}} |
| 80 | {{template "bottom" .}}{{end}} |
| 81 | |