dog

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2020 License: MIT Imports: 16 Imported by: 0

README

Dog

A logger that spins up a web browser and sends logs in real-time via websocket.

How to Build

  1. If you don't already have it, install a recent version of Go.
  2. If you are on Windows, you'll want a bash shell.
  3. In bash, cd into the path where you cloned this repo, then run ./build-dev.sh, which does the following:
    • rebuilds/installs bpak.exe, if needed
    • regenerates the bpak'd html/jss/cs files
    • runs tests
    • builds cmd/example, writing the output to local/example[.exe].
  4. Run local/example[.exe], then point a web browser at localhost:8080

I've also been playing with Air for hot-reloading. I created my own fork/branch to pull in an unmerged PR, and added a quick install script.

TODO

  • mark a field as "global", showing it in a static position, and not after the log lines where it appears
    • should this be on the server's side or a client ui?
  • structured data filters
    • add filter for specific fields that must exist
    • add way to filter on field values (exact, and ranges for numbers)
  • resizable column widths
  • Add options to periodically send memory/gc stats to the web viewer
    • maybe a generic system for adding named fields and displaying them on the sidebar?
  • Instead of mirroring frog's interface, maybe make it a module that requires frog to work?
  • add multiple filters that can be quickly switched between
  • add highlights in addition to filters, for adding custom background colors to rows containing specific terms
  • cleanup http server and any open connections on Close()
  • add visually distinct formatting for fatal log lines
  • save captured logs to text ndjson file
  • add toggles for log levels
  • add simple text filter (or regex?)
  • "currently visible" -> "active lines", then add "visible" as readonly display of actually visible lines
  • auto reload on connection if web page found to be out of date
  • display structured data ("fields")
  • infinity scroll
      // source: https://www.javascripttutorial.net/dom/css/check-if-an-element-is-visible-in-the-viewport/
      const isInViewport = (element) => {
        const rect = element.getBoundingClientRect();
        return (
          rect.top >= 0 &&
          rect.left >= 0 &&
          rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
          rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
      }
    
      scroll_parent.addEventListener('scroll',
        () => {
          let str = '----- ';
          let nodes = log_line_parent.children;
          for (let i = 0; i < nodes.length; i++) {
            if (isInViewport(nodes[i])) {
              str += '#';
            } else {
              str += '_';
            }
          }
          dlog(str);
        },
        { passive: true },
      );
    

License

See LICENSE.txt for the current license. License may change in the future.

Thanks to the MIT licensed software that I use, including:

* Halfmoon JS
* Version: 1.1.1
* https://www.gethalfmoon.com
* Copyright, Halfmoon UI
* Licensed under MIT (https://www.gethalfmoon.com/license)
* FileSaver.js
* A saveAs() FileSaver implementation.
*
* By Eli Grey, http://eligrey.com
*
* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
* source  : http://purl.eligrey.com/github/FileSaver.js

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetClientMsgHandler

func SetClientMsgHandler(l Logger, fn func(m WsMsg))

Types

type ChildLogger

type ChildLogger interface {
	// Parent returns the parent Logger, or nil if it has no parent.
	Parent() Logger
}

ChildLogger is the interface for loggers that feed back to a parent.

type Dog

type Dog struct {
	// contains filtered or unexported fields
}

func Create

func Create(host string) (*Dog, error)

func (*Dog) Close

func (d *Dog) Close()

Close is part of the Logger interface

func (*Dog) Error

func (d *Dog) Error(format string, a ...Fielder) Logger

Error is part of the Logger interface

func (*Dog) Fatal

func (d *Dog) Fatal(format string, a ...Fielder)

Fatal is part of the Logger interface

func (*Dog) Info

func (d *Dog) Info(format string, a ...Fielder) Logger

Info is part of the Logger interface

func (*Dog) Log

func (d *Dog) Log(level Level, msg string, fields ...Fielder) Logger

Log is part of the Logger interface

func (*Dog) SetMinLevel

func (d *Dog) SetMinLevel(level Level) Logger

SetMinLevel is part of the Logger interface

func (*Dog) Transient

func (d *Dog) Transient(format string, a ...Fielder) Logger

Transient is part of the Logger interface

func (*Dog) Verbose

func (d *Dog) Verbose(format string, a ...Fielder) Logger

Verbose is part of the Logger interface

func (*Dog) Warning

func (d *Dog) Warning(format string, a ...Fielder) Logger

Warning is part of the Logger interface

type Field

type Field struct {
	IsJSONString bool // if true, the string in Value should be bookended by double quotes to be valid JSON
	IsJSONSafe   bool // if true, this string only contains alpha-numerics, spaces, and safe punctuation
	Name         string
	Value        string
	Raw          interface{}
}

type FieldBool

type FieldBool struct {
	Name  string
	Value bool
}

func Bool

func Bool(name string, value bool) FieldBool

Bool adds a field whose value will be true or false

func (FieldBool) Field

func (f FieldBool) Field() Field

type FieldDuration

type FieldDuration struct {
	Name  string
	Value time.Duration
}

func Dur

func Dur(name string, value time.Duration) FieldDuration

Dur adds a time.Duration field

func Duration

func Duration(name string, value time.Duration) FieldDuration

Duration adds a time.Duration field

func (FieldDuration) Field

func (f FieldDuration) Field() Field

type FieldError

type FieldError struct {
	Name  string
	Value error
}

func Err

func Err(value error) FieldError

Err adds an error field named "error"

func (FieldError) Field

func (f FieldError) Field() Field

type FieldFloat64

type FieldFloat64 struct {
	Name  string
	Value float64
}

func Float32

func Float32(name string, value float32) FieldFloat64

Float32 adds a 32-bit floating point number field

func Float64

func Float64(name string, value float64) FieldFloat64

Float64 adds a 64-bit floating point number field

func (FieldFloat64) Field

func (f FieldFloat64) Field() Field

type FieldInt64

type FieldInt64 struct {
	Name  string
	Value int64
}

func Int

func Int(name string, value int) FieldInt64

Int adds a signed integer field

func Int16

func Int16(name string, value int16) FieldInt64

Int16 adds a 16-bit signed integer field

func Int32

func Int32(name string, value int32) FieldInt64

Int32 adds a 32-bit signed integer field

func Int64

func Int64(name string, value int64) FieldInt64

Int64 adds a 64-bit signed integer field

func Int8

func Int8(name string, value int8) FieldInt64

Int8 adds an 8-bit signed integer field

func (FieldInt64) Field

func (f FieldInt64) Field() Field

type FieldString

type FieldString struct {
	Name  string
	Value string
}

func String

func String(name string, value string) FieldString

String adds an escaped and quoted string field

func (FieldString) Field

func (f FieldString) Field() Field

type FieldTimeFormat

type FieldTimeFormat struct {
	Name   string
	Value  time.Time
	Format string
}

func Time

func Time(name string, value time.Time) FieldTimeFormat

Time adds a time.Time field that will output a string formatted using RFC 3339 (ISO 8601)

func TimeNano

func TimeNano(name string, value time.Time) FieldTimeFormat

TimeNano adds a time.Time field that will output a string formatted using RFC 3339 with nanosecond precision

func (FieldTimeFormat) Field

func (f FieldTimeFormat) Field() Field

type FieldTimeUnix

type FieldTimeUnix struct {
	Name  string
	Value time.Time
	Nano  bool
}

func TimeUnix

func TimeUnix(name string, value time.Time) FieldTimeUnix

TimeUnix adds a time.Time field that outputs as a unix epoch (unsigned integer)

func TimeUnixNano

func TimeUnixNano(name string, value time.Time) FieldTimeUnix

TimeUnixNano adds a time.Time field that outputs as a unix epoch with nanosecond precision (unsigned integer)

func (FieldTimeUnix) Field

func (f FieldTimeUnix) Field() Field

type FieldUint64

type FieldUint64 struct {
	Name  string
	Value uint64
}

func Byte

func Byte(name string, value byte) FieldUint64

Byte adds an 8-bit unsigned integer field

func Uint

func Uint(name string, value uint) FieldUint64

Uint adds an unsigned integer field

func Uint16

func Uint16(name string, value uint16) FieldUint64

Uint16 adds a 16-bit unsigned integer field

func Uint32

func Uint32(name string, value uint32) FieldUint64

Uint32 adds a 32-bit unsigned integer field

func Uint64

func Uint64(name string, value uint64) FieldUint64

Uint64 adds a 64-bit unsigned integer field

func Uint8

func Uint8(name string, value uint8) FieldUint64

Uint8 adds an 8-bit unsigned integer field

func (FieldUint64) Field

func (f FieldUint64) Field() Field

type Fielder

type Fielder interface {
	Field() Field
}

Fielder is an interface used to add structured logging to calls to Logger methods

type FixedLineAdder

type FixedLineAdder interface {
	AddFixedLine() Logger
}

FixedLineAdder is the interface for loggers that support fixing a line in place, for progress bars or other transient status messages.

type FixedLineRemover

type FixedLineRemover interface {
	RemoveFixedLine()
}

FixedLineRemover is the interface that a fixed line logger must implement in order for the fixed line to be removed before app end.

type IndexTemplate

type IndexTemplate struct {
	AppBase   string
	AppPath   string
	HostName  string
	WsAddr    string
	IndexHash string
}

type Level

type Level byte
const (
	Transient Level = iota // strictly unimportant, ie progress bars, real-time byte counts, estimated time remaining, etc
	Verbose                // debugging info
	Info                   // normal message
	Warning                // something unusual happened
	Error                  // something bad happened
	Fatal                  // stop everything right now

)

func (Level) String

func (l Level) String() string

type LogLine

type LogLine struct {
	Time   time.Time              `json:"timestamp"`
	Level  string                 `json:"level"`
	Msg    string                 `json:"msg"`
	Fields map[string]interface{} `json:"fields"`
}

type Logger

type Logger interface {
	// Close ensures any buffers are flushed and any resources released.
	// It is safe to call Close more than once (but consecutive calls do nothing).
	Close()

	// SetMinLevel sets the lowest Level that will be logged.
	SetMinLevel(level Level) Logger

	// Log is how all log lines are added.
	Log(level Level, format string, a ...Fielder) Logger

	// Transient et al are just shortcuts for calling Log with specific levels.
	// Note that Fatal will never return, as it flushes any buffers then calls os.Exit(-1).
	Transient(format string, a ...Fielder) Logger
	Verbose(format string, a ...Fielder) Logger
	Info(format string, a ...Fielder) Logger
	Warning(format string, a ...Fielder) Logger
	Error(format string, a ...Fielder) Logger
	Fatal(format string, a ...Fielder)
}

type MemFile

type MemFile struct {
	Bytes  []byte
	Name   string
	Offset int64
}

MemFile implements http.File interface

func (*MemFile) Close

func (f *MemFile) Close() error

func (*MemFile) Read

func (f *MemFile) Read(p []byte) (n int, err error)

func (*MemFile) Readdir

func (f *MemFile) Readdir(count int) ([]os.FileInfo, error)

func (*MemFile) Seek

func (f *MemFile) Seek(offset int64, whence int) (int64, error)

func (*MemFile) Stat

func (f *MemFile) Stat() (os.FileInfo, error)

type MemFileInfo

type MemFileInfo struct {
	FileName string
	FileSize int64
}

func (*MemFileInfo) IsDir

func (i *MemFileInfo) IsDir() bool

func (*MemFileInfo) ModTime

func (i *MemFileInfo) ModTime() time.Time

func (*MemFileInfo) Mode

func (i *MemFileInfo) Mode() os.FileMode

func (*MemFileInfo) Name

func (i *MemFileInfo) Name() string

func (*MemFileInfo) Size

func (i *MemFileInfo) Size() int64

func (*MemFileInfo) Sys

func (i *MemFileInfo) Sys() interface{}

type NullLogger

type NullLogger struct {
}

func (*NullLogger) Close

func (n *NullLogger) Close()

func (*NullLogger) Error

func (n *NullLogger) Error(format string, a ...Fielder) Logger

func (*NullLogger) Fatal

func (n *NullLogger) Fatal(format string, a ...Fielder)

func (*NullLogger) Info

func (n *NullLogger) Info(format string, a ...Fielder) Logger

func (*NullLogger) Log

func (n *NullLogger) Log(level Level, format string, a ...Fielder) Logger

func (*NullLogger) SetMinLevel

func (n *NullLogger) SetMinLevel(level Level) Logger

func (*NullLogger) Transient

func (n *NullLogger) Transient(format string, a ...Fielder) Logger

func (*NullLogger) Verbose

func (n *NullLogger) Verbose(format string, a ...Fielder) Logger

func (*NullLogger) Warning

func (n *NullLogger) Warning(format string, a ...Fielder) Logger

type WsClient

type WsClient struct {
	// contains filtered or unexported fields
}

WsClient holds the open connection to individual websocket clients. It manages reading, writing, and lifetime.

func CreateWsClient

func CreateWsClient(conn *websocket.Conn, owner *WsRouter) *WsClient

func (*WsClient) BeginShutDown

func (c *WsClient) BeginShutDown()

BeginShutDown requests that this client shut itself down. BeginShutDown will nop if called after client begins shutting down.

func (*WsClient) Send

func (c *WsClient) Send(msg json.RawMessage)

Send is a thread-safe call to send a message to this client. Send will nop if called after client begins shutting down.

func (*WsClient) WaitForShutDown

func (c *WsClient) WaitForShutDown()

Close breaks the connection, waits for everything to halt, then updates the owner.

type WsMsg

type WsMsg struct {
	Router *WsRouter
	Client *WsClient
	Msg    []byte
}

type WsRouter

type WsRouter struct {
	// contains filtered or unexported fields
}

func NewWsRouter

func NewWsRouter(indexHash string) *WsRouter

NewWsRouter creates a new WsRouter type

func (*WsRouter) BeginShutdown

func (r *WsRouter) BeginShutdown()

func (*WsRouter) Broadcast

func (r *WsRouter) Broadcast(msg json.RawMessage)

func (*WsRouter) SetClientMsgHandler

func (r *WsRouter) SetClientMsgHandler(fn func(WsMsg))

func (*WsRouter) Start

func (r *WsRouter) Start()

Start our websocket router, accepting various requests

func (*WsRouter) WaitForShutdown

func (r *WsRouter) WaitForShutdown()

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL