Last active
June 24, 2016 17:41
-
-
Save Kimserey/bc500501f7f738dbfb20a31e5a40a933 to your computer and use it in GitHub Desktop.
Deedle logs exploration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Logs</title> | |
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> | |
<script src="https://code.highcharts.com/highcharts.js"></script> | |
</head> | |
<body> | |
<script> | |
function makeChart(endpoint, title) { | |
$.getJSON('http://127.0.0.1:8083/' + endpoint, function (result) { | |
$('<div style="width:100%;">').highcharts({ | |
chart: { | |
type: 'spline', | |
zoomType: 'xy' | |
}, | |
title: { | |
text: title | |
}, | |
xAxis: { | |
categories: result[0].counts.map(function (e) { return e.date; }) | |
}, | |
yAxis: { | |
title: { | |
text: "Count" | |
} | |
}, | |
plotOptions: { | |
spline: { | |
marker: { | |
enabled: false | |
} | |
} | |
}, | |
legend: { | |
align: 'right', | |
x: -30, | |
verticalAlign: 'top', | |
y: 25, | |
floating: true, | |
borderColor: '#CCC', | |
borderWidth: 1, | |
shadow: false | |
}, | |
tooltip: { | |
pointFormat: '{series.name}: {point.y}' | |
}, | |
series: | |
result.map(function (e) { | |
return { | |
name: e.instance, | |
data: e.counts.map(function (e) { return e.count; }) | |
}; | |
}) | |
}).appendTo('body'); | |
}); | |
} | |
makeChart('errors', 'Error per hours'); | |
makeChart('mdrefreshes', 'MD refreshses per hours'); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#I __SOURCE_DIRECTORY__ | |
#load "../packages/Deedle/Deedle.fsx" | |
open Deedle | |
open System | |
open System.IO | |
Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ | |
let csvPath = "../data" | |
type Log = { | |
Date: DateTime | |
Level: string | |
Source: string | |
Text: string | |
Instance: string | |
} | |
let df = | |
Directory.GetFiles(csvPath, "*.csv") | |
|> Seq.map (fun (path: string) -> Frame.ReadCsv(path, hasHeaders = false)) | |
|> Seq.map (fun df -> df |> Frame.indexColsWith [ "Sequence"; "Date"; "Level"; "ThreadId"; "Source"; "Text"; "Exception"; "Instance" ]) | |
|> Seq.collect (fun df -> df |> Frame.rows |> Series.observations) | |
|> Seq.map snd | |
|> Seq.filter (fun s -> s.TryGetAs<DateTime>("Date").HasValue) | |
|> Seq.map (fun s -> | |
{ Date = s.GetAs<DateTime>("Date") | |
Level = s.GetAs<string>("Level") | |
Source = s.GetAs<string>("Source") | |
Text = s.GetAs<string>("Text") | |
Instance = s.GetAs<string>("Instance") }) | |
|> Frame.ofRecords | |
type Data = { | |
Instance: string | |
Counts: Count list | |
} | |
and Count = { | |
Date: DateTime | |
Count: int | |
} | |
let errors = | |
df | |
|> Frame.pivotTable | |
(fun _ c -> | |
let date = c.GetAs<DateTime>("Date") | |
new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0)) | |
(fun _ c -> c.GetAs<string>("Instance")) | |
(fun f -> | |
f | |
|> Frame.filterRowValues (fun c -> c.GetAs<string>("Level") = "error") | |
|> Frame.getCols | |
|> Stats.count) | |
|> Frame.fillMissingWith 0 | |
|> Frame.sortRowsByKey | |
|> Frame.getCols | |
|> Series.observations | |
|> Seq.map (fun (k, v) -> | |
{ Instance = k | |
Counts = | |
v | |
|> Series.observations | |
|> Seq.map (fun (k, v) -> | |
{ Date = k | |
Count = v }) | |
|> Seq.toList }) | |
|> Seq.toList | |
let mdRefreshes = | |
df | |
|> Frame.pivotTable | |
(fun _ c -> | |
let date = c.GetAs<DateTime>("Date") | |
new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0)) | |
(fun _ c -> c.GetAs<string>("Instance")) | |
(fun f -> | |
f | |
|> Frame.filterRowValues (fun c -> c.GetAs<string>("Text").Contains("md-refresh")) | |
|> Frame.getCols | |
|> Stats.count) | |
|> Frame.fillMissingWith 0 | |
|> Frame.sortRowsByKey | |
|> Frame.getCols | |
|> Series.observations | |
|> Seq.map (fun (k, v) -> | |
{ Instance = k | |
Counts = | |
v | |
|> Series.observations | |
|> Seq.map (fun (k, v) -> | |
{ Date = k | |
Count = v }) | |
|> Seq.toList }) | |
|> Seq.toList | |
#I __SOURCE_DIRECTORY__ | |
#r "../packages/Suave/lib/net40/Suave.dll" | |
#r "../packages/Newtonsoft.Json/lib/net40/Newtonsoft.Json.dll" | |
open Suave | |
open Suave.Json | |
open Suave.Filters | |
open Suave.Operators | |
open Suave.Successful | |
open Suave.Writers | |
open Newtonsoft.Json | |
open Newtonsoft.Json.Serialization | |
let JSON v = | |
OK (JsonConvert.SerializeObject(v, new JsonSerializerSettings(ContractResolver = new CamelCasePropertyNamesContractResolver()))) | |
>=> setMimeType "application/json; charset=utf-8" | |
>=> setHeader "Access-Control-Allow-Origin" "*" | |
>=> setHeader "Access-Control-Allow-Headers" "content-type" | |
let app = | |
GET >=> choose | |
[ path "/errors" >=> JSON errors | |
path "/mdrefreshes" >=> JSON mdRefreshes ] | |
startWebServer defaultConfig app |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment