Solved

Serilog logger question

Posted on 2015-01-24
17
171 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
  • 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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

 

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

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

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

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

828 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