Author |
|
Snoogz Newbie
Joined: 07 March 2016 Location: United States
Online Status: Offline Posts: 4
|
Posted: 24 October 2017 at 3:05pm | IP Logged
|
|
|
Hello,
I'm having an issue with the implementation of the SMTP Logger object, specifically I'm having an issue with using the in-memory logging while inside a C# parallel foreach.
My application calls SMTP.SendEmail() for each email object in a collection of emails, in parallel. We set smtp.Log.MemoryLog = true, and setup an event for smtp.LogNewEntry (for formatting reasons) to append each log to a string object. Then we save the return object in the database, which should contain the smtp logs for just that email. However what we're seeing is that the Logger object is shared across all the threads, which is causing our logs to be a jumbled up mess of smtp logs from all emails in that collection. Even using Logger.SyncRoot did not create suitable log output. Code snippets below.
Is there a thread safe way to implement in-memory logging? Or a way I can implement so that each email log only contains the smtp logs for its' email?
Workflow.cs
Parallel.ForEach(emails, (email) => {
// Call to email service layer
var result = emailSerivce.SendEmail(email);
});
EmailService.cs
public string log = "";
public Object SendEmail(Email email)
{
Smtp smtp = new Smtp();
smtp.Log.Enabled = true;
smtp.Log.MemoryLog = true;
smtp.Log.Format = MailBee.LogFormatOptions.AddDate;
smtp.LogNewEntry += SmtpOnLogNewEntry;
...
}
private void SmtpOnLogNewEntry(object sender, LogNewEntryEventArgs e)
{
log += string.Forat("{0} {1} {2}\n",e.NewEntry.Time, e.NewEntry.MessageType, e.NewEntry.MessageText);
}
Thank you
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 25 October 2017 at 3:05am | IP Logged
|
|
|
Hi,
Logger is unique per thread. However, your 'log' variable is not. It's shared among all the threads (and thus it ends up containing log records from all the threads). What's the purpose of this variable?
Regards,
Alex
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 25 October 2017 at 3:08am | IP Logged
|
|
|
More exactly, Logger is unique per Smtp instance. But because you're using one Smtp instance per thread, the result is just the same.
Regards,
Alex
|
Back to Top |
|
|
Snoogz Newbie
Joined: 07 March 2016 Location: United States
Online Status: Offline Posts: 4
|
Posted: 25 October 2017 at 11:20am | IP Logged
|
|
|
The purpose of the log variable is to keep a string copy of the formatted logs until the process has completed then return that string to the calling process to be saved in our database. It's a global variable because I couldn't see a different implementation of saving the formatted log entries.
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 25 October 2017 at 12:18pm | IP Logged
|
|
|
So your issue is actually not related to MailBee? You have code with many threads which all write into the same variable ('log'). So why are you asking why this happens (that all sessions from all threads write into the same variable) because that's what you're exactly doing? I don't get it..
If you need each session to be maintained separately, you obviously need to have separate 'log' variable for each thread (Smtp instance).
Regards,
Alex
|
Back to Top |
|
|
Snoogz Newbie
Joined: 07 March 2016 Location: United States
Online Status: Offline Posts: 4
|
Posted: 26 October 2017 at 1:26pm | IP Logged
|
|
|
You're correct. I was getting hung up on the existing implementation of our email services and how to implement the MailBee logging. Moving the logic inside the parallel foreach and containing my objects in a ConcurrentQueue gave me the results I was looking for.
Parallel.ForEach(emailQueue, email =>
{
string log = "";
Smtp mailer = new Smtp();
mailer.Log.Enabled = true;
mailer.Log.MemoryLog = true;
mailer.LogNewEntry += (sender, args) =>
{
log += "Formatted logs Here";
}
...
mailer.Send();
email.Log = log;
}
Thanks for the clarification.
|
Back to Top |
|
|