Search code examples
regexasp.net-coreasp.net-core-mvcsyslogkestrel-http-server

How to convert escape codes to html or remove


Kestrel in ASP.NET 5 Core MVC application in Debian writes escape codes to /var/log/syslog text file like

Apr  5 22:02:21 ew kestrel-store[31907]: #033[40m#033[32minfo#033[39m#033[22m#033[49m: Microsoft.Hosting.Lifetime[0]
Apr  5 22:02:21 ew kestrel-store[31907]:       Now listening on: http://localhost:5000
Apr  5 22:02:21 ew kestrel-store[31907]: #033[40m#033[32minfo#033[39m#033[22m#033[49m: Microsoft.Hosting.Lifetime[0]
Apr  5 22:02:21 ew kestrel-store[31907]:       Application started. Press Ctrl+C to shut down.
Apr  5 22:02:21 ew kestrel-store[31907]: #033[40m#033[32minfo#033[39m#033[22m#033[49m: Microsoft.Hosting.Lifetime[0]
Apr  5 22:02:21 ew kestrel-store[31907]:       Hosting environment: Production
Apr  5 22:02:21 ew kestrel-store[31907]: #033[40m#033[32minfo#033[39m#033[22m#033[49m: Microsoft.Hosting.Lifetime[0]
Apr  5 22:02:21 ew kestrel-store[31907]:       Content root path: /var/www/store5

This file is read by MVC controller and sent to user in view.

How to convert this file to html (for example, using colored or italic lines) or remove escape codes from file so that file is easier to read ? Or how to force kestrel output plain text without escape codes ?

Controller code:

public IActionResult Syslog()
{
    return new ContentResult()
    {
        Content = FileToStr("/var/log/syslog")
    };
}

static string FileToStr(string cFileName)
{
    StreamReader oReader = File.OpenText(cFileName);
    string lcString = oReader.ReadToEnd();
    oReader.Close();
    return lcString;
}

Escape sequence is defined as:

  1. One \x1b
  2. One [
  3. Zero or more parameter bytes 0x30-0x3f
  4. Zero or more intermediate bytes 0x20-0x2f
  5. One final byte 0x40-0x7f

Update

Code in answer adds span to start of every line and does not remove escape sequences:

<span style="color: blue">Apr  8 00:00:05 ew rsyslogd:  [origin software="rsyslogd" swVersion="8.1901.0" x-pid="573" x-info="https://www.rsyslog.com"] rsyslogd was HUPed</span>
<span style="color: blue">Apr  8 00:00:05 ew systemd[1]: logrotate.service: Succeeded.</span>
<span style="color: blue">Apr  8 00:00:05 ew systemd[1]: Started Rotate log files.</span>
<span style="color: blue">Apr  8 00:00:10 ew colord[1172]: failed to get session [pid 23699]: No data available</span>
<span style="color: blue">Apr  8 00:00:12 ew colord[1172]: failed to get session [pid 23699]: No data available</span>
<span style="color: blue">Apr  8 00:00:14 ew colord[1172]: failed to get session [pid 23699]: No data available</span>
<span style="color: blue">Apr  8 00:05:01 ew CRON[23838]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)</span>
<span style="color: blue">Apr  8 00:15:01 ew CRON[24082]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)</span>
<span style="color: blue">Apr  8 00:17:01 ew CRON[24128]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)</span>
<span style="color: blue">Apr  8 00:21:49 ew kestrel-store[22413]: #033[40m#033[32minfo#033[39m#033[22m#033[49m: WebOptimizer.AssetMiddleware[1000]</span>
<span style="color: blue">Apr  8 00:21:49 ew kestrel-store[22413]:       Request started for '/c/version.js'</span>
<span style="color: blue">Apr  8 00:21:49 ew kestrel-store[22413]: #033[41m#033[30mfail#033[39m#033[22m#033[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]</span>
<span style="color: blue">Apr  8 00:21:49 ew kestrel-store[22413]:       An unhandled exception has occurred while executing the request.</span>

Expected output is:

enter image description here


Solution

  • Hope this is helpful. I used rextester.com write a formatted code. But tests with files doesn't work there.

    Please correct this post if necessary. Also its not the shortest version, but I think its most clear.

    //Rextester.Program.Main is the entry point for your code. Don't change it.
    //Microsoft (R) Visual C# Compiler version 2.9.0.63208 (958f2354)
    
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    namespace Rextester
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                using (var reader = new StreamReader(@"c:\your_input_file.txt"))
                using (var writer = new StreamWriter(@"c:\your_output_file.html"))
                {
                    WriteHtmlHeader(writer);
                    string line;
                    while((line = reader.ReadLine()) != null)
                    {
                        line = AddSpan(line);
                    }
                    WriteHtmlFooter(writer);
                }
            }
            
            private static void WriteHtmlHeader(StreamWriter outfile)
            {
                // writing all the header and the start of body...
                // you can take it from another file
            }
            
            private static void WriteHtmlFooter(StreamWriter outfile)
            {
                // writing the footer of your html file
            }
            
            private static string AddSpan(string line)
            {
                if (Regex.IsMatch(line, "\x1b"))
                {
                    return AddStyledSpan(line, "color: green");
                }
                else if (Regex.IsMatch(line, "\["))
                {
                    return AddStyledSpan(line, "color: blue");
                }
                // ...
                else
                {
                    // Mark this span as error or standard
                    return AddStyledSpan(line, "color: red");
                }
            }
                
            private static string AddStyledSpan(string line, string style)
            {
                return "<span style=\"" + style + "\">" + line + "</span>";
            }
        }
    }
    

    Hope this helps. Also look at regex101 - online regex tester and debuggex - regex visualization. (But use it carefully, regular expressions works somtimes different).