-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlogs2Timeline.fsx
153 lines (120 loc) · 4.9 KB
/
logs2Timeline.fsx
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#r "nuget: System.Diagnostics.EventLog, 8.0.0"
#r "nuget: Newtonsoft.Json, 13.0.3"
#r "nuget: FSharp.Data, 6.3.0"
open FSharp.Data
open Newtonsoft.Json
open System
open System.IO
open System.Diagnostics
open System.Diagnostics.Eventing.Reader
type Output = {
Folder : string
JsFile : string
HtmlFile : string
}
type EventData = {
[<JsonProperty(PropertyName = "date")>] Date: DateTime
[<JsonProperty(PropertyName = "detail")>] Detail: string list
}
type Event = {
[<JsonProperty(PropertyName = "name")>] Name: string;
[<JsonProperty(PropertyName = "data")>] Data: EventData list
}
type Events = {
[<JsonProperty(PropertyName = "startdate")>] Startdate: DateTime
[<JsonProperty(PropertyName = "stopdate")>] Stopdate: DateTime
[<JsonProperty(PropertyName = "events")>] Events: Event list
}
type Entry = {
TimeCreated: DateTime
ProviderName: string
Level: string
Data: string
}
let output = { Folder = "timeline"; JsFile = "app.js"; HtmlFile = "timeline.html" }
let sanitizeDetail (detail : string) =
detail.Replace("\n", "<br>").Replace("'"," ").Trim()
let computeEntries (entries : Entry list) =
let getStartDate(allEntries : Entry list) =
let minDate = (allEntries |> List.minBy (fun x -> x.TimeCreated)).TimeCreated
new DateTime(minDate.Year,minDate.Month,minDate.Day,00,00,01)
let getStopdate (allEntries : Entry list) =
let maxDate = (allEntries |> List.maxBy (fun x -> x.TimeCreated)).TimeCreated
new DateTime(maxDate.Year,maxDate.Month,maxDate.Day,23,59,59)
let getItemData (entriesGroup : Entry list) = entriesGroup
|> List.groupBy (fun x -> x.TimeCreated)
|> List.map (fun (key,values) -> { Date = key; Detail = values |> List.map (fun x -> sanitizeDetail x.Data) })
let getItems (allEntries : Entry list) = allEntries
|> List.groupBy (fun x -> sprintf "%s - %s" x.ProviderName x.Level)
|> List.map (fun (key,values) -> { Name = key; Data = getItemData values})
{
Startdate = getStartDate entries
Stopdate = getStopdate entries
Events = getItems entries
}
let serialize items = JsonConvert.SerializeObject(items)
let computeJavascriptFile (events : Events) = sprintf "run(%s)" <| serialize events
let getOutputPath file = Path.Combine(__SOURCE_DIRECTORY__, output.Folder, file)
let writeFile path content =
use file = File.CreateText(path)
fprintfn file "%s" content
let writeJavascriptFile = writeFile <| getOutputPath output.JsFile
let openHtmlFile() =
let info = ProcessStartInfo(FileName = getOutputPath output.HtmlFile, UseShellExecute = true)
Process.Start(info) |> ignore
let processEntries entries =
entries
|> computeEntries
|> computeJavascriptFile
|> writeJavascriptFile
openHtmlFile()
let loadEventLogEntriesFromFile path =
let readEventLogEntriesFromFile() =
use reader = new EventLogReader(path,PathType.FilePath)
let normalyze (entry : EventRecord) = {
TimeCreated = entry.TimeCreated.Value
Level = entry.LevelDisplayName
ProviderName = entry.ProviderName
Data = entry.FormatDescription()
}
let rec read entries =
match reader.ReadEvent() with
| null -> entries
| entry -> read (entry::entries)
read [] |> List.map normalyze
try
match File.Exists(path) with
| true -> Some(readEventLogEntriesFromFile())
| _ -> None
with
| _ -> None
let loadLocalEventLogEntries logName =
let readLocalEventLogEntries() =
use eventLog = new EventLog(logName)
let normalyze (entry : EventLogEntry) = {
TimeCreated = entry.TimeGenerated
ProviderName = entry.Source
Level = entry.EntryType.ToString()
Data = entry.Message
}
[for entry in eventLog.Entries -> normalyze entry]
try
match EventLog.Exists logName with
| true -> Some(readLocalEventLogEntries())
| _ -> None
with
| _ -> None
let processEventLogFile path =
match loadEventLogEntriesFromFile path with
| Some(entries) -> processEntries entries
| _ -> printfn "Invalid path or file"
let processLocalEventLog logName =
match loadLocalEventLogEntries logName with
| Some(entries) -> processEntries entries
| _ -> printfn "Invalid log name or no entries"
match fsi.CommandLineArgs with
| [| _ ; "--file" ; path|] ->
processEventLogFile path
| [| _ ; "--logname" ; logName|] ->
processLocalEventLog logName
| _ -> printfn "Invalid command line"