Table of Contents
Other articles in the Log Wizard Series
Introduction, Filters, Notes, Windows Event Logs
I created Log Wizard to make viewing Log Files (and Logs in general) as painless as possible. In fact, my focus is making viewing Logs enjoyable!
Of course, you're the judge of that - let me know what you think, and also, let me know what I can do to improve this even further.
Note that I host the project on github, where I strive to do a new release every 3-4 weeks.
As of version 1.8, I've added Pretty Formatting to it, to help you easily focus on what's relevant to you. Or put another way, have the relevant information stand out.
Here's how to have the relevant information stand out:
- Hide lines that are irrelevant to your task at hand. Or, put another way, Filters. I've discussed them here.
- Color the information that is relevant to you, so that it stands out.
- Hide some of the information, so that you view more information at a time (In other words, abbreviate some stuff that is usually unimportant. You can always un-abbreviate it)
- Visually group several things that belong together into categories. Such as, have all rows from a thread painted in a certain (backgound) color.
For the latter 3 cases, I've added Column Formatting. Or, Pretty Formatting sounds better ;)
A picture is worth a thosand words:
- current selection is at line 8813
- bookmarks at 8727 and 8784
- lines are shown quite nicely, a' la intelliJ
- notice how lines background alternates, but just a bit, so that it doesn't hurt the eyes
- notice how the selection is just a tad darker, enough to let you know where it is
- time: I'll let you figure it out for yourself ;)
- level: lines 8697, 8854 and 8978 are warnings
- numbers are shown in red
After using Formatters, which I'll explain below, you'll notice a few things:
As long as you specify them correctly, they only override what they need, leaving the rest unchanged. For example, a Filter can specify a line is blue. In that line, the "Number" formatter will how all numbers in red, leaving the rest of the line blue (as it originally was).
So, lets get started! The purpose of Column Formatting is to make important stuff stand out. Stand out, and Look Pretty!
You decide what stuff is important! Log Wizard comes with a few defaults, but you can configure it until it suits your needs.
To edit the Formatting, right click on any Column Header. You'll notice the last option:
Select it, and you get to edit the Formatters.
I've made it simple:
- Top-left is the Formatters. I'll explain the syntax below
- A bit of help on the top-right
- On the lower pane, you'll see an Instant Preview of what you're editing. Anything you change: add/ remove/modify a Formatting line, you'll notice its effects immediately. If any Formatting Line is in error, you'll notice the error shown below, in red.
- Apply to current View - in case you have several views, you can choose to apply this Formatting only the the current view.
My focus has been to let you achieve your Formatting goal in as few lines as possible. Here's the syntax:
[column_name1]
formatter_name1
property11=value11
property12=value12
...
[column_name2]
formatter_name2
property21=value21
propertyp22=value22
...
The column_name
is what the name says - the name of the column:
all
- applies it to all columns. An easy way to apply a formatting everywhere. msg
- refers to the Message column. thread-
refers the the Thread column, and so on. Just remember to write it in lowercase.
You will use all
quite a bit - to easily apply formatting to all columns.
The formatter_name
specifies the Formatter to be applied. Its settings are easily set in a property=value
fashion. I'll explain each important formatter below.
To keep things to a minimum, I've provided the following formatters:
cell
- contains formatting to be applied altogether to the cell. format
- contains general formatting, such as - regexes, abbreviations, numbers and so on. Depending on its settings, it can apply to parts of the text (not to the text as a whole). picture
- allow replacing texts with pictures.
Throughout the remainder of the article, you will see a whole lot of settings. All of them are optional. If something is not set, the part dealing with that setting wil simply not happen. The rest will continue as usual.
In case you specify a setting B
that depends on a setting A
, but forget to set the setting A
, Log Wizard will behave as both settings A
and B
are not set.
This is the easiest formatter. It applies formatting to the whole cell. I've mainly used it for line
column, but you can use it anywhere. The settings are:
format=<format>
- applies this format to the whole cell selection=<image>
- shows an image on the row that contains the selection bookmark=<image>
- shows an image on the row that contains a bookmark align=<alignment>
- aligns the text (+ image). Possible values: left
(default), center
, and right
The format
is what font and/or color(s) to apply to the cell. You'll encounter the format
setting in quite a few Formatters. Its syntax is always like this:
The format property has a flexible syntax: a/b/c...
It specifies some formatting to be applied to some text.
a
, b
, c
, can be any of:
bold
, italic
, underline
- make the font bold, italic or underline darker
, lighter
- make the foreground color a bit darker or lighter darker-bg
, lighter-bg
- make the background color a bit darker or lighter #color
- set the color. If it's the first occurrence, it's the foreground. The second occurrence is the background. To force a color to be background, just add an extra #
, like ##color
. font name
- specify the font name, such as, tahoma
or arial
. font size
- specify the font size
Examples:
darker/12/italic
- format the text italic, 12pt, and darker than is (relative to how the normal color would be) tahoma/9/red
- make the text red, 9pt, Tahoma arial/11/darker/italic
- make the text Arial, 11pt, italic and darker than it would be
Lets get back to the cell
Formatter. I've show you the format
property. The selection
and bookmark
are image file names. They can either be relative to the Log Wizard Home (User's Home\Documents\LogWizard
directory), or absolute file names.
So, the following:
[line]
cell
format=courier new/#800000/#F0F0F0
align=right
selection=icons\arrow4.png
bookmark=icons\bookmark8.png
will generate this
Note that there are a few other icons you can choose from, to easily customize it to your liking. Just go to Home\
Documents
\
LogWizard
and take a look.
This is sort of a jack-of-all-trades formatter. Just set only what you need. I've split this into sub-sections. You can specify as many or as few formatting options as you want:
Allows you to apply formatting to a regular expression, when found in the text.
regex.expr=<regex_expr>
- the regex_expression to match regex.format=<format>
- the format to apply to the regex. Note that at this time (1.8) - I only allow the color to be specified. I will fix this to allow any formatting in a future version. regex2.expr=<regex_expr>
- same as above regex2.format=<format>
- same as above - ...
regexN.expr=<regex_expr>
- same as above regexN.format=<format>
- same as above
Example:
[msg]
format
regex.expr=(?<=\[).*(?=\])|(?<=\().*(?=\))|(?<=\{).*(?=\})
regex.format=lighter
regex2.expr=(?<=")(?:\\.|[^"\\])*(?=")|(?<=')(?:\\.|[^'\\])*(?=')
regex2.format=darkviolet
The above will show text in any brackets (normal brackets, square brackets or curly braces) in a lighter color, and text in quotes (single or double) in violet.
If you're not familiar with regexes, I highly recommend you get acquainted with them - there are awesome things you can do, and I've optimized Log Wizard to show the results really really fast.
Allows you to make text shorter, so that you can see more text that actually matters.
I can't stress enough how awesome this is.
When some column's text is too big, usually there will be some part of it that is important only probably 1% of the time. You could end up not being able to read it all, and having to painfully go through each message's details to see what it says. Or,
You can use abbreviations, like this:
- On the Message column, to abbreviate some properties that you dump. You might dump them as "
prop1=value1,prop2=value2, ...
", but you're so used to this that you know the names of prop1
, prop2
, etc. by heart. When watching the log, you want to see only the values. - To simply hide some information you usually don't need. You can hide it altogether, or you can replace it with something like
...
together with some color that will hint that there's something there. - On some
function
or class
-like column, to hide the strenous namespace or prefix information, that is usually the same all the time, and you simply don't care for it.
The syntax is boringly easy:
abb.find=<regex_to_find>
- the regex to find. You can use named regexes. abb.replace=<regex_to_replace_with>
abb2.find=<regex_to_find>
- same as above abb2.replace=<regex_to_replace_with>
- same as above - ... - you can have as many abbreviations as possible
abbN.find=<regex_to_find>
- same as above abbN.replace=<regex_to_replace_with>
- same as above
If you don't specify the .replace
part, we simple remove the found regex from the text.
You can also apply formatting to the replaced text. Anything between ["
and "]
is formatting to be applied to the text in-between (I'll show you an example below)
You can use named regexes for the replaced text.
Once you've brushed up on your regexes, the next level is definitely to use named regexes. Long story short, you can identify pieces of text from your find, and use them in the replaced expression. For example, say you want to find expressions like {x=<value>,y=<value>,width=<value>,height=<value}
, and replace them with [x,y,width/height]
. Just let that ponder for a bit. How would you do it?
Amazingly, this is actually possible:
[msg]
format
abb.find=\{x=(?<x>\d*),y=(?<y>\d*),width=(?<w>\d*),height=(?<h>\d*)\}
abb.replace=["green"][["red/bold"]${x},["blue/italic"]${y},["violet/bold"]${w}/${h}["green"]]
Here's the result. Pretty neat, yeah?
In the second example, I'll show you how to get rid of long column text:
[ctx2]
format
abb.find=^.*:(?<name>.*)\.xaml
abb.replace=["tahoma/red"]...["blue"]${name}
The above will find any name that ends in .xaml, and remember only the end part - which is basically what you want.
Finally, abbreviations are really smart:
- Abbreviations only apply to the View pane. They don't apply to the Details Pane. So you can always see the full text in Details, if you truly want to (which 99.99% of the time is No).
Look again at the above two pictures - see the Details pane? - They can always be toggled ON/OFF. By default, abbreviations are ON. You can toggle them OFF by pressing
Ctrl-Shift-A
. In this case, the original text is shown. Press Ctrl-Shift-A
again - and abbreviations are back ON.
This allows you to format numbers from the text
number.base=2 or 8 or 10 or 16
(default=10). In what base to show the numbers. number.pad=<padding>
- how to pad the numbers (only when base is 10). The padding is what you would use in c# to pad a number when you print, such as "0,000
", "00.0
" and so on number.color=<color>
- the color for showing the numbers number.look_for_hex=1
or 0 (default=1) - if 1, we also look for hexadecimal numbers (in order to print them in a color you set above)
Example:
number.color=darkred
This will show all numbers in darkred color.
One thing to note is that you seldom need to specify the number base (leave it to the default). But, you can toggle between bases via Ctrl-Shift-B
hotkey. Press it once, and you have base 16:
Press it again, and you have base 8
Press it again, and you have base 2, and then back to base 10.
And as an extra bonus, just move your mouse over a number: it will be shown in all bases:
This sub-formatter only applies to date/time columns (it's ignored for the other columns)
time.show_diff=0 or 1
(default=1). If 1, it will always show difference between this and the previous row, so that you very easily see what changed. This is an awesome way to find out what changes from row to row time.format=<format>
- formatting to be applied to the time. time.light=<color>
- Only useful when show_diff=1
. What color to use for showing what's same as previous time time.format_time=<format_time>
- how to show the time, a' la' C#'s custom date/time formatting
Example:
[all]
format
time.format=courier new/blue/bold
time.format_time=MMM/dd HH:mm:ss,fff
time.light=#adc7e8
This will show the time column like this
This basically acts as the cell formatter
described above. The idea in addition to the settings below, you can set any of the other format
settings (which are quite a few, as you can see).
all.format=<format>
- applies formatting to all cell all.selection=<image>
- shows an image for the row that contains the selection all.bookmark=<image>
- shows an image for the row that contains a bookmark
This allows you to specify alternate backgrounds to the rows, allow you to easily differentiate between them:
alternate.row_count=<rows>
- how many consecutive rows to paint in a certain color. If 1, paint one row in one color, the other one in the alternate color and so on. If 5, paint 5 rows in one color, the next 5 rows in the alternate color, and so on. alternate.color=<color>
- the alternate color
Example:
[msg]
format
alternate.row_count=5
alternate.color=#d7e5ff
This is an awesome tool if one or several of your columns can contain several lines. What this can help you with - is to show you several lines into a single line, so that you view as much as possible.
multiline.multi=0 or 1
(defaults to 0). If 1 (on), in case the text contains several lines, they are shown on a single line, so that you see as much info as possible. multiline.separator=<separator-char>
- how to separate each line, when showing several lines multiline.separator_format=<format>
- how to format the separator, to easily see where each line is multiline.alternate_format=<format>
- how to show each alternate line, in order to easily differentiate between them
Example:
[msg]
format
multiline.multi=1
multiline.alternate_format=lighter
multiline.separator=|
multiline.separator_format=blue
You'll love this, for example, for Windows Event Logs:
It allows you to compare a number against one or several values, and based on that, select its formatting.
It is very useful when a number can get dangerously high or dangerously low - and you want to easily see that.
compare-n.where=before*after
- How to identify the number (before
and after
are both strings). compare-n.value=int or double
(default=int). What the number is - integer, or double compare-n.compare=value,format-less,format-equal,format-greater
- compares number against value. If less, apply the first formatting. If equal, apply middle formatting. If greater, apply last formatting. compare-n.compare2=value,format-less,format-equal,format-greater
- same as above, you can compare the original number against several values - ... - you can compare against as many values as you wish
compare-n.compareN=value,format-less,format-equal,format-greater
- same as above, you can compare the original number against several values
Example:
compare-n.where=time*ms
compare-n.compare=100,green,yellow,orange
compare-n.compare2=200,,,red
compare-n.compare3=400,,,bold
This will look for numbers like 'time 93 ms', 'time 352 ms'. Numbers:
- less than 100 are shown in green
- 100 is shown yellow
- between 100-200 are shown in orange
- between 200-400 are shown in red
- higher than 400 are shown in red / bold
This is a formatter on its own. It replaces any cell starting with a given text with a picture:
pic=text->image
- if the cell's text starts with text (case-insensitive), it will show the given image pic2=text2->image2
- same as above - ... - you can have as many pictures as you wish
picN=textN->imageN
- same as above align=<alignment>
. How to align the picture (left
, right
or center
).
Example:
[level]
picture
pic=info->icons\level\info.png
pic2=error->icons\level\error.png
pic3=fatal->icons\level\fatal.png
pic4=debug->icons\level\debug.png
pic5=warn->icons\level\warn.png
align=center
This is basically your default level formatter.
Now that I've shown you the available formatters, I've set some default formatters for you. Assuming you don't specify anything, you'll inherit somethine more or less like this:
[line]
cell
format=courier new/#800000/#F0F0F0
align=right
selection=icons\arrow4.png
bookmark=icons\bookmark8.png
[all]
format
time.format=courier new/blue/bold
time.format_time=MM/dd HH:mm:ss,fff
time.light=#adc7e8
[msg]
format
number.color=darkred
regex.expr=(?<=\[).*(?=\])|(?<=\().*(?=\))|(?<=\{).*(?=\})
regex.format=lighter
regex2.expr=(?<=")(?:\\.|[^"\\])*(?=")|(?<=')(?:\\.|[^'\\])*(?=')
regex2.format=darkviolet
alternate.row_count=1
alternate.color=#fbfdf9
multiline.multi=0
multiline.alternate_format=lighter
multiline.separator=|
multiline.separator_format=blue
[level]
picture
pic=info->icons\level\info.png
pic2=error->icons\level\error.png
pic3=fatal->icons\level\fatal.png
pic4=debug->icons\level\debug.png
pic5=warn->icons\level\warn.png
align=center
If you look closely, you'll find stuff I've already explained. You can change this in Preferences >> Colors >> Column Formatting : Default Format
. If you wish to change it, I highly recommend you only do after testing it on an existing log.
The Categories
allows you to:
- Pick a column
- LogWizard will find out all the unique values from that column
- You can assign a Background color based on the value from the column
- Rows of the same type as the selection are shown a bit darker
This is a huge feature.
To understand this best, it's better to come up with an example: Threads
. Assuming you have a Thread
column:
- Press
Alt-C
to show Categories. - In the
Categories
combo, select Thread
, if not already selected - Wait a bit until Log Wizard finds out all unique thread names
- By default, Log Wizard will come up with some background colors for each unique thread. You can leave them as is, or override them
- One thing to note is that Log Wizard will remember your choice and re-use it next time
Here's what to remember
- You can select any
Category
(= Column) you want.
- Log Wizard will compute unique values for that column and show them to you
- If a Category (= Column) has too many values, it will show an error. At this point, we accept up to 25 unique values (more than that, likely coloring won't help much)
- You will see 4 rows
Value
- one of the unique values from the Column Color
- Source color to compute the Background colors for this unique value. You can click on it to change it. By default, Same
and This (Sel)
colors are computed from this - these are both background colors to show the row tha contains this specific value. Same
- this is the background color to use when a value is same as Value
. This (Sel)
- this is the background color to use when a value matches the Value
of the selected row. The idea is for the rows tha match the selection to be a bit darker. As soon as you use it, you'll see what I mean - Both
Same
and This (Sel)
are by default computed from Color
. The only reason for Color'
s existance is to compute Same and This (Sel). - If you're not happy with the default computed
Same
and This (Sel)
, you can override them.
Once you're happy with the selection, just press the Start
button (lower right).
The result is instantaneous - rows are grouped by color, given the Category
value you chose. For Threads
, this makes total sense right away - you'll be able to easily see which log line comes from what thread.
It will really help you grasp complicated scenarios - when messages can and do come from several Threads
.
Your Category
of choice might be different, but being able to easily see which row comes from where can help a lot - especially with bigger and more complicated logs.
You might very well ask - why would I ever use Categories, when Pictures can achieve pretty much the same desired effect?
This is indeed true, when your set of available values is small and fixed. In this case, pictures are indeed worth a thousand words, and the Level column shown throughout the article is living proof of that.
Things become much blurrier when the number of available values is not that fixed (and is usually found out at runtime). For instance, based on your configuration, your application might have 5 threads, or might have 15 threads. The names of the threads might also not be fixed - running a specific module can cause a few threads to start, while if not running it, those threads will never start.
Another thing to consider (at least at the beginning) is if you have several columns that can be deemed as Category
columns. In this case, just doing Alt-C
, selecting a Category
, and hitting Start
is sure a fast way to get an overview of what's happening.
In the end, for sure, if your column has a unique set of values, and you can easily assign a picture to each value, go for that. Otherwise, you will simply love Categories. I certainly do.
I wish you Pretty Logging!
- 15 Feb 2016, Initial version (v1.8)