1
0
mirror of https://github.com/taigrr/log-socket synced 2025-01-18 04:53:14 -08:00

Compare commits

...

15 Commits

Author SHA1 Message Date
f114098a8c
uodate go version 2023-08-26 22:00:42 -07:00
Ethan Holz
2571dbe347
Add Github Actions for automated testing (#12)
* ci: Added initial github action for automated testing

* fix: changed go version

* ci: updated to change job name to test
2023-05-13 23:27:20 -07:00
80b80758de
Add Default() func 2023-03-29 14:26:06 -07:00
0fa4de7961
Revert "add ability to embed other loggers of varying functionality"
This reverts commit 50c507c8f4d6939d0feda2a5148800e4c9fc5d19.
2023-03-29 14:06:00 -07:00
50c507c8f4
add ability to embed other loggers of varying functionality 2023-03-29 14:02:57 -07:00
e21fb8a614
make pass gofumpt 2022-10-14 22:23:42 -07:00
2492509b6b
extract browser from string var, upgrade deps 2022-10-14 22:14:47 -07:00
a1e960366e
Merge pull request #11 from ethanholz/log-parity
feat: Updated to include print and added ln variants for all logs
2022-10-13 08:05:39 -07:00
Ethan Holz
430181e3a2
feat: Updated to include print and added ln variants for all logs 2022-10-13 09:59:04 -05:00
147a8cb30b
Merge pull request #10 from ethanholz/README
Added a README
2022-10-10 13:38:59 -07:00
Ethan Holz
8e044e3993
docs: Updated README to include running example. 2022-10-10 12:16:52 -05:00
Ethan Holz
e97d37012e
docs: Added inital README 2022-10-10 12:09:29 -05:00
ebef59a9a8
actually set value for depth 2021-08-23 21:58:05 -07:00
b3ceb12277
fixes fileinfo reflection issue 2021-08-23 21:45:08 -07:00
45cad34fdc
fixes fileinfo reflection issue 2021-08-23 21:44:56 -07:00
12 changed files with 551 additions and 253 deletions

24
.github/workflows/ci.yaml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Go package
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.16'
- name: Install dependencies
run: go get .
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...

View File

@ -1,4 +1,4 @@
Copyright (C) 2019-2021 by Tai Groot <tai@taigrr.com>
Copyright (C) 2019-2022 by Tai Groot <tai@taigrr.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

15
README.md Normal file
View File

@ -0,0 +1,15 @@
log-socket
==========
`log-socket` is a drop-in replacement for Go's `log` package that allows for streaming of logs via WebSockets.
## Installation
To install the library:
`go get github.com/taigrr/log-socket`
## Running
To run a demo of this library:
`go run main.go`
This demo will do a sample of every log type and push results to `0.0.0.0:8080`. Once running, you can open a browser and navigate to
`0.0.0.0:8080` to see an example implementation of how logs are streamed.

View File

@ -1,6 +1,7 @@
package browser
import (
_ "embed"
"html/template"
"net/http"
"strings"
@ -17,201 +18,7 @@ func LogSocketViewHandler(w http.ResponseWriter, r *http.Request) {
homeTemplate.Execute(w, wsResource)
}
var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<center>
<input type="text" id="search" onkeyup="filterTable()" placeholder="Filter...">
<input type="checkbox" id="shouldScroll" checked>Enable Autoscroll<br>
<table id="logHeaders" style="text-align:left; width:80%;" >
<tbody>
<tr class="header">
<th style="width:20%;">TimeStamp</th>
<th style="width:5%;">Level</th>
<th style="width:65%;">Output</th>
<th style="width:10%;">Source</th>
</tr>
</tbody>
</table>
//go:embed viewer.html
var webpage string
<div id="tableWrapper">
<table id="logs" style="text-align:left; width:100%;" >
<tbody id="tbodylogs">
<tr class="header">
<th style="width:20%;"></th>
<th style="width:5%;"></th>
<th style="width:65%;"></th>
<th style="width:10%;"></th>
</tr>
</tbody>
</table>
</div>
<br>
<input class="button" type="button" id="download" value="Download Logs" style="background-color:#3f51b5;"/>
<input class="button" type="button" id="delete" value="Delete Logs" style="background-color:#f44336"/>
</center>
</body>
<footer>
<style>
#tableWrapper{
overflow-y: scroll;
display: flow-root;
width: 80%;
height: 80vh;
}
td,tr{
height: min-content;
}
.button{
display: inline-block;
width: 5vw;
height: 5vh;
}
</style>
<script>
var logTable = document.getElementById("logs");
var logTableB = document.getElementById("tbodylogs");
var ws = null;
var application = "demo-commit"
var logs = [];
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function openSocket() {
if (ws) {
return false;
}
ws = new WebSocket("{{.}}");
ws.onclose = async function(evt) {
ws = null;
while(ws == null){
openSocket()
await sleep(5000);
}
}
ws.onmessage = function(evt) {
var entry = JSON.parse(evt.data)
logs.push(entry)
var row = document.createElement('tr');
var ts = document.createElement('td');
var tst = document.createTextNode(entry.timestamp);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.level);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.output);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.file);
ts.appendChild(tst);
row.appendChild(ts);
var bg="";
switch(entry.level){
case "INFO":
bg="white";
break;
case "ERROR":
bg="#f44336";
break;
case "WARN":
bg="#fb8c00"
break;
case "TRACE":
bg="#E1F5FE"
break;
case "DEBUG":
bg="#B3E5FC"
break;
default:
bg="white"
break;
}
row.style.backgroundColor=bg
logTableB.append(row)
filterTable()
}
ws.onerror = function(evt) {
if (evt != null && evt.data != null){
// handle error here
}
}
}
function clearTable(){
if(!window.confirm("Are you sure you want to delete all logs?")){
return
}
logs = []
while (logTableB.childNodes.length > 1) {
logTableB.removeChild(logTableB.childNodes[1]);
}
}
function filterTable() {
var cols, input, filter, table, tr, td, i, txtValue, w;
input = document.getElementById("search");
filter = input.value;
table = logTableB;
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
cols = tr[i].getElementsByTagName("td");
var visible = false;
for (w = 0; w < cols.length; w++){
if (!visible && cols[w]) {
td = cols[w]
txtValue = td.textContent || td.innerText;
if (txtValue.indexOf(filter) > -1) {
visible = true
}
}
}
if(visible){
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
function pageScroll() {
if (document.getElementById('shouldScroll').checked) {
document.getElementById('tableWrapper').scrollBy(0,10);
}
setTimeout(pageScroll,10);
}
document.getElementById("delete").addEventListener("click", function(){
clearTable()
}, false);
document.getElementById("download").addEventListener("click", function(){
download(application+'.json',JSON.stringify(logs));
}, false);
openSocket();
pageScroll();
</script>
</footer>
</html>
`))
var homeTemplate = template.Must(template.New("").Parse(webpage))

196
browser/viewer.html Normal file
View File

@ -0,0 +1,196 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<center>
<input type="text" id="search" onkeyup="filterTable()" placeholder="Filter...">
<input type="checkbox" id="shouldScroll" checked>Enable Autoscroll<br>
<table id="logHeaders" style="text-align:left; width:80%;" >
<tbody>
<tr class="header">
<th style="width:20%;">TimeStamp</th>
<th style="width:5%;">Level</th>
<th style="width:65%;">Output</th>
<th style="width:10%;">Source</th>
</tr>
</tbody>
</table>
<div id="tableWrapper">
<table id="logs" style="text-align:left; width:100%;" >
<tbody id="tbodylogs">
<tr class="header">
<th style="width:20%;"></th>
<th style="width:5%;"></th>
<th style="width:65%;"></th>
<th style="width:10%;"></th>
</tr>
</tbody>
</table>
</div>
<br>
<input class="button" type="button" id="download" value="Download Logs" style="background-color:#3f51b5;"/>
<input class="button" type="button" id="delete" value="Delete Logs" style="background-color:#f44336"/>
</center>
</body>
<footer>
<style>
#tableWrapper{
overflow-y: scroll;
display: flow-root;
width: 80%;
height: 80vh;
}
td,tr{
height: min-content;
}
.button{
display: inline-block;
width: 5vw;
height: 5vh;
}
</style>
<script>
var logTable = document.getElementById("logs");
var logTableB = document.getElementById("tbodylogs");
var ws = null;
var application = "demo-commit"
var logs = [];
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function openSocket() {
if (ws) {
return false;
}
ws = new WebSocket("{{.}}");
ws.onclose = async function(evt) {
ws = null;
while(ws == null){
openSocket()
await sleep(5000);
}
}
ws.onmessage = function(evt) {
var entry = JSON.parse(evt.data)
logs.push(entry)
var row = document.createElement('tr');
var ts = document.createElement('td');
var tst = document.createTextNode(entry.timestamp);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.level);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.output);
ts.appendChild(tst);
row.appendChild(ts);
var ts = document.createElement('td');
var tst = document.createTextNode(entry.file);
ts.appendChild(tst);
row.appendChild(ts);
var bg="";
switch(entry.level){
case "INFO":
bg="white";
break;
case "ERROR":
bg="#f44336";
break;
case "WARN":
bg="#fb8c00"
break;
case "TRACE":
bg="#E1F5FE"
break;
case "DEBUG":
bg="#B3E5FC"
break;
default:
bg="white"
break;
}
row.style.backgroundColor=bg
logTableB.append(row)
filterTable()
}
ws.onerror = function(evt) {
if (evt != null && evt.data != null){
// handle error here
}
}
}
function clearTable(){
if(!window.confirm("Are you sure you want to delete all logs?")){
return
}
logs = []
while (logTableB.childNodes.length > 1) {
logTableB.removeChild(logTableB.childNodes[1]);
}
}
function filterTable() {
var cols, input, filter, table, tr, td, i, txtValue, w;
input = document.getElementById("search");
filter = input.value;
table = logTableB;
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
cols = tr[i].getElementsByTagName("td");
var visible = false;
for (w = 0; w < cols.length; w++){
if (!visible && cols[w]) {
td = cols[w]
txtValue = td.textContent || td.innerText;
if (txtValue.indexOf(filter) > -1) {
visible = true
}
}
}
if(visible){
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
function pageScroll() {
if (document.getElementById('shouldScroll').checked) {
document.getElementById('tableWrapper').scrollBy(0,10);
}
setTimeout(pageScroll,10);
}
document.getElementById("delete").addEventListener("click", function(){
clearTable()
}, false);
document.getElementById("download").addEventListener("click", function(){
download(application+'.json',JSON.stringify(logs));
}, false);
openSocket();
pageScroll();
</script>
</footer>
</html>

4
go.mod
View File

@ -1,5 +1,5 @@
module github.com/taigrr/log-socket
go 1.17
go 1.21
require github.com/gorilla/websocket v1.4.2
require github.com/gorilla/websocket v1.5.0

4
go.sum
View File

@ -1,2 +1,2 @@
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=

View File

@ -26,18 +26,12 @@ func init() {
}
func (c *Client) logStdErr() {
for {
select {
case e, more := <-c.writer:
if e.level >= c.LogLevel {
fmt.Fprintf(os.Stderr, "%s\t%s\t%s\t%s\n", e.Timestamp.String(), e.Level, e.Output, e.File)
}
if !more {
stderrFinished <- true
return
}
for e := range c.writer {
if e.level >= c.LogLevel {
fmt.Fprintf(os.Stderr, "%s\t%s\t%s\t%s\n", e.Timestamp.String(), e.Level, e.Output, e.File)
}
}
stderrFinished <- true
}
func CreateClient() *Client {
@ -61,7 +55,7 @@ func Flush() {
func (c *Client) Destroy() error {
var otherClients []*Client
if !c.initialized {
panic(errors.New("Cannot delete uninitialized client, did you use CreateClient?"))
panic(errors.New("cannot delete uninitialized client, did you use CreateClient?"))
}
sliceTex.Lock()
c.writer = nil
@ -78,7 +72,7 @@ func (c *Client) Destroy() error {
func (c *Client) GetLogLevel() Level {
if !c.initialized {
panic(errors.New("Cannot get level for uninitialized client, use CreateClient instead"))
panic(errors.New("cannot get level for uninitialized client, use CreateClient instead"))
}
return c.LogLevel
}
@ -109,14 +103,14 @@ func SetLogLevel(level Level) {
// SetLogLevel set log level of logger
func (c *Client) SetLogLevel(level Level) {
if !c.initialized {
panic(errors.New("Cannot set level for uninitialized client, use CreateClient instead"))
panic(errors.New("cannot set level for uninitialized client, use CreateClient instead"))
}
c.LogLevel = level
}
func (c *Client) Get() Entry {
if !c.initialized {
panic(errors.New("Cannot get logs for uninitialized client, did you use CreateClient?"))
panic(errors.New("cannot get logs for uninitialized client, did you use CreateClient?"))
}
return <-c.writer
}
@ -147,6 +141,19 @@ func Tracef(format string, args ...interface{}) {
createLog(e)
}
// Trace prints out logs on trace level with newline
func Traceln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "TRACE",
level: LTrace,
}
createLog(e)
}
// Debug prints out logs on debug level
func Debug(args ...interface{}) {
output := fmt.Sprint(args...)
@ -173,6 +180,19 @@ func Debugf(format string, args ...interface{}) {
createLog(e)
}
// Debug prints out logs on debug level with a newline
func Debugln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "DEBUG",
level: LDebug,
}
createLog(e)
}
// Info prints out logs on info level
func Info(args ...interface{}) {
output := fmt.Sprint(args...)
@ -199,6 +219,19 @@ func Infof(format string, args ...interface{}) {
createLog(e)
}
// Info prints out logs on info level with a newline
func Infoln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "INFO",
level: LInfo,
}
createLog(e)
}
// Info prints out logs on info level
func Notice(args ...interface{}) {
output := fmt.Sprint(args...)
@ -225,6 +258,19 @@ func Noticef(format string, args ...interface{}) {
createLog(e)
}
// Info prints out logs on info level with a newline
func Noticeln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "NOTICE",
level: LNotice,
}
createLog(e)
}
// Warn prints out logs on warn level
func Warn(args ...interface{}) {
output := fmt.Sprint(args...)
@ -251,6 +297,19 @@ func Warnf(format string, args ...interface{}) {
createLog(e)
}
// Newline print for Warn
func Warnln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "WARN",
level: LWarn,
}
createLog(e)
}
// Error prints out logs on error level
func Error(args ...interface{}) {
output := fmt.Sprint(args...)
@ -277,6 +336,19 @@ func Errorf(format string, args ...interface{}) {
createLog(e)
}
// Error prints out logs on error level with a newline
func Errorln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "ERROR",
level: LError,
}
createLog(e)
}
// Panic prints out logs on panic level
func Panic(args ...interface{}) {
output := fmt.Sprint(args...)
@ -323,6 +395,28 @@ func Panicf(format string, args ...interface{}) {
panic(errors.New(output))
}
func Panicln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "PANIC",
level: LPanic,
}
createLog(e)
if len(args) >= 0 {
switch args[0].(type) {
case error:
panic(args[0])
default:
// falls through to default below
}
}
Flush()
panic(errors.New(output))
}
// Fatal prints out logs on fatal level
func Fatal(args ...interface{}) {
output := fmt.Sprint(args...)
@ -353,6 +447,32 @@ func Fatalf(format string, args ...interface{}) {
os.Exit(1)
}
func Fatalln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
Level: "FATAL",
level: LFatal,
}
createLog(e)
Flush()
os.Exit(1)
}
func Print(args ...interface{}) {
Info(args...)
}
func Printf(format string, args ...interface{}) {
Infof(format, args...)
}
func Println(args ...interface{}) {
Infoln(args...)
}
// fileInfo for getting which line in which file
func fileInfo(skip int) string {
_, file, line, ok := runtime.Caller(skip)

View File

@ -55,8 +55,7 @@ func BenchmarkDebugSerial(b *testing.B) {
// Trace ensure logs come out in the right order
func TestOrder(t *testing.T) {
testString := "Testing trace: "
var c *Client
c = CreateClient()
c := CreateClient()
c.SetLogLevel(LTrace)
for i := 0; i < 5000; i++ {
@ -86,6 +85,15 @@ func TestInfo(t *testing.T) {
// }
}
// Print prints out logs on info level
func TestPrint(t *testing.T) {
// if logLevel >= LInfo {
// entry := logger.WithFields(logrus.Fields{})
// entry.Data["file"] = fileInfo(2)
// entry.Info(args...)
// }
}
// Warn prints out logs on warn level
func TestWarn(t *testing.T) {
// if logLevel >= LWarn {
@ -121,6 +129,7 @@ func TestPanic(t *testing.T) {
// entry.Panic(args...)
// }
}
func TestFlush(t *testing.T) {
defer Flush()
}

View File

@ -7,13 +7,21 @@ import (
"time"
)
func Default() *Logger {
return &Logger{FileInfoDepth: 0}
}
func (l *Logger) SetInfoDepth(depth int) {
l.FileInfoDepth = depth
}
// Trace prints out logs on trace level
func (_ Logger) Trace(args ...interface{}) {
func (l Logger) Trace(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "TRACE",
level: LTrace,
}
@ -21,12 +29,25 @@ func (_ Logger) Trace(args ...interface{}) {
}
// Formatted print for Trace
func (_ Logger) Tracef(format string, args ...interface{}) {
func (l Logger) Tracef(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "TRACE",
level: LTrace,
}
createLog(e)
}
// Trace prints out logs on trace level with newline
func (l Logger) Traceln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "TRACE",
level: LTrace,
}
@ -34,12 +55,12 @@ func (_ Logger) Tracef(format string, args ...interface{}) {
}
// Debug prints out logs on debug level
func (_ Logger) Debug(args ...interface{}) {
func (l Logger) Debug(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "DEBUG",
level: LDebug,
}
@ -47,12 +68,12 @@ func (_ Logger) Debug(args ...interface{}) {
}
// Formatted print for Debug
func (_ Logger) Debugf(format string, args ...interface{}) {
func (l Logger) Debugf(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "DEBUG",
level: LDebug,
}
@ -60,12 +81,12 @@ func (_ Logger) Debugf(format string, args ...interface{}) {
}
// Info prints out logs on info level
func (_ Logger) Info(args ...interface{}) {
func (l Logger) Info(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "INFO",
level: LInfo,
}
@ -73,38 +94,64 @@ func (_ Logger) Info(args ...interface{}) {
}
// Formatted print for Info
func (_ Logger) Infof(format string, args ...interface{}) {
func (l Logger) Infof(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "INFO",
level: LInfo,
}
createLog(e)
}
// Info prints out logs on info level
func (_ Logger) Notice(args ...interface{}) {
// Info prints out logs on info level with newline
func (l Logger) Infoln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "INFO",
level: LInfo,
}
createLog(e)
}
// Notice prints out logs on notice level
func (l Logger) Notice(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "NOTICE",
level: LNotice,
}
createLog(e)
}
// Formatted print for Info
func (_ Logger) Noticef(format string, args ...interface{}) {
// Formatted print for Notice
func (l Logger) Noticef(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "NOTICE",
level: LNotice,
}
createLog(e)
}
// Notice prints out logs on notice level with newline
func (l Logger) Noticeln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "NOTICE",
level: LNotice,
}
@ -112,12 +159,12 @@ func (_ Logger) Noticef(format string, args ...interface{}) {
}
// Warn prints out logs on warn level
func (_ Logger) Warn(args ...interface{}) {
func (l Logger) Warn(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "WARN",
level: LWarn,
}
@ -125,12 +172,25 @@ func (_ Logger) Warn(args ...interface{}) {
}
// Formatted print for Warn
func (_ Logger) Warnf(format string, args ...interface{}) {
func (l Logger) Warnf(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "WARN",
level: LWarn,
}
createLog(e)
}
// Warn prints out logs on warn level with a newline
func (l Logger) Warnln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "WARN",
level: LWarn,
}
@ -138,12 +198,12 @@ func (_ Logger) Warnf(format string, args ...interface{}) {
}
// Error prints out logs on error level
func (_ Logger) Error(args ...interface{}) {
func (l Logger) Error(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "ERROR",
level: LError,
}
@ -151,12 +211,25 @@ func (_ Logger) Error(args ...interface{}) {
}
// Formatted print for error
func (_ Logger) Errorf(format string, args ...interface{}) {
func (l Logger) Errorf(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "ERROR",
level: LError,
}
createLog(e)
}
// Error prints out logs on error level with a new line
func (l Logger) Errorln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "ERROR",
level: LError,
}
@ -164,12 +237,12 @@ func (_ Logger) Errorf(format string, args ...interface{}) {
}
// Panic prints out logs on panic level
func (_ Logger) Panic(args ...interface{}) {
func (l Logger) Panic(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "PANIC",
level: LPanic,
}
@ -187,12 +260,35 @@ func (_ Logger) Panic(args ...interface{}) {
}
// Formatted print for panic
func (_ Logger) Panicf(format string, args ...interface{}) {
func (l Logger) Panicf(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "PANIC",
level: LPanic,
}
createLog(e)
if len(args) >= 0 {
switch args[0].(type) {
case error:
panic(args[0])
default:
// falls through to default below
}
}
Flush()
panic(errors.New(output))
}
// Panic prints out logs on panic level with a newline
func (l Logger) Panicln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "PANIC",
level: LPanic,
}
@ -210,12 +306,12 @@ func (_ Logger) Panicf(format string, args ...interface{}) {
}
// Fatal prints out logs on fatal level
func (_ Logger) Fatal(args ...interface{}) {
func (l Logger) Fatal(args ...interface{}) {
output := fmt.Sprint(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "FATAL",
level: LFatal,
}
@ -225,12 +321,12 @@ func (_ Logger) Fatal(args ...interface{}) {
}
// Formatted print for fatal
func (_ Logger) Fatalf(format string, args ...interface{}) {
func (l Logger) Fatalf(format string, args ...interface{}) {
output := fmt.Sprintf(format, args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(2),
File: fileInfo(l.FileInfoDepth),
Level: "FATAL",
level: LFatal,
}
@ -238,3 +334,33 @@ func (_ Logger) Fatalf(format string, args ...interface{}) {
Flush()
os.Exit(1)
}
// Fatal prints fatal level with a new line
func (l Logger) Fatalln(args ...interface{}) {
output := fmt.Sprintln(args...)
e := Entry{
Timestamp: time.Now(),
Output: output,
File: fileInfo(l.FileInfoDepth),
Level: "FATAL",
level: LFatal,
}
createLog(e)
Flush()
os.Exit(1)
}
// Handles print to info
func (l Logger) Print(args ...interface{}) {
l.Info(args...)
}
// Handles formatted print to info
func (l Logger) Printf(format string, args ...interface{}) {
l.Infof(format, args...)
}
// Handles print to info with new line
func (l Logger) Println(args ...interface{}) {
l.Infoln(args...)
}

View File

@ -31,4 +31,5 @@ type Entry struct {
}
type Logger struct {
FileInfoDepth int
}

View File

@ -25,7 +25,7 @@ func LogSocketHandler(w http.ResponseWriter, r *http.Request) {
logger.Info("Websocket client attached.")
for {
logEvent := lc.Get()
logJSON, err := json.Marshal(logEvent)
logJSON, _ := json.Marshal(logEvent)
err = c.WriteMessage(websocket.TextMessage, logJSON)
if err != nil {
logger.Error("write:", err)