Solved

Serilog logger question

Posted on 2015-01-24
17
181 Views
Last Modified: 2015-01-28
Hello,
I am using Serilog for the first time to perform logging. I am outputting to a text files with the following statement:

MyGlobals.logger.Debug("Test1 User: {UserName} ", MyExe.userId);

I am getting the following output:
2015-01-24 19:26:11.965 +00:00 [Debug] Test1 User: "pclarkeirl"
This works well.

I now want to be able to make the output more configurable by passing in the text and variables that are to be output by the logger.

MyGlobals.logger.Debug(message);
Where message is set to  “Test1 User: {UserName}, MyExe.userId”

However I am getting the following output:
2015-01-24 19:26:14.245 +00:00 [Debug] Test1 User: {UserName}, MyExe.userId
It is treating the whole line as text.

Is there any way that I can pass the logger message in as a variable and have it displayed correctly?

regards
Pat
0
Comment
Question by:pclarke7
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
17 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40570656
It doesn't look like you are passing in the data to the call.

Example:

http://serilog.net/

log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
0
 

Author Comment

by:pclarke7
ID: 40571158
Hi Bob,
 you are right, my data is coming in as text. Taking your example, what if I wanted to build the string

Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs


 rather than hardcode it. First I would get the text portion

 myString="Processed {@Position} in {Elapsed:000} ms."

 but how can I append the positions,elapsedMs
 without making the whole thing a string ?

 regards
 Pat
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40571199
The signature for that method is:

Serilog.Log.Debug(string, params object[])

Open in new window


All you would need to do is pass in an array of objects.

This would be equivalent to your first statement:

var valueList = new object[] {  MyExe.userId };
MyGlobals.logger.Debug("Test1 User: {UserName} ", valueList);

Open in new window

0
Salesforce Has Never Been Easier

Improve and reinforce salesforce training & adoption using WalkMe's digital adoption platform. Start saving on costly employee training by creating fast intuitive Walk-Thrus for Salesforce. Claim your Free Account Now

 

Author Comment

by:pclarke7
ID: 40571234
Hi Bob,
I think you are missing what I am trying to achieve. I know that I can log successfully by issuing a statement like   MyGlobals.logger.Debug("Test1 User: {UserName} ", MyExe.userId );  but I want the flexibility to have the text and variables passed to the logger at run time.

MyGlobals.logger.Debug("variable text {A} {B} {C}", varfield1,varfield2,varfield3)

but when I try to build this string I get:
"variable text {A} {B} {C}, varfield1 , varfield2,varfield3"

instead of

"variable text {A} {B} {C}" ,  varfield1,varfield2,varfield3

regards
Pat
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40571252
Are you building the string like this?

MyGlobals.logger.Debug("variable text {A} {B} {C}", varfield1,varfield2,varfield3);

Open in new window

0
 

Author Comment

by:pclarke7
ID: 40571454
Yes,
that's how I'm trying to build the string but it is interpreting everything as belonging inside double quotes. I am not sure how to change it so it can interpret the 3 fields as fields.

I'm getting this:   MyGlobals.logger.Debug("variable text {A} {B} {C}, varfield1,varfield2,varfield3)";

what I want is this: MyGlobals.logger.Debug("variable text {A} {B} {C}", varfield1,varfield2,varfield3);

the difference being the quotes
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40571473
What are the values for varfield1,varfield2,varfield3?
0
 

Author Comment

by:pclarke7
ID: 40572313
These values will vary. The application looks at the transaction type being processed and will set a different value based on the type.

Trans type 'D'  will have varfield values of  'userId, transactionId, FieldValuesDict'
Trans type 'I'    will have varfield values of  'userId, transactionId, InputValuList, OutputValuList'
etc...

regards
Pat
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40573234
If you do this:

MyGlobals.logger.Debug("variable text {A} {B} {C}", varfield1,varfield2,varfield3);

Open in new window


where varfield1 = userId, varfield2 = "transactionId", varfield3 = "FieldValuesDict",

what do you want to show in the log?
0
 

Author Comment

by:pclarke7
ID: 40573537
The user decides what viarables (from a list of dozens of available variables) that they want to view on the logger by transactions. So 1 user might decide that they just want to see the values dictionary for transaction type 'D' whilst another might want to log the full list of  variables available.

This is why I am trying to build the logger statement at run time rather than hard code it.

regards
Pat
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40573657
I am certainly not seeing the "big picture" here, so if I understand what you are looking for, it would be something like this Windows Forms example (with a ListBox):

            var valueList = new List<object>();

            var builder = new StringBuilder();

            var count = 0;

            for (var i = 0; i < listBox1.Items.Count; i++)
            {
                if (listBox1.GetSelected(i))
                {
                    var text = listBox1.Items[i].ToString();

                    builder.Append("{");
                    builder.Append((char)(i + 65));
                    builder.Append("} ");

                    switch (text)
                    {
                        case "userId":
                            valueList.Add(data.userId);
                            break;

                        case "transactionId":
                            valueList.Add(data.transactionId);
                            break;

                        case "FieldValuesDict":
                            valueList.Add(data.FieldValuesDict);
                            break;
                    }
                }
            }

            var message = "variable text " + builder.ToString();

            MyGlobals.logger.Debug(message, values.ToArray());

Open in new window

0
 

Author Comment

by:pclarke7
ID: 40574065
Hi Bob,
yes, I think your example is close. I have simplified it below:

                    var text = "THIS IS A TEST:";
                    string[] list1 ={"User name:", "Transaction:" ,"Transaction values:"};
                    string[] list2 = { "MyUser.userId", "MyTransSeq.transactionId", "MyVarValueDict" };
                    for(int j=0; j< list1.Length; j++)
                    {
                        text = text + list1[j] + " {"+j+"} ";
                    }
                  MyGlobals.logger.Information(text, list2.ToArray());
 
At the time of running
MyUser.userId='pclarkeirl' ,
MyTransSeq.transactionId='initmenu01'
MyVarValueDict=  various values
text="THIS IS A TEST:User name: {0} Transaction: {1} Transaction values: {2} "

The output of the  logger is:
2015-01-27 22:40:55.110 +00:00 [Information] THIS IS A TEST:User name: ["MyUser.userId", "MyTransSeq.transactionId", "MyVarValueDict"] Transaction: {1} Transaction values: {2}

It seems to have taken the 3 values in list 2 and assumed they were just 1 value belonging to {0} rather than 3 values belonging to {0},{1},{2}. Any idea how I can get the value of list2 to appear as 3 literals ?

regards
Pat
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40574360
How are you creating the logger?  

What type of sink are you using?
0
 

Author Comment

by:pclarke7
ID: 40574683
Hi Bob,
just writing to a text file. The logger works perfectly when I hard code the values such as

MyGlobals.logger.Information(User name: {0} Transaction: {1} Transaction values: {2} ,MyUser.userId, MyTransSeq.transactionId, MyVarValueDict)

The issue is getting the variable to be seen as literals rather than text enclosed in " ". I'm not sure how to achieve this ?

regards
Pat
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
ID: 40575367
This is tricky--reviewing the signature (Debug(string, params object[]), you would need an object array, not a string array.  I don't believe that the compiler will map the parameter objects otherwise.  

Try this instead:

 var text = "THIS IS A TEST:";
                    string[] list1 ={"User name:", "Transaction:" ,"Transaction values:"};
                    var list2 = new object[] { MyUser.userId, MyTransSeq.transactionId, MyVarValueDict };
                    for(int j=0; j< list1.Length; j++)
                    {
                        text = text + list1[j] + " {"+j+"} ";
                    }
                  MyGlobals.logger.Information(text, list2.ToArray());

Open in new window

0
 

Author Comment

by:pclarke7
ID: 40576103
Hi Bob,
Works like a charm.


2015-01-28 20:56:09.146 +00:00 [Information] THIS IS A TEST:User name: "pclarkeirl" Transaction: "initmenu01" Transaction values: [("<&option>": " "), ("<&envname>": "prod"), ("<&test>": "MYTESTVALU"), ("<&envcount>": "3"), ("<&companyid>": "strykerlmk"), ("<&envdesc1>": "Production Env"), ("<&envdesc2>": "Limerick Production environment"), ("<&envcolour>": "green"), ("<&count>": " "), ("<&selopt>": " ")]


thank you for all of your help on this. points certainly earned.

regards
Pat
0
 

Author Closing Comment

by:pclarke7
ID: 40576105
thanks for your patience
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question