创建自定义的事件接收器
Semantic Logging Application Block提供了大量的事件接收器,如Rolling Flat File,SQL Database, 云存储接收器等。这些接收器都实现了IObservable<EventEntry>接口。
有时这些并不能很好的满足客户需求,这时就需要定制事件接收器,比如邮件接收器、短信接收器等。
下面介绍以下如何定制邮件接收器,在特定的事件发生时自动发送邮件给指定的客户。
本文介绍了以下主题:
创建自定义接收器
在进程内使用自定义接收器
创建自定义接收器
要创建自定义接收器,必须实现IObservable<EventEntry>接口,该接口提供了3个函数:OnCompleted,OnError和OnExt
public interface IObserver<in T> { void OnCompleted(); void OnError(Exception error); void OnNext(T value); }
下面的展示了如何创建自定义的Email接收器。
public sealed class EmailSink : IObserver<EventEntry> { private const string DefaultSubject = "Email Sink Extension"; private IEventTextFormatter formatter; private MailAddress sender; private MailAddressCollection recipients = new MailAddressCollection(); private string subject; private string host; private int port; private NetworkCredential credentials; public EmailSink(string host, int port, string recipients, string subject, string credentials, IEventTextFormatter formatter) { this.formatter = formatter ?? new EventTextFormatter(); this.host = host; this.port = GuardPort(port); this.credentials = CredentialManager.GetCredentials(credentials); this.sender = new MailAddress(this.credentials.UserName); this.recipients.Add(GuardRecipients(recipients)); this.subject = subject ?? DefaultSubject; } public void OnNext(EventEntry entry) { if (entry != null) { using (var writer = new StringWriter()) { this.formatter.WriteEvent(entry, writer); Post(writer.ToString()); } } } public void OnCompleted() { } public void OnError(Exception error) { } private void Post(string body) { using (var client = new SmtpClient(this.host, this.port) { Credentials = this.credentials, EnableSsl = true }) using (var message = new MailMessage(this.sender, this.recipients[0]) { Body = body, Subject = this.subject }) { for (int i = 1; i < this.recipients.Count; i++) message.CC.Add(this.recipients[i]); try { client.Send(message); } catch (SmtpException e) { SemanticLoggingEventSource.Log.CustomSinkUnhandledFault( "SMTP error sending email: " + e.Message); } catch (InvalidOperationException e) { SemanticLoggingEventSource.Log.CustomSinkUnhandledFault( "Configuration error sending email: " + e.Message); } catch (...) { // additional exception handling code here. } } } private static int GuardPort(int port) { if (port < 0) throw new ArgumentOutOfRangeException("port"); return port; } private static string GuardRecipients(string recipients) { if (recipients == null) throw new ArgumentNullException("recipients"); if (string.IsNullOrWhiteSpace(recipients)) throw new ArgumentException( "The recipients cannot be empty", "recipients"); return recipients; } }
并使用一个扩展函数来实例化监听器,代码如下
public static class EmailSinkExtensions { public static EventListener CreateListener(string host, int port, string recipients, string subject, string credentials, IEventTextFormatter formatter = null) { var listener = new ObservableEventListener(); listener.LogToEmail(host, port, recipients, subject, credentials, formatter); return listener; } public static SinkSubscription<EmailSink> LogToEmail( this IObservable<EventEntry> eventStream, string host, int port, string recipients, string subject, string credentials, IEventTextFormatter formatter = null) { var sink = new EmailSink(host, port, recipients, subject, credentials, formatter); var subscription = eventStream.Subscribe(sink); return new SinkSubscription<EmailSink>(subscription, sink); } }
如何使用自定义接收器
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { var listener = new ObservableEventListener(); listener.LogToEmail("smtp.live.com", 25, "[email protected]", "In Proc Sample", "etw"); listener.EnableEvents(MyCompanyEventSource.Log,EventLevel.LogAlways, EventKeywords.All); MyCompanyEventSource.Log.Startup(); }