update lol to actually work, and make this actually a go repo

This commit is contained in:
2025-01-30 11:46:26 -01:06
parent 0448f28cc3
commit a0a6bf9c96
5 changed files with 391 additions and 3 deletions

16
go.mod Normal file
View File

@@ -0,0 +1,16 @@
module protocol.realy.lol
go 1.23.4
require (
github.com/davecgh/go-spew v1.1.1
github.com/fatih/color v1.18.0
go.uber.org/atomic v1.11.0
)
require (
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/stretchr/testify v1.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
)

19
go.sum Normal file
View File

@@ -0,0 +1,19 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

316
pkg/lol/log.go Normal file
View File

@@ -0,0 +1,316 @@
package lol
import (
"fmt"
"io"
"os"
"runtime"
"strings"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/fatih/color"
"go.uber.org/atomic"
)
const (
Off = iota
Fatal
Error
Warn
Info
Debug
Trace
)
var LevelNames = []string{
"off",
"fatal",
"error",
"warn",
"info",
"debug",
"trace",
}
type (
// LevelPrinter defines a set of terminal printing primitives that output with
// extra data, time, log logLevelList, and code location
// Ln prints lists of interfaces with spaces in between
Ln func(a ...interface{})
// F prints like fmt.Println surrounded []byte log details
F func(format string, a ...interface{})
// S prints a spew.Sdump for an enveloper slice
S func(a ...interface{})
// C accepts a function so that the extra computation can be avoided if it is
// not being viewed
C func(closure func() string)
// Chk is a shortcut for printing if there is an error, or returning true
Chk func(e error) bool
// Err is a pass-through function that uses fmt.Errorf to construct an error
// and returns the error after printing it to the log
Err func(format string, a ...interface{}) error
LevelPrinter struct {
Ln
F
S
C
Chk
Err
}
LevelSpec struct {
ID int
Name string
Colorizer func(a ...interface{}) string
}
// Entry is a log entry to be printed as json to the log file
Entry struct {
Time time.Time
Level string
Package string
CodeLocation string
Text string
}
)
var (
// sep is just a convenient shortcut for this very longwinded expression
sep = string(os.PathSeparator)
// writer can be swapped out for any io.*writer* that you want to use instead of
// stdout.
writer io.Writer = os.Stderr
// LevelSpecs specifies the id, string name and color-printing function
LevelSpecs = []LevelSpec{
{Off, "", NoSprint},
{Fatal, "FTL", color.New(color.BgRed, color.FgHiWhite).Sprint},
{Error, "ERR", color.New(color.FgHiRed).Sprint},
{Warn, "WRN", color.New(color.FgHiYellow).Sprint},
{Info, "INF", color.New(color.FgHiGreen).Sprint},
{Debug, "DBG", color.New(color.FgHiBlue).Sprint},
{Trace, "TRC", color.New(color.FgHiMagenta).Sprint},
}
NoTimeStomp atomic.Bool
)
func NoSprint(a ...any) string { return "" }
// Log is a set of log printers for the various Level items.
type Log struct {
F, E, W, I, D, T LevelPrinter
}
type Check struct {
F, E, W, I, D, T Chk
}
type Errorf struct {
F, E, W, I, D, T Err
}
type Logger struct {
*Log
*Check
*Errorf
}
var Level atomic.Int32
var Main = &Logger{}
func init() {
// Main = &Logger{}
Main.Log, Main.Check, Main.Errorf = New(os.Stderr)
SetLoggers(Info)
}
func SetLoggers(level int) {
Main.Log.T.F("log level %s", LevelSpecs[level].Colorizer(LevelNames[level]))
Level.Store(int32(level))
}
func GetLogLevel(level string) (i int) {
for i = range LevelNames {
if level == LevelNames[i] {
return i
}
}
return Info
}
func SetLogLevel(level string) {
for i := range LevelNames {
if level == LevelNames[i] {
SetLoggers(i)
return
}
}
}
func JoinStrings(a ...any) (s string) {
for i := range a {
s += fmt.Sprint(a[i])
if i < len(a)-1 {
s += " "
}
}
return
}
var msgCol = color.New(color.FgBlue).Sprint
func GetPrinter(l int32, writer io.Writer) LevelPrinter {
return LevelPrinter{
Ln: func(a ...interface{}) {
if Level.Load() < l {
return
}
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name),
JoinStrings(a...),
msgCol(GetLoc(2)),
)
},
F: func(format string, a ...interface{}) {
if Level.Load() < l {
return
}
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name),
fmt.Sprintf(format, a...),
msgCol(GetLoc(2)),
)
},
S: func(a ...interface{}) {
if Level.Load() < l {
return
}
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name),
spew.Sdump(a...),
msgCol(GetLoc(2)),
)
},
C: func(closure func() string) {
if Level.Load() < l {
return
}
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name),
closure(),
msgCol(GetLoc(2)),
)
},
Chk: func(e error) bool {
if Level.Load() < l {
return e != nil
}
if e != nil {
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name),
e.Error(),
msgCol(GetLoc(2)),
)
return true
}
return false
},
Err: func(format string, a ...interface{}) error {
if Level.Load() < l {
fmt.Fprintf(writer,
"%s%s %s %s\n",
msgCol(Timestamper()),
LevelSpecs[l].Colorizer(LevelSpecs[l].Name, " "),
fmt.Sprintf(format, a...),
msgCol(GetLoc(2)),
)
}
return fmt.Errorf(format, a...)
},
}
}
func GetNullPrinter() LevelPrinter {
return LevelPrinter{
Ln: func(a ...interface{}) {},
F: func(format string, a ...interface{}) {},
S: func(a ...interface{}) {},
C: func(closure func() string) {},
Chk: func(e error) bool { return e != nil },
Err: func(format string, a ...interface{}) error { return fmt.Errorf(format, a...) },
}
}
func New(writer io.Writer) (l *Log, c *Check, errorf *Errorf) {
l = &Log{
T: GetPrinter(Trace, writer),
D: GetPrinter(Debug, writer),
I: GetPrinter(Info, writer),
W: GetPrinter(Warn, writer),
E: GetPrinter(Error, writer),
F: GetPrinter(Fatal, writer),
}
c = &Check{
F: l.F.Chk,
E: l.E.Chk,
W: l.W.Chk,
I: l.I.Chk,
D: l.D.Chk,
T: l.T.Chk,
}
errorf = &Errorf{
F: l.F.Err,
E: l.E.Err,
W: l.W.Err,
I: l.I.Err,
D: l.D.Err,
T: l.T.Err,
}
return
}
// Timestamper e
func Timestamper() (s string) {
if NoTimeStomp.Load() {
return
}
timeText := fmt.Sprint(time.Now().UnixNano())
lt := len(timeText)
lb := lt + 1
var timeBytes = make([]byte, lb)
copy(timeBytes[lb-9:lb], timeText[lt-9:lt])
timeBytes[lb-10] = '.'
lb -= 10
lt -= 9
copy(timeBytes[:lb], timeText[:lt])
return fmt.Sprint(string(timeBytes), " ")
}
var wd, _ = os.Getwd()
func GetNLoc(n int) (output string) {
for ; n > 1; n-- {
output += fmt.Sprintf("%s\n", GetLoc(n))
}
return
}
func GetLoc(skip int) (output string) {
_, file, line, _ := runtime.Caller(skip)
split := strings.Split(file, wd+string(os.PathSeparator))
if len(split) < 2 {
output = fmt.Sprintf("%s:%d", file, line)
} else {
output = fmt.Sprintf("%s:%d", split[1], line)
}
return
}

35
pkg/lol/readme.md Normal file
View File

@@ -0,0 +1,35 @@
# lol
location of log
This is a very simple, but practical library for logging in applications. Its
main feature is printing source code locations to make debugging easier.
## usage
put this somewhere in your package:
```go
var log, chk, errorf = lol.Main.Log, lol.Main.Check, lol.Main.Errorf
```
then you can invoke like this:
```go
log.I.S(spew.this.thing)
errorf.E("print and return this error")
if err = bogus; chk.E(err) { return bogus.response } // print an error at the site and return the error
```
## terminals
Due to how so few terminals actually support source location hyperlinks, pretty much tilix and intellij terminal are
the only two that really provide adequate functionality, this logging library defaults to output format that works
best with intellij. As such, the terminal is aware of the CWD and the code locations printed are relative, as
required to get the hyperlinkization from this terminal. Handling support for Tilix requires more complications and
due to advances with IntelliJ's handling it is not practical to support any other for this purpose. Users of this
library can always fall back to manually interpreting and accessing the relative file path to find the source of a log.
In addition, due to this terminal's slow rendering of long lines, long log strings are automatically broken into 80
character lines, and if there is comma separators in the line, the line is broken at the comma instead of at
column80. This works perfectly for this purpose.

View File

@@ -1,14 +1,16 @@
# R.E.A.L.Y. Protocol # R.E.A.L.Y. Protocol
> relay events and like yeah > relay events and like... yeah
relay events and like yeah protocol [![Documentation](https://img.shields.io/badge/godoc-documentation-blue.svg)](https://pkg.go.dev/protocol.realy.lol)
[![matrix chat](https://img.shields.io/badge/matrix-chat-green.svg)](https://matrix.to/#/#realy-general:matrix.org)
zap mleku: ⚡mleku@getalby.com
Inspired by the event bus architecture of [nostr](https://github.com/nostr-protocol) but redesigned to avoid the serious deficiencies of that protocol for both developers and users. Inspired by the event bus architecture of [nostr](https://github.com/nostr-protocol) but redesigned to avoid the serious deficiencies of that protocol for both developers and users.
- [why](./why.md) - [why](./why.md)
- [event spec](./spec.md) - [event spec](./spec.md)
- [matrix chat](https://matrix.to/#/#realy-general:matrix.org)
- [reference relays](./relays/readme.md) - [reference relays](./relays/readme.md)
- [reference clients](./clients/readme.md) - [reference clients](./clients/readme.md)
- [GO libraries](./pkg/readme.md) - [GO libraries](./pkg/readme.md)