-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample-simple-diagnostics.pc
136 lines (116 loc) · 3.06 KB
/
example-simple-diagnostics.pc
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// it would be nice if _log* functions were integrated into the language for consistency
func _logHeader() -> string
{
var t = new Time().gmt()
// take the last 6 characters of the lane (a uuid)
var shortId = substring(lane, -6)
return sprintf("%s %s", t.shortDateTime(), shortId)
}
func _logFormat(string formatStr, ...) -> string
{
return sprint(_logHeader(), " ", vsprintf(formatStr, ...))
}
func _log(Stream stream, string level, ...)
{
// is there a way to determine the length of the vargs?
if (arglength(...) > 0)
{
fprint(stream, " ", level, " ", ...)
fprint(stream, "\n")
}
}
func _logf(Stream stream, string level, string formatStr, ...)
{
fprint(stream, _logHeader(), " ", level, " ", _logFormat(formatStr, ...), "\n")
}
// I love separation of state from methods
object Log
{
Stream chattyStream
Stream urgentStream
}
impl Log
{
// how to do constructor?
// this would be cool - if ctor specified, one is required in object instantiation
// I hate overloads and default parameters - loses traceability in the source code
ctor singleStream(Stream stream)
{
this.twoStreams(stream, stream)
}
ctor twoStreams(Stream chattyStream, Stream urgentStream)
{
this.chattyStream = chattyStream
this.urgentStream = urgentStream
}
dtor
{
this.chattyStream.flush()
this.urgentStream.flush()
}
func info(...)
{
_log(this.chattyStream, "INFO", ...)
}
func infof(string formatStr, ...)
{
_logf(this.chattyStream, "INFO", formatStr, ...)
}
func warn(...)
{
_log(this.urgentStream, "WARN", ...)
}
func warnf(string formatStr, ...)
{
_logf(this.urgentStream, "WARN", formatStr, ...)
}
func error(Error error, ...)
{
_log(this.urgentStream, "ERROR", ...)
_log(this.urgentStream, "STACK", error.stack()) // imagined way to get the call stack as a string
}
func errorf(Error error, string formatStr, ...)
{
_logf(this.urgentStream, "ERROR", formatStr, ...)
_log(this.urgentStream, "STACK", error.stack())
}
}
var log = new Log.singleStream(Stream.stdout)
func server()
{
var s = new Socket()
s.listen()
loop
{
var client = s.accept()
// imagined syntax for spawing a thread
spawn acceptConnection(cxn)
}
}
func acceptConnection(Socket cxn)
{
// new thread - want a new uuid & context
lane++
log.infof("connected: %s", cxn.networkAddress)
// some imagined state machine creation
var service = state::transactionStream
loop
{
// imagined syntax for hooking a transition event
upon service => next(cxn)
{
txnReady -> txn:
{
log.info("parsed ", txn)
}
quit -> err:
{
if (err != null)
{
log.error(err)
}
log("connection terminated")
}
}
}
}