Better error tracing
This commit is contained in:
parent
e968f0a5b9
commit
71ef3a290e
9 changed files with 52 additions and 16 deletions
|
|
@ -2,6 +2,7 @@ package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -36,7 +37,10 @@ func (admin *Admin) Status(ctx context.Context, QuickInformation bool) (target s
|
||||||
// store the info for this group!
|
// store the info for this group!
|
||||||
group.Go(func() (err error) {
|
group.Go(func() (err error) {
|
||||||
information[i], err = instance.Info().Information(ctx, true)
|
information[i], err = instance.Info().Information(ctx, true)
|
||||||
return err
|
if err != nil {
|
||||||
|
return fmt.Errorf("instance %q: %w", instance.Slug, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,14 @@ func (admin *Admin) instanceData(ctx context.Context) http.Handler {
|
||||||
|
|
||||||
ctx.Pathbuilders, err = ctx.Instance.Pathbuilder().GetAll(r.Context(), server)
|
ctx.Pathbuilders, err = ctx.Instance.Pathbuilder().GetAll(r.Context(), server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prefixes := ctx.Instance.Prefixes()
|
prefixes := ctx.Instance.Prefixes()
|
||||||
ctx.NoPrefixes = prefixes.NoPrefix()
|
ctx.NoPrefixes = prefixes.NoPrefix()
|
||||||
ctx.Prefixes, err = prefixes.All(r.Context(), server)
|
ctx.Prefixes, err = prefixes.All(r.Context(), server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx, []templating.FlagFunc{
|
return ctx, []templating.FlagFunc{
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func (admin *Admin) instanceDrupal(ctx context.Context) http.Handler {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err = eg.Wait(); err != nil {
|
if err = eg.Wait(); err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx, []templating.FlagFunc{
|
return ctx, []templating.FlagFunc{
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func (admin *Admin) instanceSnapshots(ctx context.Context) http.Handler {
|
||||||
|
|
||||||
ctx.Snapshots, err = ctx.Instance.Snapshots(r.Context())
|
ctx.Snapshots, err = ctx.Instance.Snapshots(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx, []templating.FlagFunc{
|
return ctx, []templating.FlagFunc{
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func (admin *Admin) instanceSSH(ctx context.Context) http.Handler {
|
||||||
|
|
||||||
keys, err := ctx.Instance.SSH().Keys(r.Context())
|
keys, err := ctx.Instance.SSH().Keys(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SSHKeys = make([]string, len(keys))
|
ctx.SSHKeys = make([]string, len(keys))
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ func (admin *Admin) instanceStats(ctx context.Context) http.Handler {
|
||||||
// read statistics
|
// read statistics
|
||||||
ctx.Statistics, err = ctx.Instance.Stats().Get(r.Context(), nil)
|
ctx.Statistics, err = ctx.Instance.Stats().Get(r.Context(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, nil, httpx.ErrInternalServerError
|
return ctx, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx, []templating.FlagFunc{
|
return ctx, []templating.FlagFunc{
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
|
||||||
|
|
@ -145,6 +146,7 @@ func WithCSP(handler http.Handler, policy string) http.Handler {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
httpx.InterceptorOnFallback = func(req *http.Request, err error) {
|
httpx.InterceptorOnFallback = func(req *http.Request, err error) {
|
||||||
zerolog.Ctx(req.Context()).Err(err).Msg("unknown error intercepted")
|
stack := debug.Stack()
|
||||||
|
zerolog.Ctx(req.Context()).Err(err).Str("stack", string(stack)).Msg("unknown error intercepted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -165,6 +166,7 @@ func (ctx *tContext[C]) Footer() (template.HTML, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderSafeError = "Error displaying page. See server log for details. "
|
const renderSafeError = "Error displaying page. See server log for details. "
|
||||||
|
const renderPanicError = "Panic displaying page. See server log for details. "
|
||||||
|
|
||||||
func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (template.HTML, error) {
|
func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (template.HTML, error) {
|
||||||
|
|
||||||
|
|
@ -173,16 +175,19 @@ func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (te
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err, panicked := func() (value template.HTML, err error, panicked bool) {
|
value, panicked, panik, stack, err := func() (value template.HTML, panicked bool, panik any, stack []byte, err error) {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if panicked {
|
if panicked {
|
||||||
r := recover()
|
panik = recover()
|
||||||
|
stack = debug.Stack()
|
||||||
|
|
||||||
zerolog.Ctx(ctx.ctx).Error().
|
zerolog.Ctx(ctx.ctx).Error().
|
||||||
Str("uri", ctx.Runtime.RequestURI).
|
Str("uri", ctx.Runtime.RequestURI).
|
||||||
Str("name", name).
|
Str("name", name).
|
||||||
Str("panic", fmt.Sprint(r)).
|
Str("panic", fmt.Sprint(panik)).
|
||||||
|
Str("stack", string(stack)).
|
||||||
Msg("renderSafe: template panic()ed")
|
Msg("renderSafe: template panic()ed")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
@ -198,11 +203,24 @@ func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (te
|
||||||
Msg("template errored")
|
Msg("template errored")
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.HTML(builder.String()), err, false
|
return template.HTML(builder.String()), false, nil, nil, err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err != nil || panicked {
|
if err != nil {
|
||||||
return renderSafeError, httpx.ErrInternalServerError
|
return renderSafeError, err
|
||||||
|
}
|
||||||
|
if panicked {
|
||||||
|
return renderPanicError, panicErr{value: panik, stack: stack}
|
||||||
}
|
}
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// panicErr is returned by renderSafe when a panic occurs
|
||||||
|
type panicErr struct {
|
||||||
|
value any
|
||||||
|
stack []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pe panicErr) Error() string {
|
||||||
|
return fmt.Sprintf("panic: %v", pe.value)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package info
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -68,14 +70,24 @@ func (wisski *Info) Information(ctx context.Context, quick bool) (info status.Wi
|
||||||
// quick: don't need to create servers
|
// quick: don't need to create servers
|
||||||
if flags.Quick {
|
if flags.Quick {
|
||||||
defer recordTime(i)()
|
defer recordTime(i)()
|
||||||
return fetcher.Fetch(flags, &info)
|
|
||||||
|
err := fetcher.Fetch(flags, &info)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("fetcher %s (quick): %w", reflect.TypeOf(fetcher), err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete: need to use a server from the pool
|
// complete: need to use a server from the pool
|
||||||
return pool.Use(func(s *phpx.Server) error {
|
return pool.Use(func(s *phpx.Server) error {
|
||||||
defer recordTime(i)()
|
defer recordTime(i)()
|
||||||
flags.Server = s
|
flags.Server = s
|
||||||
return fetcher.Fetch(flags, &info)
|
|
||||||
|
err := fetcher.Fetch(flags, &info)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("fetcher %s (pool): %w", reflect.TypeOf(fetcher), err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue