//----------------------------------------------------------------------------- // // Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). // You may not use this file except in compliance with the License. // A copy of the License is located at // // http://aws.amazon.com/apache2.0 // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. // //----------------------------------------------------------------------------- using System; using System.Net; using System.Net.Sockets; using System.Text; using Amazon.Runtime.Internal.Util; using Amazon.XRay.Recorder.Core.Internal.Entities; using Amazon.XRay.Recorder.Core.Internal.Utils; using System.Threading.Tasks; using EndPoint = Amazon.XRay.Recorder.Core.Internal.Utils.EndPoint; namespace Amazon.XRay.Recorder.Core.Internal.Emitters { /// /// Send the segment to daemon /// public class UdpSegmentEmitter : ISegmentEmitter { private static readonly Logger _logger = Logger.GetLogger(typeof(UdpSegmentEmitter)); private readonly IPAddress _defaultDaemonAddress = IPAddress.Loopback; private readonly ISegmentMarshaller _marshaller; private readonly UdpClient _udpClient; private DaemonConfig _daemonConfig; private bool _disposed; /// /// Initializes a new instance of the class. /// public UdpSegmentEmitter() : this(new JsonSegmentMarshaller()) { } private UdpSegmentEmitter(ISegmentMarshaller marshaller) { _marshaller = marshaller; _udpClient = new UdpClient(); _daemonConfig = DaemonConfig.GetEndPoint(); } /// /// Gets the end point to daemon. /// /// Two successive calls may not return the same IP as the backing /// endpoint may be a HostEndpoint that could update. /// /// public IPEndPoint EndPoint => _daemonConfig.UDPEndpoint; /// /// Send segment to local daemon /// /// The segment to be sent public void Send(Entity segment) { try { var packet = _marshaller.Marshall(segment); var data = Encoding.ASCII.GetBytes(packet); var ip = EndPoint; //Need local var to ensure ip do not updates _logger.DebugFormat("UDP Segment emitter endpoint: {0}.", ip); _udpClient.Send(data, data.Length, ip); } catch (SocketException e) { _logger.Error(e, "Failed to send package through socket."); } catch (ArgumentNullException e) { _logger.Error(e, "The udp data gram is null."); } catch (ObjectDisposedException e) { _logger.Error(e, "The udp client is already closed."); } catch (InvalidOperationException e) { _logger.Error(e, "The udp client connection is invalid."); } } /// /// Sets the daemon address. /// The daemon address should be in format "IPAddress:Port", i.e. "127.0.0.1:2000" /// /// The daemon address. public void SetDaemonAddress(string daemonAddress) { if (Environment.GetEnvironmentVariable(DaemonConfig.EnvironmentVariableDaemonAddress) == null) { SetEndPointOrDefault(daemonAddress); } else { _logger.InfoFormat("Ignoring call to SetDaemonAddress as " + DaemonConfig.EnvironmentVariableDaemonAddress + " is set."); } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_disposed) { return; } if (disposing) { if (_udpClient != null) { #if NET45 _udpClient.Close(); #else _udpClient.Dispose(); #endif } _disposed = true; } } private void SetEndPointOrDefault(string daemonAddress) { _daemonConfig = DaemonConfig.GetEndPoint(daemonAddress); } } }