Given a list of objects, I'd like to log a specific attribute of each element in the list (say, its name). The only thing I can think of is logging in a forloop. Is there a better way to achieve what I want?
Small example:
public class Dog
{
public string Name { get; set; }
public int Id { get; set; }
public bool CanBark{ get; set; }
}
and then somewhere else in my code
public void GetAllDogsWithLogs(){
List<Dog> barkingDogs = GetBarkingDogs();
foreach(var dog in barkingDogs){ // ---> I'd like to avoid a forloop just for logging
Log.Debug("Found barking dog {Name} with Id {Id}", dog.Name, dog.Id);
}
}
Note that I cannot log all attributes of my objects, since that would introduce way too much noise into my logs.
For posterity: I ended up solving this using LINQ:
Log.Debug("Found barking dogs with name and ID {NameIds}",
barkingDogs.Select(dog => (dog.Name, dog.Id));
I'd recommend leveraging the destructuring mechanism in Serilog to support this.
You can use the special @
character when logging the entity to trigger destructuring of the object as documented here:
Log.Debug("Found barking dog {@Dog}", dog);
Then, configure the destructuring logic as per here:
new LoggerConfiguration()
.Destructure.ByTransforming<Dog>(
d => new { Name = d.Name, /* add other properties here */ })
This relies on inline configuration so it can get a bit verbose.
If you want a more general purpose destructuring logic, you could implement your own IDestructuringPolicy
that checks for the presence of an attribute on each property for example, or just use one of the existing solutions from here:
This particular package allows you to control destructuring via attributes which would give you the general purpose solution right away without having to implement your own logic:
Just configure the logger like this:
var log = new LoggerConfiguration()
.Destructure.UsingAttributes()
And then use the [LogWithName]
and [NotLogger]
attributes accordingly to customize the name / opt-out of the log data for a particular object:
public class Dog
{
[LogWithName("DogNameOrSomething")]
public string Name { get; set; }
[NotLogged]
public int Id { get; set; }
[NotLogged]
public bool CanBark{ get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With