1
#region Copyright & License
3
// Copyright 2001-2005 The Apache Software Foundation
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
9
// http://www.apache.org/licenses/LICENSE-2.0
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
20
using System.Globalization;
22
using System.Net.Sockets;
29
namespace log4net.Appender
32
/// Sends logging events as connectionless UDP datagrams to a remote host or a
33
/// multicast group using an <see cref="UdpClient" />.
37
/// UDP guarantees neither that messages arrive, nor that they arrive in the correct order.
40
/// To view the logging results, a custom application can be developed that listens for logging
44
/// When decoding events send via this appender remember to use the same encoding
45
/// to decode the events as was used to send the events. See the <see cref="Encoding"/>
46
/// property to specify the encoding to use.
50
/// This example shows how to log receive logging events that are sent
51
/// on IP address 244.0.0.1 and port 8080 to the console. The event is
52
/// encoded in the packet as a unicode string and it is decoded as such.
54
/// IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
55
/// UdpClient udpClient;
57
/// string loggingEvent;
61
/// udpClient = new UdpClient(8080);
65
/// buffer = udpClient.Receive(ref remoteEndPoint);
66
/// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer);
67
/// Console.WriteLine(loggingEvent);
70
/// catch(Exception e)
72
/// Console.WriteLine(e.ToString());
75
/// <code lang="Visual Basic">
76
/// Dim remoteEndPoint as IPEndPoint
77
/// Dim udpClient as UdpClient
78
/// Dim buffer as Byte()
79
/// Dim loggingEvent as String
82
/// remoteEndPoint = new IPEndPoint(IPAddress.Any, 0)
83
/// udpClient = new UdpClient(8080)
86
/// buffer = udpClient.Receive(ByRef remoteEndPoint)
87
/// loggingEvent = System.Text.Encoding.Unicode.GetString(buffer)
88
/// Console.WriteLine(loggingEvent)
90
/// Catch e As Exception
91
/// Console.WriteLine(e.ToString())
95
/// An example configuration section to log information using this appender to the
96
/// IP 224.0.0.1 on port 8080:
98
/// <code lang="XML" escaped="true">
99
/// <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
100
/// <remoteAddress value="224.0.0.1" />
101
/// <remotePort value="8080" />
102
/// <layout type="log4net.Layout.PatternLayout" value="%-5level %logger [%ndc] - %message%newline" />
106
/// <author>Gert Driesen</author>
107
/// <author>Nicko Cadell</author>
108
public class UdpAppender : AppenderSkeleton
110
#region Public Instance Constructors
113
/// Initializes a new instance of the <see cref="UdpAppender" /> class.
116
/// The default constructor initializes all fields to their default values.
122
#endregion Public Instance Constructors
124
#region Public Instance Properties
127
/// Gets or sets the IP address of the remote host or multicast group to which
128
/// the underlying <see cref="UdpClient" /> should sent the logging event.
131
/// The IP address of the remote host or multicast group to which the logging event
136
/// Multicast addresses are identified by IP class <b>D</b> addresses (in the range 224.0.0.0 to
137
/// 239.255.255.255). Multicast packets can pass across different networks through routers, so
138
/// it is possible to use multicasts in an Internet scenario as long as your network provider
139
/// supports multicasting.
142
/// Hosts that want to receive particular multicast messages must register their interest by joining
143
/// the multicast group. Multicast messages are not sent to networks where no host has joined
144
/// the multicast group. Class <b>D</b> IP addresses are used for multicast groups, to differentiate
145
/// them from normal host addresses, allowing nodes to easily detect if a message is of interest.
148
/// Static multicast addresses that are needed globally are assigned by IANA. A few examples are listed in the table below:
151
/// <list type="table">
153
/// <term>IP Address</term>
154
/// <description>Description</description>
157
/// <term>224.0.0.1</term>
160
/// Sends a message to all system on the subnet.
165
/// <term>224.0.0.2</term>
168
/// Sends a message to all routers on the subnet.
173
/// <term>224.0.0.12</term>
176
/// The DHCP server answers messages on the IP address 224.0.0.12, but only on a subnet.
183
/// A complete list of actually reserved multicast addresses and their owners in the ranges
184
/// defined by RFC 3171 can be found at the <A href="http://www.iana.org/assignments/multicast-addresses">IANA web site</A>.
187
/// The address range 239.0.0.0 to 239.255.255.255 is reserved for administrative scope-relative
188
/// addresses. These addresses can be reused with other local groups. Routers are typically
189
/// configured with filters to prevent multicast traffic in this range from flowing outside
190
/// of the local network.
193
public IPAddress RemoteAddress
195
get { return m_remoteAddress; }
196
set { m_remoteAddress = value; }
200
/// Gets or sets the TCP port number of the remote host or multicast group to which
201
/// the underlying <see cref="UdpClient" /> should sent the logging event.
204
/// An integer value in the range <see cref="IPEndPoint.MinPort" /> to <see cref="IPEndPoint.MaxPort" />
205
/// indicating the TCP port number of the remote host or multicast group to which the logging event
209
/// The underlying <see cref="UdpClient" /> will send messages to this TCP port number
210
/// on the remote host or multicast group.
212
/// <exception cref="ArgumentOutOfRangeException">The value specified is less than <see cref="IPEndPoint.MinPort" /> or greater than <see cref="IPEndPoint.MaxPort" />.</exception>
213
public int RemotePort
215
get { return m_remotePort; }
218
if (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort)
220
throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value,
221
"The value specified is less than " +
222
IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) +
223
" or greater than " +
224
IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + ".");
228
m_remotePort = value;
234
/// Gets or sets the TCP port number from which the underlying <see cref="UdpClient" /> will communicate.
237
/// An integer value in the range <see cref="IPEndPoint.MinPort" /> to <see cref="IPEndPoint.MaxPort" />
238
/// indicating the TCP port number from which the underlying <see cref="UdpClient" /> will communicate.
242
/// The underlying <see cref="UdpClient" /> will bind to this port for sending messages.
245
/// Setting the value to 0 (the default) will cause the udp client not to bind to
249
/// <exception cref="ArgumentOutOfRangeException">The value specified is less than <see cref="IPEndPoint.MinPort" /> or greater than <see cref="IPEndPoint.MaxPort" />.</exception>
252
get { return m_localPort; }
255
if (value != 0 && (value < IPEndPoint.MinPort || value > IPEndPoint.MaxPort))
257
throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("value", (object)value,
258
"The value specified is less than " +
259
IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) +
260
" or greater than " +
261
IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + ".");
271
/// Gets or sets <see cref="Encoding"/> used to write the packets.
274
/// The <see cref="Encoding"/> used to write the packets.
278
/// The <see cref="Encoding"/> used to write the packets.
281
public Encoding Encoding
283
get { return m_encoding; }
284
set { m_encoding = value; }
287
#endregion Public Instance Properties
289
#region Protected Instance Properties
292
/// Gets or sets the underlying <see cref="UdpClient" />.
295
/// The underlying <see cref="UdpClient" />.
298
/// <see cref="UdpAppender" /> creates a <see cref="UdpClient" /> to send logging events
299
/// over a network. Classes deriving from <see cref="UdpAppender" /> can use this
300
/// property to get or set this <see cref="UdpClient" />. Use the underlying <see cref="UdpClient" />
301
/// returned from <see cref="Client" /> if you require access beyond that which
302
/// <see cref="UdpAppender" /> provides.
304
protected UdpClient Client
306
get { return this.m_client; }
307
set { this.m_client = value; }
311
/// Gets or sets the cached remote endpoint to which the logging events should be sent.
314
/// The cached remote endpoint to which the logging events will be sent.
317
/// The <see cref="ActivateOptions" /> method will initialize the remote endpoint
318
/// with the values of the <see cref="RemoteAddress" /> and <see cref="RemotePort"/>
321
protected IPEndPoint RemoteEndPoint
323
get { return this.m_remoteEndPoint; }
324
set { this.m_remoteEndPoint = value; }
327
#endregion Protected Instance Properties
329
#region Implementation of IOptionHandler
332
/// Initialize the appender based on the options set.
336
/// This is part of the <see cref="IOptionHandler"/> delayed object
337
/// activation scheme. The <see cref="ActivateOptions"/> method must
338
/// be called on this object after the configuration properties have
339
/// been set. Until <see cref="ActivateOptions"/> is called this
340
/// object is in an undefined state and must not be used.
343
/// If any of the configuration properties are modified then
344
/// <see cref="ActivateOptions"/> must be called again.
347
/// The appender will be ignored if no <see cref="RemoteAddress" /> was specified or
348
/// an invalid remote or local TCP port number was specified.
351
/// <exception cref="ArgumentNullException">The required property <see cref="RemoteAddress" /> was not specified.</exception>
352
/// <exception cref="ArgumentOutOfRangeException">The TCP port number assigned to <see cref="LocalPort" /> or <see cref="RemotePort" /> is less than <see cref="IPEndPoint.MinPort" /> or greater than <see cref="IPEndPoint.MaxPort" />.</exception>
353
public override void ActivateOptions()
355
base.ActivateOptions();
357
if (this.RemoteAddress == null)
359
throw new ArgumentNullException("The required property 'Address' was not specified.");
361
else if (this.RemotePort < IPEndPoint.MinPort || this.RemotePort > IPEndPoint.MaxPort)
363
throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.RemotePort", (object)this.RemotePort,
364
"The RemotePort is less than " +
365
IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) +
366
" or greater than " +
367
IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + ".");
369
else if (this.LocalPort != 0 && (this.LocalPort < IPEndPoint.MinPort || this.LocalPort > IPEndPoint.MaxPort))
371
throw log4net.Util.SystemInfo.CreateArgumentOutOfRangeException("this.LocalPort", (object)this.LocalPort,
372
"The LocalPort is less than " +
373
IPEndPoint.MinPort.ToString(NumberFormatInfo.InvariantInfo) +
374
" or greater than " +
375
IPEndPoint.MaxPort.ToString(NumberFormatInfo.InvariantInfo) + ".");
379
this.RemoteEndPoint = new IPEndPoint(this.RemoteAddress, this.RemotePort);
380
this.InitializeClientConnection();
386
#region Override implementation of AppenderSkeleton
389
/// This method is called by the <see cref="AppenderSkeleton.DoAppend(LoggingEvent)"/> method.
391
/// <param name="loggingEvent">The event to log.</param>
394
/// Sends the event using an UDP datagram.
397
/// Exceptions are passed to the <see cref="AppenderSkeleton.ErrorHandler"/>.
400
protected override void Append(LoggingEvent loggingEvent)
404
Byte [] buffer = m_encoding.GetBytes(RenderLoggingEvent(loggingEvent).ToCharArray());
405
this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
410
"Unable to send logging event to remote host " +
411
this.RemoteAddress.ToString() +
413
this.RemotePort + ".",
415
ErrorCode.WriteFailure);
420
/// This appender requires a <see cref="Layout"/> to be set.
422
/// <value><c>true</c></value>
425
/// This appender requires a <see cref="Layout"/> to be set.
428
override protected bool RequiresLayout
434
/// Closes the UDP connection and releases all resources associated with
435
/// this <see cref="UdpAppender" /> instance.
439
/// Disables the underlying <see cref="UdpClient" /> and releases all managed
440
/// and unmanaged resources associated with the <see cref="UdpAppender" />.
443
override protected void OnClose()
447
if (this.Client != null)
454
#endregion Override implementation of AppenderSkeleton
456
#region Protected Instance Methods
459
/// Initializes the underlying <see cref="UdpClient" /> connection.
463
/// The underlying <see cref="UdpClient"/> is initialized and binds to the
464
/// port number from which you intend to communicate.
467
/// Exceptions are passed to the <see cref="AppenderSkeleton.ErrorHandler"/>.
470
protected virtual void InitializeClientConnection()
474
if (this.LocalPort == 0)
476
this.Client = new UdpClient();
480
this.Client = new UdpClient(this.LocalPort);
486
"Could not initialize the UdpClient connection on port " +
487
this.LocalPort.ToString(NumberFormatInfo.InvariantInfo) + ".",
489
ErrorCode.GenericFailure);
495
#endregion Protected Instance Methods
497
#region Private Instance Fields
500
/// The IP address of the remote host or multicast group to which
501
/// the logging event will be sent.
503
private IPAddress m_remoteAddress;
506
/// The TCP port number of the remote host or multicast group to
507
/// which the logging event will be sent.
509
private int m_remotePort;
512
/// The cached remote endpoint to which the logging events will be sent.
514
private IPEndPoint m_remoteEndPoint;
517
/// The TCP port number from which the <see cref="UdpClient" /> will communicate.
519
private int m_localPort;
522
/// The <see cref="UdpClient" /> instance that will be used for sending the
525
private UdpClient m_client;
528
/// The encoding to use for the packet.
530
private Encoding m_encoding = Encoding.Default;
532
#endregion Private Instance Fields