private static void ExportOnlyHandling(FileExportFilter fileExort, string line, bool isReceive, string dataPart, StreamWriter currentExportWriter) { string output; if (fileExort.ExportOnlyKey != null) { string exportOnlyValue = GetJsonSimpleStringValue(dataPart, fileExort.ExportOnlyKey); output = (isReceive ? "< " : "> ") + exportOnlyValue; } else { output = line; } if (fileExort.ExportWithSpaceSequence.HasValue) { var list = Enumerable .Range(0, output.Length / fileExort.ExportWithSpaceSequence.Value) .Select(i => output.Substring(i * fileExort.ExportWithSpaceSequence.Value, fileExort.ExportWithSpaceSequence.Value)); output = string.Join(" ", list); } currentExportWriter.WriteLine(output); }
public IList <StreamSession> AnalyzeDataStreamSession(string fileName, TimeSpan?roundTripTimeFilter, int?flowRateFilter, Action <int> progressPercentage, FileExportFilter fileExort, out StringBuilder errors) { this.LastFilePath = fileName; errors = new StringBuilder(); HashSet <int> ignoreSessions = new HashSet <int>(); Dictionary <string, StreamWriter> openFileExportStreams = null; using (StreamReader streamReader = new StreamReader(fileName)) { Dictionary <int, StreamSession> sessions = new Dictionary <int, StreamSession>(); StreamSession currentSession = null; double totalFileSize = (double)streamReader.BaseStream.Length; string line = null; long lineNumber = 1; while ((line = streamReader.ReadLine()) != null) { string[] parts = line.Split(FieldSeparator); if (parts.Length > 4) { // message contains \t in data part // merge last parts string lastPart = string.Join("", parts, 3, parts.Length - 3); parts = new string[] { parts[0], parts[1], parts[2], lastPart }; } if (parts.Length == 4) { TimeSpan time; int sessionId; bool isReceive; if (TryParseDataStreamLine(parts, out time, out sessionId, out isReceive)) { string dataPart = parts[3]; if (dataPart.StartsWith("Session Created")) { var sessionInfoParts = dataPart.Split(';'); RawMessageFormat format = RawMessageFormat.JSON; if (sessionInfoParts.Length >= 3) { string formatStr = sessionInfoParts[2]; string[] formatParts = formatStr.Split(':'); format = (RawMessageFormat)Enum.Parse(typeof(RawMessageFormat), formatParts[1].Trim()); } currentSession = new StreamSession(sessionId, dataPart, time, format); sessions.Add(sessionId, currentSession); } else if (dataPart.StartsWith("Session Terminated")) { currentSession.TerminatedAt = time; } else if (dataPart.StartsWith("[Dismiss invalid session message]")) { errors.AppendLine("Packet received without valid session!"); errors.AppendLine(line); errors.AppendLine(); continue; } else if (!dataPart.StartsWith("[Logger Stopped]")) { if (currentSession == null || currentSession.SessionId != sessionId) { if (!sessions.TryGetValue(sessionId, out currentSession)) { if (!ignoreSessions.Contains(sessionId)) { errors.Append("Session ID "); errors.Append(sessionId); errors.AppendLine(" not found! All messages from this session are ignored!"); ignoreSessions.Add(sessionId); } continue; } } IGenericMessage message = ParseMessage(dataPart, currentSession.Format); // Flow rate if (currentSession.PendingFlowRate == null) { currentSession.PendingFlowRate = new FlowRate(time.Hours, time.Minutes, time.Seconds); currentSession.PendingFlowRate.StartLineNumber = lineNumber; } else if (currentSession.PendingFlowRate.Time.Hours != time.Hours || currentSession.PendingFlowRate.Time.Minutes != time.Minutes || currentSession.PendingFlowRate.Time.Seconds != time.Seconds) { // add pending flowrate and create new if (!flowRateFilter.HasValue || flowRateFilter <= currentSession.PendingFlowRate.TotalCallCount) { currentSession.FlowRates.Add(currentSession.PendingFlowRate); } currentSession.PendingFlowRate = new FlowRate(time.Hours, time.Minutes, time.Seconds); currentSession.PendingFlowRate.StartLineNumber = lineNumber; } var pendFlowRate = currentSession.PendingFlowRate; pendFlowRate.TotalCallCount++; pendFlowRate.PayloadByteCount += dataPart.Length; // round trip determination MethodInvokeRoundtrip methodInvokeReq = null; MethodInvokeRoundtrip methodInvokeResp = null; switch (message.Type) { case MessageType.AsyncMethodInvokeRequest: if (isReceive) { currentSession.IncomingAsyncCallCount++; pendFlowRate.IncomingAsyncCallCount++; CheckReceiveRequestOrder(errors, currentSession, message); } else { currentSession.OutgoingAsyncCallCount++; pendFlowRate.OutgoingAsyncCallCount++; CheckSendRequestOrder(errors, currentSession, message); } break; case MessageType.MethodInvokeRequest: methodInvokeReq = new MethodInvokeRoundtrip(); methodInvokeReq.IsReceive = isReceive; methodInvokeReq.Request = message; methodInvokeReq.RequestTime = time; if (isReceive) { currentSession.IncomingSyncCallCount++; currentSession.IncomingSyncCalls.Add(message.RequestId, methodInvokeReq); pendFlowRate.IncomingSyncCallCount++; CheckReceiveRequestOrder(errors, currentSession, message); } else { currentSession.OutgoingSyncCallCount++; currentSession.OutgoingSyncCalls.Add(message.RequestId, methodInvokeReq); pendFlowRate.OutgoingSyncCallCount++; CheckSendRequestOrder(errors, currentSession, message); } break; case MessageType.MethodInvokeResponse: if (isReceive) { if (currentSession.OutgoingSyncCalls.TryGetValue(message.RequestId, out methodInvokeResp)) { methodInvokeResp.Response = message; methodInvokeResp.ResponseTime = time; if (roundTripTimeFilter.HasValue && methodInvokeResp.RoundTripTime < roundTripTimeFilter) { currentSession.OutgoingSyncCalls.Remove(message.RequestId); } } else { errors.AppendLine("Incoming method invoke response could not be assigned to a request: "); errors.AppendLine(line); errors.AppendLine(); } } else { if (currentSession.IncomingSyncCalls.TryGetValue(message.RequestId, out methodInvokeResp)) { methodInvokeResp.Response = message; methodInvokeResp.ResponseTime = time; if (roundTripTimeFilter.HasValue && methodInvokeResp.RoundTripTime < roundTripTimeFilter) { currentSession.IncomingSyncCalls.Remove(message.RequestId); } } else { errors.AppendLine("Outgoing method invoke response could not be assigned to a incoming request: "); errors.AppendLine(line); errors.AppendLine(); } } break; } // handle file export if (fileExort != null) { if (openFileExportStreams == null) { openFileExportStreams = new Dictionary <string, StreamWriter>(); } if (fileExort.MessageNames.Where(mn => mn.Equals(message.Name)).Any()) { bool isConditionMatching = true; if (fileExort.Conditions != null) { foreach (var cond in fileExort.Conditions) { string condValue = GetJsonSimpleStringValue(dataPart, cond.Key); if (cond.Value != condValue) { isConditionMatching = false; break; } } } if (isConditionMatching) { string fileExportGroupValues = string.Concat(fileExort.GroupByKeys.Select(gk => GetJsonSimpleStringValue(dataPart, gk) + "_")); //string fileExportGroupValue = GetJsonSimpleStringValue(dataPart, fileExort.GroupByKey); StreamWriter currentExportWriter = null; if (openFileExportStreams.TryGetValue(fileExportGroupValues, out currentExportWriter) == false) { if (Directory.Exists(fileExort.ExportDirectory) == false) { Directory.CreateDirectory(fileExort.ExportDirectory); } string conditions = string.Concat(fileExort.Conditions?.Select(cd => $"{cd.Key}-{cd.Value}_")); string groupKeyValues = string.Concat(fileExort.GroupByKeys?.Select(gk => $"{gk}-{GetJsonSimpleStringValue(dataPart, gk)}_")); string exportPath = Path.Combine(Path.GetFullPath(fileExort.ExportDirectory), $"{conditions}{groupKeyValues.TrimEnd('_')}.txt"); if (File.Exists(exportPath)) { File.Delete(exportPath); } currentExportWriter = new StreamWriter(exportPath); openFileExportStreams.Add(fileExportGroupValues, currentExportWriter); } if (fileExort.SeparateOnKey != null) { string separateOnKeyValue = GetJsonSimpleStringValue(dataPart, fileExort.SeparateOnKey); if (separateOnKeyValue == fileExort.SeparateOnKeyValue) { currentExportWriter.WriteLine(Environment.NewLine); currentExportWriter.WriteLine(Environment.NewLine); } } ExportOnlyHandling(fileExort, line, isReceive, dataPart, currentExportWriter); if (methodInvokeReq != null && methodInvokeReq.ExportFileStream == null) { methodInvokeReq.ExportFileStream = currentExportWriter; } } } else if (methodInvokeResp != null && methodInvokeResp.ExportFileStream != null) { // write response as well ExportOnlyHandling(fileExort, line, isReceive, dataPart, methodInvokeResp.ExportFileStream); methodInvokeResp.ExportFileStream = null; } } } } else { errors.AppendLine("Invalid data row: " + line); } } else { errors.AppendLine("Invalid data row! Could not be splitted into 4 parts: " + line); } lineNumber++; if (progressPercentage != null && (lineNumber % 30000) == 0) { double dblPercentage = 100d / totalFileSize * (double)streamReader.BaseStream.Position; progressPercentage((int)dblPercentage); } } if (openFileExportStreams != null) { foreach (var fileStream in openFileExportStreams.Values) { fileStream.Close(); } } return(sessions.Values.ToList <StreamSession>()); } }