-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLogAgent.fs
More file actions
94 lines (77 loc) · 3 KB
/
LogAgent.fs
File metadata and controls
94 lines (77 loc) · 3 KB
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
// See: http://fsharpforfunandprofit.com/posts/concurrency-actor-model/
// See: http://msdn.microsoft.com/en-us/library/ee370357.aspx
/// Agent for logging
module internal CASO.DB.Titan.RexPro.LogAgent
// Log writer implementation using F# asynchronous agents
open System
open System.IO
type private Message =
| Debug of string
| Info of string
| Warn of string
| Error of string
| Fatal of string
with
static member toString logMessage =
match logMessage with
| Debug msg -> ("DEBUG", msg)
| Info msg -> ("INFO", msg)
| Warn msg -> ("WARN", msg)
| Error msg -> ("ERROR", msg)
| Fatal msg -> ("FATAL", msg)
|> fun (lvl, msg) ->
let timeStr = DateTime.Now.ToString("dd/MM/yy HH:mm:ss.fff")
let threadId = System.Threading.Thread.CurrentThread.ManagedThreadId
sprintf "[%s][%s][%d]: %s" lvl timeStr threadId msg
override x.ToString() =
Message.toString x
type private LogCommand =
| Log of Message
| Flush
| Close of AsyncReplyChannel<unit>
let inline internal write (writer:StreamWriter) message =
printfn "%s" message
System.Diagnostics.Debug.WriteLine message
writer.WriteLine message
type LogAgent(logFile:string) as x =
let writer = lazy(File.AppendText logFile)
let agent = MailboxProcessor.Start (fun agent ->
// Do the loop until the Stop command is received
// Keep the number of lines written to the log
let rec loop(count) = async {
let! command = agent.Receive()
match command with
| Log message ->
let count = count + 1
let message = Message.toString message
write writer.Value message
| Flush ->
if writer.IsValueCreated then
writer.Value.Flush()
| Close reply ->
let message = sprintf "%d messages written into log" count
write writer.Value message
x.DoClose()
reply.Reply(ignore())
return! loop(count)
}
loop(0))
interface IDisposable with
member x.Dispose() = x.DoClose()
member private x.DoClose() =
let message = sprintf "Discarding %d messages in the queue" (agent.CurrentQueueLength)
write writer.Value message
let d = agent :> IDisposable
d.Dispose()
if writer.IsValueCreated then
writer.Value.Dispose()
member private x.log objToMessage obj =
obj |> objToMessage |> LogCommand.Log |> agent.Post
member x.fatal = x.log Fatal
member x.error = x.log Error
member x.warn = x.log Warn
member x.info = x.log Info
member x.debug = x.log Debug
member x.queueLength = agent.CurrentQueueLength
member x.flush() = LogCommand.Flush |> agent.Post
member x.close() = LogCommand.Close |> agent.PostAndReply