• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ParadoxGameConverters / Fronter.NET / 17702954560

13 Sep 2025 10:39PM UTC coverage: 19.079% (+0.9%) from 18.155%
17702954560

push

github

web-flow
Optimize the slicing of log messages from converter backends (#905)

* Optimize the slicing of log messages from converter backends

This should result in better speed and reduced heap memory allocation.

* Remove old code from MessageSlicer

99 of 708 branches covered (13.98%)

Branch coverage included in aggregate %.

52 of 79 new or added lines in 5 files covered. (65.82%)

1 existing line in 1 file now uncovered.

572 of 2809 relevant lines covered (20.36%)

9.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.0
/Fronter.NET/Services/MessageSlicer.cs
1
using commonItems;
2
using Fronter.Models;
3
using log4net;
4
using log4net.Core;
5
using System;
6
using System.Globalization;
7

8
namespace Fronter.Services;
9

10
internal static class MessageSlicer {
NEW
11
    private static readonly ILog logger = LogManager.GetLogger("Frontend");
×
12

13
    public static LogLine SliceMessage(string message) {
1✔
14
        ReadOnlySpan<char> span = message.AsSpan();
1✔
15

16
        int posOpen = span.IndexOf('[');
1✔
17
        int posClose = span.IndexOf(']');
1✔
18

19
        if (posOpen < 0 || posOpen > posClose) {
1!
NEW
20
                        return new LogLine(DateTime.Now, level: null, message);
×
21
                }
22

23
        ReadOnlySpan<char> timestampSpan = span[..posOpen].Trim();
1✔
24
                DateTime timestamp;
25
                if (IsTimestamp(timestampSpan)) {
2!
26
                        timestamp = DateTime.ParseExact(timestampSpan, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
1✔
27
                } else {
1✔
NEW
28
                        timestamp = DateTime.Now;
×
NEW
29
                        var trimmedStart = span.TrimStart();
×
NEW
30
                        if (trimmedStart.IsEmpty || trimmedStart[0] != '[') {
×
NEW
31
                                return new LogLine(timestamp, level: null, message);
×
32
                        }
UNCOV
33
                }
×
34

35
                var levelSpan = span.Slice(posOpen + 1, posClose - posOpen - 1);
1✔
36
                Level? level = GetLogLevel(levelSpan);
1✔
37

38
                string msg = string.Empty;
1✔
39
                if (message.Length >= posClose + 2) {
2✔
40
                        msg = message[(posClose + 2)..];
1✔
41
                }
1✔
42

43
        return new LogLine(timestamp, level, msg);
1✔
44
        }
1✔
45

46
    private static Level GetLogLevel(ReadOnlySpan<char> levelSpan) {
1✔
47
                // Map common levels without allocations.
48
                // For optimal performance, order by expected frequency.
49
                if (levelSpan.Equals("DEBUG".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
50
                        return Level.Debug;
×
51
                }
52
                if (levelSpan.Equals("INFO".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
53
                        return Level.Info;
×
54
                }
55
                if (levelSpan.Equals("PROGRESS".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
56
                        return LogExtensions.ProgressLevel;
×
57
                }
58
                if (levelSpan.Equals("WARN".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
59
                        return Level.Warn;
×
60
                }
61
                if (levelSpan.Equals("NOTICE".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
62
                        return Level.Notice;
×
63
                }
64
                if (levelSpan.Equals("ERROR".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
65
                        return Level.Error;
×
66
                }
67
                if (levelSpan.Equals("FATAL".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
68
                        return Level.Fatal;
×
69
                }
70
                if (levelSpan.Equals("WARNING".AsSpan(), StringComparison.OrdinalIgnoreCase)) {
1!
NEW
71
                        return Level.Warn;
×
72
                }
73

74
                string levelKey = new(levelSpan);
1✔
75
                var level = LogManager.GetRepository().LevelMap[levelKey];
1✔
76
        if (level == null) {
1!
NEW
77
            logger.Warn($"Unknown log level: {levelKey}");
×
NEW
78
            level = Level.Debug;
×
NEW
79
        }
×
80

81
        return level;
1✔
82
    }
1✔
83

84
    private static bool IsTimestamp(ReadOnlySpan<char> s) {
1✔
85
        // Fast check for format: yyyy-MM-dd HH:mm:ss (length 19)
86
        if (s.Length != 19) return false;
1!
87

88
        static bool IsDigit(char c) => (uint)(c - '0') <= 9u;
14✔
89

90
        // yyyy
91
        if (!IsDigit(s[0]) || !IsDigit(s[1]) || !IsDigit(s[2]) || !IsDigit(s[3])) return false;
1!
92
        // -
93
        if (s[4] != '-') return false;
1!
94
        // MM
95
        if (!IsDigit(s[5]) || !IsDigit(s[6])) return false;
1!
96
        // -
97
        if (s[7] != '-') return false;
1!
98
        // dd
99
        if (!IsDigit(s[8]) || !IsDigit(s[9])) return false;
1!
100
        // space
101
        if (s[10] != ' ') return false;
1!
102
        // HH
103
        if (!IsDigit(s[11]) || !IsDigit(s[12])) return false;
1!
104
        // :
105
        if (s[13] != ':') return false;
1!
106
        // mm
107
        if (!IsDigit(s[14]) || !IsDigit(s[15])) return false;
1!
108
        // :
109
        if (s[16] != ':') return false;
1!
110
        // ss
111
        if (!IsDigit(s[17]) || !IsDigit(s[18])) return false;
1!
112

113
        return true;
1✔
114
    }
1✔
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc