foundationdb/contrib/TraceLogHelper/JsonParser.cs

95 lines
3.5 KiB
C#

/*
* JsonParser.cs
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2020 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Linq;
namespace Magnesium
{
public static class JsonParser
{
static Random r = new Random();
// dummy parameter nonFatalParseError to match xml
public static IEnumerable<Event> Parse(System.IO.Stream stream, string file,
bool keepOriginalElement = false, double startTime = -1, double endTime = Double.MaxValue,
double samplingFactor = 1.0, Action<string> nonFatalErrorMessage = null)
{
using (var reader = new System.IO.StreamReader(stream))
{
string line;
while((line = reader.ReadLine()) != null)
{
XElement root = XElement.Load(JsonReaderWriterFactory.CreateJsonReader(new MemoryStream(Encoding.UTF8.GetBytes(line)), new XmlDictionaryReaderQuotas()));
Event ev = null;
try
{
ev = ParseEvent(root, file, keepOriginalElement, startTime, endTime, samplingFactor);
}
catch (Exception e)
{
throw new Exception(string.Format("Failed to parse JSON {0}", root), e);
}
if (ev != null) yield return ev;
}
}
}
private static Event ParseEvent(XElement xEvent, string file, bool keepOriginalElement, double startTime, double endTime, double samplingFactor)
{
if (samplingFactor != 1.0 && r.NextDouble() > samplingFactor)
return null;
XElement trackLatestElement = xEvent.XPathSelectElement("//TrackLatestType");
bool rolledEvent = trackLatestElement != null && trackLatestElement.Value.Equals("Rolled");
String timeElement = (rolledEvent) ? "OriginalTime" : "Time";
double eventTime = double.Parse(xEvent.XPathSelectElement("//" + timeElement).Value);
if (eventTime < startTime || eventTime > endTime)
return null;
return new Event {
Severity = (Severity)int.Parse(xEvent.XPathSelectElement("//Severity").ValueOrDefault("40")),
Type = string.Intern(xEvent.XPathSelectElement("//Type").Value),
Time = eventTime,
Machine = string.Intern(xEvent.XPathSelectElement("//Machine").Value),
ID = string.Intern(xEvent.XPathSelectElement("//ID").ValueOrDefault("0")),
TraceFile = file,
DDetails = xEvent.Elements()
.Where(a=>a.Name != "Type" && a.Name != "Time" && a.Name != "Machine" && a.Name != "ID" && a.Name != "Severity" && (!rolledEvent || a.Name != "OriginalTime"))
.ToDictionary(a=>string.Intern(a.Name.LocalName), a=>(object)a.Value),
original = keepOriginalElement ? xEvent : null
};
}
private static string ValueOrDefault( this XElement attr, string def ) {
if (attr == null) return def;
else return attr.Value;
}
}
}