Skip to content

Commit

Permalink
UI for recent logs
Browse files Browse the repository at this point in the history
  • Loading branch information
kyleu committed Sep 4, 2023
1 parent ba899b5 commit 0972878
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 131 deletions.
5 changes: 5 additions & 0 deletions app/controller/clib/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/kyleu/npn/app"
"github.com/kyleu/npn/app/controller"
"github.com/kyleu/npn/app/controller/cutil"
"github.com/kyleu/npn/app/lib/log"
"github.com/kyleu/npn/app/lib/user"
"github.com/kyleu/npn/app/util"
"github.com/kyleu/npn/views/vadmin"
Expand Down Expand Up @@ -57,6 +58,10 @@ func Admin(rc *fasthttp.RequestCtx) {
return "", err
}
return controller.FlashAndRedir(true, "wrote heap profile", "/admin", rc, ps)
case "logs":
x := util.DebugMemStats()
ps.Data = x
return controller.Render(rc, as, &vadmin.Logs{Logs: log.RecentLogs}, ps, "admin", "Recent Logs")
case "memusage":
x := util.DebugMemStats()
ps.Data = x
Expand Down
42 changes: 28 additions & 14 deletions app/lib/log/encoder.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:build !js

// Content managed by Project Forge, see [projectforge.md] for details.
package log

Expand All @@ -19,18 +17,27 @@ const timeFormat = "15:04:05.000000"

type customEncoder struct {
zapcore.Encoder
pool buffer.Pool
colored bool
pool buffer.Pool
}

func newEncoder(cfg zapcore.EncoderConfig) *customEncoder {
return &customEncoder{Encoder: zapcore.NewJSONEncoder(cfg), pool: buffer.NewPool()}
func newEncoder(cfg zapcore.EncoderConfig, colored bool) *customEncoder {
return &customEncoder{Encoder: zapcore.NewJSONEncoder(cfg), colored: colored, pool: buffer.NewPool()}
}

func (e *customEncoder) Clone() zapcore.Encoder {
return &customEncoder{Encoder: e.Encoder.Clone(), pool: e.pool}
}

func (e *customEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
go func() {
recentMU.Lock()
defer recentMU.Unlock()
RecentLogs = append(RecentLogs, &entry)
if len(RecentLogs) > 50 {
RecentLogs = RecentLogs[1:]
}
}()
b, err := e.Encoder.EncodeEntry(entry, fields)
if err != nil {
return nil, errors.Wrap(err, "logging error")
Expand All @@ -51,7 +58,9 @@ func (e *customEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field)
}

lvl := fmt.Sprintf("%-5v", entry.Level.CapitalString())
lvl = levelToColor[entry.Level.String()].Add(lvl)
if e.colored {
lvl = levelToColor[entry.Level.String()].Add(lvl)
}
tm := entry.Time.Format(timeFormat)

msg := entry.Message
Expand All @@ -62,12 +71,21 @@ func (e *customEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field)
msgLines = msgLines[1:]
}

addLine(fmt.Sprintf("[%s] %s %s", lvl, tm, Cyan.Add(msg)))
if e.colored {
addLine(fmt.Sprintf("[%s] %s %s", lvl, tm, Cyan.Add(msg)))
} else {
addLine(fmt.Sprintf("[%s] %s %s", lvl, tm, msg))
}

lo.ForEach(msgLines, func(ml string, _ int) {
if strings.Contains(ml, util.AppKey) {
ml = Green.Add(ml)
if e.colored {
if strings.Contains(ml, util.AppKey) {
ml = Green.Add(ml)
}
addLine(" " + Cyan.Add(ml))
} else {
addLine(" " + ml)
}
addLine(" " + Cyan.Add(ml))
})
if len(data) > 0 {
addLine(" " + util.ToJSONCompact(data))
Expand All @@ -76,10 +94,6 @@ func (e *customEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field)
if entry.Caller.Function != "" {
caller += " (" + entry.Caller.Function + ")"
}
// idx := strings.Index(caller, "github.com/")
// if idx > 0 {
// caller = caller[idx:]
// }
addLine(" " + caller)

if entry.Stack != "" {
Expand Down
87 changes: 0 additions & 87 deletions app/lib/log/encoderwasm.go

This file was deleted.

9 changes: 8 additions & 1 deletion app/lib/log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
package log

import (
"runtime"
"strings"
"sync"

"github.com/pkg/errors"
"go.uber.org/zap"
Expand All @@ -13,6 +15,11 @@ import (

const keyCustom = "custom"

var (
RecentLogs []*zapcore.Entry
recentMU = &sync.Mutex{}
)

func InitLogging(debug bool) (util.Logger, error) {
var logger *zap.Logger
var err error
Expand All @@ -37,7 +44,7 @@ func CreateTestLogger() (util.Logger, error) {

func initDevLogging(lvl zapcore.Level) (*zap.Logger, error) {
_ = zap.RegisterEncoder(keyCustom, func(cfg zapcore.EncoderConfig) (zapcore.Encoder, error) {
return newEncoder(cfg), nil
return newEncoder(cfg, runtime.GOOS == "js"), nil
})
config := zap.NewDevelopmentConfig()
config.EncoderConfig = zapcore.EncoderConfig{}
Expand Down
43 changes: 43 additions & 0 deletions views/vadmin/Logs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!-- Content managed by Project Forge, see [projectforge.md] for details. -->
<!-- Content managed by Project Forge, see [projectforge.md] for details. -->
{% import (
"go.uber.org/zap/zapcore"

"github.com/kyleu/npn/app"
"github.com/kyleu/npn/app/controller/cutil"
"github.com/kyleu/npn/app/util"
"github.com/kyleu/npn/views/layout"
) %}

{% code type Logs struct {
layout.Basic
Logs []*zapcore.Entry
} %}

{% func (p *Logs) Body(as *app.State, ps *cutil.PageState) %}
<div class="card">
<h3>Recent Logs</h3>
{%= logTable(p.Logs) %}
</div>
{% endfunc %}

{% func logTable(logs []*zapcore.Entry) %}
<table class="mt">
<thead>
<tr>
<th>Level</th>
<th>Message</th>
<th>Occurred</th>
</tr>
</thead>
<tbody>
{%- for _, l := range logs -%}
<tr>
<td>{%s l.Level.String() %}</td>
<td>{%s l.Message %}</td>
<td>{%s util.TimeRelative(&l.Time) %}</td>
</tr>
{%- endfor -%}
</tbody>
</table>
{% endfunc %}
Loading

0 comments on commit 0972878

Please sign in to comment.