//----------------------------------------------------------------------------- // <copyright file="UdpSegmentEmitter.cs" company="Amazon.com"> // 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. // </copyright> //----------------------------------------------------------------------------- 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 { /// <summary> /// Send the segment to daemon /// </summary> 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; /// <summary> /// Initializes a new instance of the <see cref="UdpSegmentEmitter"/> class. /// </summary> public UdpSegmentEmitter() : this(new JsonSegmentMarshaller()) { } private UdpSegmentEmitter(ISegmentMarshaller marshaller) { _marshaller = marshaller; _udpClient = new UdpClient(); _daemonConfig = DaemonConfig.GetEndPoint(); } /// <summary> /// Gets the end point to daemon. /// <para> /// Two successive calls may not return the same IP as the backing /// endpoint may be a HostEndpoint that could update. /// </para> /// </summary> public IPEndPoint EndPoint => _daemonConfig.UDPEndpoint; /// <summary> /// Send segment to local daemon /// </summary> /// <param name="segment">The segment to be sent</param> 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."); } } /// <summary> /// Sets the daemon address. /// The daemon address should be in format "IPAddress:Port", i.e. "127.0.0.1:2000" /// </summary> /// <param name="daemonAddress">The daemon address.</param> 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."); } } /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> 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); } } }