source: trunk/FACT++/src/showlog.cc @ 19438

Last change on this file since 19438 was 16968, checked in by tbretz, 6 years ago
Added a possibility to strip color codes.
File size: 6.1 KB
Line 
1#include <boost/regex.hpp>
2
3#include "Time.h"
4#include "tools.h"
5#include "WindowLog.h"
6#include "Configuration.h"
7
8
9using namespace std;
10
11// ------------------------------------------------------------------------
12
13void SetupConfiguration(Configuration &conf)
14{
15    po::options_description control("Showlog");
16    control.add_options()
17        ("file,f",    vars<string>(), "File names of log-files to be read.")
18        ("begin,b",   var<string>(), "Start time to be displayed (e.g. 20:00:12)")
19        ("end,e",     var<string>(), "End time to be displayed (e.g. 21:00:13)")
20        ("verbose,v", var<int16_t>()->implicit_value(true)->default_value(8), "Verbosity level (0:only fatal errors, 8:everything)")
21        ("color,c",   po_switch(), "Process a file which already contains color codes")
22        ("strip,s",   po_switch(), "Strip color codes completely")
23        ;
24
25    po::positional_options_description p;
26    p.add("file", -1); // The first positional options
27
28    conf.AddOptions(control);
29    conf.SetArgumentPositions(p);
30}
31
32void PrintUsage()
33{
34    cout <<
35        "showlog - Log file converter\n"
36        "\n"
37        "This tool can be used to convert the log-files written by the\n"
38        "datalogger back to colored output, limit the displayed time\n"
39        "range and limit the displayed severity of the messages.\n"
40        "Note that this tool will not work by default on logs containing\n"
41        "already colored output as the logs directly written by the programs.\n"
42        "Use -c or --color to process color coded files.\n"
43        "\n"
44        "The default is to read from stdin if no filoename as given. If, as "
45        "a filename, just a number between 2000000 and 21000000 is given, "
46        "e.g. 20111016 a log with the name /fact/aux/2011/10/16/20111016.log "
47        "is read.\n"
48        "\n"
49        "Usage: showlog [-c] [-vN] [-b start] [-e end] [file1 ...]\n"
50        "  or:  showlog [-c] [-vN] [-b start] [-e end] YYYYMMDD\n";
51    cout << endl;
52}
53
54void PrintHelp()
55{
56    cout <<
57        "\n"
58        "Examples:\n"
59        " cat temperature.log | showlog -c -v2\n"
60        " showlog -c temperature.log -v2\n"
61        " cat 20130909.log | showlog -v2\n"
62        " showlog 20130909.log -v2\n"
63        "\n";
64    cout << endl;
65}
66
67
68void showlog(string fname, const Time &tbeg, const Time &tend, int16_t severity, bool color, bool strip)
69{
70    // Alternatives
71    // \x1B\[[0-9;]*[mK]
72    // \x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]
73    // \x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]
74    const boost::regex reg("\x1B\[([0-9]{1,3}(;[0-9]{1,3})?[a-zA-Z]");
75
76    const uint32_t night = atoi(fname.c_str());
77    if (night>20000000 && night<21000000 &&to_string(night)==fname)
78        fname = Tools::Form("/fact/aux/%04d/%02d/%02d/%d.log",
79                            night/10000, (night/100)%100, night%100, night);
80
81    if (!fname.empty())
82        cerr << "Reading " << fname << endl;
83
84    ifstream fin(fname.empty() ? "/dev/stdin" : fname.c_str());
85    if (!fin)
86        throw runtime_error(strerror(errno));
87
88    string buffer;
89
90    WindowLog log;
91
92    Time tprev;
93
94    while (getline(fin, buffer, '\n'))
95    {
96        if (color || strip)
97            buffer = boost::regex_replace(buffer, reg, "");
98
99        if (buffer.size()==0)
100            continue;
101
102        if (buffer.size()>18)
103        {
104            const string tm = buffer.substr(4, 15);
105
106            const Time t("1970-01-01 "+tm);
107
108            if (tbeg.IsValid() && !tend.IsValid() && t<tbeg)
109                continue;
110
111            if (tend.IsValid() && !tbeg.IsValid() && t>tend)
112                continue;
113
114            if (tbeg.IsValid() && tend.IsValid())
115            {
116                if (tend>tbeg)
117                {
118                    if (t<tbeg)
119                        continue;
120                    if (t>tend)
121                        continue;
122                }
123                else
124                {
125                    if (t>tbeg)
126                        continue;
127                    if (t<tend)
128                        continue;
129                }
130            }
131        }
132
133        if (buffer.size()>1 && !strip)
134        {
135            int16_t lvl = -1;
136            switch (buffer[1])
137            {
138            case ' ': lvl = 7; break; // kDebug
139            case '#': lvl = 6; break; // kComment
140            case '-': lvl = 5; break; // kMessage
141            case '>': lvl = 4; break;
142            case 'I': lvl = 3; break; // kInfo
143            case 'W': lvl = 2; break; // kWarn
144            case 'E': lvl = 1; break; // kError/kAlarm
145            case '!': lvl = 0; break; // kFatal
146            }
147
148            if (lvl>severity)
149                continue;
150
151            switch (buffer[1])
152            {
153            case ' ': log << kBlue;          break; // kDebug
154            case '#': log << kDefault;       break; // kComment
155            case '-': log << kDefault;       break; // kMessage
156            case '>': log << kBold;          break;
157            case 'I': log << kGreen;         break; // kInfo
158            case 'W': log << kYellow;        break; // kWarn
159            case 'E': log << kRed;           break; // kError/kAlarm
160            case '!': log << kRed << kBlink; break; // kFatal
161            }
162        }
163
164        (strip?cout:log) << buffer << endl;
165    }
166}
167
168int main(int argc, const char* argv[])
169{
170    Configuration conf(argv[0]);
171    conf.SetPrintUsage(PrintUsage);
172    SetupConfiguration(conf);
173
174    if (!conf.DoParse(argc, argv, PrintHelp))
175        return 127;
176
177    const vector<string> files = conf.Vec<string>("file");
178
179    Time tbeg(Time::none);
180    Time tend(Time::none);
181
182    if (conf.Has("begin"))
183    {
184        std::stringstream stream;
185        stream << "1970-01-01 " << conf.Get<string>("begin");
186        stream >> Time::iso >> tbeg;
187    }
188
189    if (conf.Has("end"))
190    {
191        std::stringstream stream;
192        stream << "1970-01-01 " << conf.Get<string>("end");
193        stream >> Time::iso >> tend;
194    }
195
196    if (files.size()==0)
197        showlog("", tbeg, tend, conf.Get<int16_t>("verbose"), conf.Get<bool>("color"), conf.Get<bool>("strip"));
198
199    for (auto it=files.begin(); it!=files.end(); it++)
200        showlog(*it, tbeg, tend, conf.Get<int16_t>("verbose"), conf.Get<bool>("color"), conf.Get<bool>("strip"));
201
202    return 0;
203}
Note: See TracBrowser for help on using the repository browser.