Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file. //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
package logging
import (
"encoding/binary"
"io"
"math"
"syscall/js"
"github.com/hack-pad/safejs"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/xxdk-wasm/worker"
)
// threadLogger manages the recording of jwalterweatherman logs from a worker to
// the in-memory file buffer in a remote Worker thread.
type threadLogger struct {
threshold jww.Threshold
mm *worker.MessageManager
}
// newThreadLogger starts logging to an in-memory log file in a remote Worker
// at the specified threshold. Returns a [threadLogger] that can be used to get
// the log file.
func newThreadLogger(threshold jww.Threshold, channelName string,
messagePort js.Value) (*threadLogger, error) {
p := worker.DefaultParams()
p.MessageLogging = false
mm, err := worker.NewMessageManager(safejs.Safe(messagePort),
channelName+"-worker", p)
if err != nil {
return nil, err
}
tl := &threadLogger{
threshold: threshold,
mm: mm,
}
jww.FEEDBACK.Printf("[LOG] Worker outputting log to file at level "+
"%s using web worker", tl.threshold)
logger = tl
return tl, nil
}
// Write adheres to the io.Writer interface and sends the log entries to the
// worker to be added to the file buffer. Always returns the length of p and
// nil. All errors are printed to the log.
func (tl *threadLogger) Write(p []byte) (n int, err error) {
return len(p), tl.mm.SendNoResponse(WriteLogTag, p)
}
// Listen adheres to the [jwalterweatherman.LogListener] type and returns the
// log writer when the threshold is within the set threshold limit.
func (tl *threadLogger) Listen(threshold jww.Threshold) io.Writer {
if threshold < tl.threshold {
return nil
}
return tl
}
// StopLogging stops sending log messages to the logging worker. Once logging is
// stopped, it cannot be resumed and the log file cannot be recovered. This does
// not stop the logging worker.
func (tl *threadLogger) StopLogging() {
tl.threshold = math.MaxInt
}
// GetFile returns the entire log file.
func (tl *threadLogger) GetFile() []byte {
response, err := tl.mm.Send(GetFileTag, nil)
if err != nil {
jww.FATAL.Panicf("[LOG] Failed to get log file from worker: %+v", err)
}
return response
}
// Threshold returns the log level threshold of logs sent to the worker.
func (tl *threadLogger) Threshold() jww.Threshold {
return tl.threshold
}
// MaxSize returns the max size, in bytes, that the log file is allowed to be.
func (tl *threadLogger) MaxSize() int {
response, err := tl.mm.Send(MaxSizeTag, nil)
if err != nil {
jww.FATAL.Panicf("[LOG] Failed to max file size from worker: %+v", err)
}
return int(binary.LittleEndian.Uint64(response))
}
// Size returns the number of bytes written to the log file.
func (tl *threadLogger) Size() int {
response, err := tl.mm.Send(SizeTag, nil)
if err != nil {
jww.FATAL.Panicf("[LOG] Failed to file size from worker: %+v", err)
}
return int(binary.LittleEndian.Uint64(response))
}
// Worker always returns nil
func (tl *threadLogger) Worker() *worker.Manager {
return nil
}