1b4c3325e3c884660e2a9087951d92bd4a0bdc5f
6 open System.Diagnostics
8 open System.Collections.Generic
10 type Severity = DEBUG = 1 | USER = 2 | WARNING = 3 | ERROR = 4 | FATAL = 5
12 type IListener = abstract NewEntry : Severity -> string -> unit
16 let maxSizeFile = 10L * 1024L * 1024L // [byte] (10 MB).
17 let nbEntriesCheckSize = 100; // Each 100 entries added we check the size of the log file to test if it is greater than 'MAX_SIZE_FILE'.
18 let LogDefaultDirectory = "Parasitemia\\Log"
19 let filenameFormat = "{0:D4}.log"
20 let encoding = Encoding.GetEncoding("UTF-8")
22 let moduleName = System.Diagnostics.StackFrame(1).GetMethod().Module.Name
24 let mutable stream : StreamWriter = null
26 let mutable logDir : string = null
27 let mutable absoluteDir : string = null
29 let mutable nbEntries = 0L
31 let monitor = Object()
33 let listeners = List<IListener>()
42 static let instance = new Log()
44 let setLogDirectory (dir
: string) =
45 lock
monitor (fun () ->
47 absoluteDir <- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), logDir)
49 if stream <> null then
54 if not
<| Directory.Exists(absoluteDir) then
55 Directory.CreateDirectory(absoluteDir) |> ignore
57 | _ as ex -> Console.Error.WriteLine("Unable to create the log directory: {0}", absoluteDir))
61 if stream = null || (nbEntries % (int64
nbEntriesCheckSize) = 0L) && stream.BaseStream.Length > maxSizeFile then
62 if stream <> null then
66 for existingFile
in Directory.GetFiles(absoluteDir) do
68 if Int32.TryParse(existingFile
.Remove(existingFile
.LastIndexOf('.')), current_n) && !current_n > n then
71 let mutable filename = Path.Combine(absoluteDir, String.Format(filenameFormat, n))
73 if (FileInfo(filename).Length > maxSizeFile) then
74 filename <- Path.Combine(absoluteDir, String.Format(filenameFormat, n + 1))
76 | :? FileNotFoundException -> () // The file may not exist.
78 stream <- new StreamWriter(filename, true, encoding)
80 | _ as ex -> Console.Error.WriteLine("Can't open the file log: {0}", ex)
83 setLogDirectory LogDefaultDirectory
85 interface IDisposable with
86 member this
.Dispose () =
87 if stream <> null then
90 member private
this.Write (message
: string, severity
: Severity) =
91 lock
monitor (fun () ->
92 nbEntries <- nbEntries + 1L
95 if stream <> null then
96 let mutable moduleNameCaller = moduleName
97 match StackTrace().GetFrames() |> Array.tryPick
(fun frame
-> let name = frame
.GetMethod().Module.Name
98 if name <> moduleName then Some name else None) with
99 | Some name -> moduleNameCaller <- name
102 let threadName = Thread.CurrentThread.Name
104 for listener
in listeners do
105 listener
.NewEntry severity message
109 "{0:yyyy-MM-dd HH:mm:ss.fff} [{1}] {{{2}}} ({3}) : {4}",
110 TimeZone.CurrentTimeZone.ToLocalTime(DateTime.UtcNow),
113 (if String.IsNullOrEmpty(threadName) then Thread.CurrentThread.ManagedThreadId.ToString() else String.Format("{0}-{1}", threadName, Thread.CurrentThread.ManagedThreadId)),
118 | :? IOException as ex -> Console.Error.WriteLine("Unable to write to the log file: {0}", ex))
121 member private
this.AddListener (listener
: IListener) =
122 lock
monitor (fun () ->
123 if not
<| listeners.Contains(listener
) then
124 listeners.Add(listener
))
126 member private
this.RmListener (listener
: IListener) =
127 lock
monitor (fun () ->
128 listeners.Remove(listener
) |> ignore
)
130 static member AddListener (listener
: IListener) = instance.AddListener(listener
)
131 static member RmListener (listener
: IListener) = instance.RmListener(listener
)
133 static member LogWithTime (message
: string, severity
: Severity, f
: unit -> 'a option, [<ParamArray>] args: Object[]) : 'a
option =
139 instance.Write(String.Format(message
, args
) + sprintf
" (time: %d ms)" sw.ElapsedMilliseconds, severity
)
142 static member Debug (message
: string, [<ParamArray>] args
: Object[]) =
144 instance.Write(String.Format(message
, args
), Severity.DEBUG)
149 static member User (message
: string, [<ParamArray>] args
: Object[]) =
150 instance.Write(String.Format(message
, args
), Severity.USER)
152 static member Warning (message
: string, [<ParamArray>] args
: Object[]) =
153 instance.Write(String.Format(message
, args
), Severity.WARNING)
155 static member Error (message
: string, [<ParamArray>] args
: Object[]) =
156 instance.Write(String.Format(message
, args
), Severity.ERROR)
158 static member Fatal (message
: string, [<ParamArray>] args
: Object[]) =
159 instance.Write(String.Format(message
, args
), Severity.FATAL)