Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions docs/01-basic/report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## (Q1.1)

### 1

在LogParser\Parser\LogFileParser.cs中

```
using var csv = new CsvReader(logFile, config);
csv.Context.RegisterClassMap<LogRecordMap>();

foreach (var logRecord in csv.GetRecords<LogRecord>())

```

csv.GetRecords按照CSV规则解析各行。而每一列对应什么含义,也是在 LogFileParser 中通过 Index 指定的:

```
Map(m => m.LineNo).Index(0);
Map(m => m.Timestamp).Index(1);
Map(m => m.PodName).Index(2);
Map(m => m.Message).Index(3);

```

### 2

```

using (var doc = JsonDocument.Parse(logRecord.Message))
{
var root = doc.RootElement;
if (root.TryGetProperty("event", out var eventElement))

```

根据 eventElement 来判断类型

### 3

使用JsonSerializer.Deserialize。

同时设置

private static JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower,
};

调用时将options传入,完成命名法转换

## (Q1.2)

+ Dictionary<string, string> KeyValueVisitor.Dump(LogEntry entry)
+ Dictionary<string, string> CallLogEntry.Accept<Dictionary<string, string>>(visitor)
+ Dictionary<string, string> KeyValueVisitor.Visit(CallLogEntry entry)

## (Q1.3)

没有使用AI,时间花了大概三小时。比程设作业难。我认为我完成作业只是模仿示例完成了代码,还没有完全看懂整个架构。

4 changes: 2 additions & 2 deletions src/LogParser/Models/LogEntries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public sealed record RequestLogEntry(
{
public override TResult Accept<TResult>(ILogEntryVisitor<TResult> visitor)
{
throw new NotImplementedException("TODO: T1.2");
return visitor.Visit(this);
}
}

Expand All @@ -69,7 +69,7 @@ public sealed record InternalLogEntry(
{
public override TResult Accept<TResult>(ILogEntryVisitor<TResult> visitor)
{
throw new NotImplementedException("TODO: T1.2");
return visitor.Visit(this);
}
}

Expand Down
47 changes: 41 additions & 6 deletions src/LogParser/Parser/LineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public static LogEntry ParseLine(LogRecord logRecord)
return eventElement.GetString() switch
{
"call" => LineParser.CreateCall(logRecord),
"request" => throw new NotImplementedException("TODO: T1.2"),
"internal" => throw new NotImplementedException("TODO: T1.2"),
"request" => LineParser.CreateRequest(logRecord),
"internal" => LineParser.CreateInternal(logRecord),
_ => throw new FormatException($"Unknown event type: {eventElement.GetString()} in log message: {logRecord.Message}")
};
}
Expand Down Expand Up @@ -50,12 +50,40 @@ private static LogEntry CreateCall(LogRecord logRecord)

private static LogEntry CreateRequest(LogRecord logRecord)
{
throw new NotImplementedException("TODO: T1.2");
var requestMessage = JsonSerializer.Deserialize<RequestMessage>(logRecord.Message, options)
?? throw new FormatException($"Failed to deserialize call message: {logRecord.Message}");
return new RequestLogEntry(
LineNo: logRecord.LineNo,
Timestamp: DateTimeOffset.Parse(logRecord.Timestamp),
PodName: logRecord.PodName,
Severity: ParseSeverity(requestMessage.Severity),
RequestId: requestMessage.RequestId,
Method: requestMessage.Method,
Path: requestMessage.Path,
StatusCode: requestMessage.StatusCode
);
}

private static LogEntry CreateInternal(LogRecord logRecord)
{
throw new NotImplementedException("TODO: T1.2");
var internalMessage = JsonSerializer.Deserialize<InternalMessage>(logRecord.Message, options)
?? throw new FormatException($"Failed to deserialize call message: {logRecord.Message}");
var Exception = internalMessage.Exception;
var idx = Exception.IndexOf(":");
if (idx < 0)
{
throw new FormatException($"Invalid exception format: {internalMessage.Exception}");
}
var ExceptionName = Exception.Substring(0,idx);
var ExceptionMessage = Exception.Substring(idx+2);
return new InternalLogEntry(
LineNo: logRecord.LineNo,
Timestamp: DateTimeOffset.Parse(logRecord.Timestamp),
PodName: logRecord.PodName,
Severity: ParseSeverity(internalMessage.Severity),
ExceptionName: ExceptionName,
ExceptionMessage: ExceptionMessage
);
}

private static LogSeverity ParseSeverity(string severity)
Expand All @@ -77,11 +105,18 @@ private record CallMessage(
);

private record RequestMessage(
// TODO: T1.2
[property: JsonRequired] string Severity,
[property: JsonRequired] string RequestId,
[property: JsonRequired] string Method,
[property: JsonRequired] string Path,
[property: JsonRequired] int StatusCode

);

private record InternalMessage(
// TODO: T1.2
[property: JsonRequired] string Severity,
[property: JsonRequired] string Exception

);
}
}
24 changes: 22 additions & 2 deletions src/LogParser/Visitors/KeyValueVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,32 @@ public Dictionary<string, string> Visit(CallLogEntry entry)

public Dictionary<string, string> Visit(RequestLogEntry entry)
{
throw new NotImplementedException("TODO: T1.3");
return new Dictionary<string, string>
{
["LineNo"] = entry.LineNo.ToString(),
["Timestamp"] = entry.Timestamp.ToString("O"),
["PodName"] = entry.PodName,
["Severity"] = entry.Severity.ToString(),
["EventType"] = entry.EventType.ToString(),
["RequestId"] = entry.RequestId,
["Method"] = entry.Method,
["Path"] = entry.Path,
["StatusCode"] = entry.StatusCode.ToString()
};
}

public Dictionary<string, string> Visit(InternalLogEntry entry)
{
throw new NotImplementedException("TODO: T1.3");
return new Dictionary<string, string>
{
["LineNo"] = entry.LineNo.ToString(),
["Timestamp"] = entry.Timestamp.ToString("O"),
["PodName"] = entry.PodName,
["Severity"] = entry.Severity.ToString(),
["EventType"] = entry.EventType.ToString(),
["ExceptionName"] = entry.ExceptionName,
["ExceptionMessage"] = entry.ExceptionMessage
};
}
}
}
Loading