aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/EventsViews/JobEventView.xaml.cs
blob: 89faa3a850cfeef35bb3272c86ef9a2662d4c4c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Tango.PPC.Events.EventsViews
{
    /// <summary>
    /// Interaction logic for JobEventView.xaml
    /// </summary>
    public partial class JobEventView : UserControl
    {
        public JobEventView()
        {
            InitializeComponent();
        }
    }
}
using Google.Protobuf;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Integration.ExternalBridge;
using Tango.PMR.Diagnostics;
using Tango.Integration.Operation;
using Tango.PPC.Common.Application;
using Tango.PPC.Common.Authentication;
using Tango.PPC.Common.Connection;
using Tango.Transport;

namespace Tango.PPC.Common.EventLogging
{
    /// <summary>
    /// Represents the default database events logger.
    /// </summary>
    /// <seealso cref="IEventLogger" />
    public class DefaultEventLogger : ExtendedObject, IEventLogger
    {
        private ObservablesContext _db;
        private Thread _logThread;
        private ConcurrentQueue<MachinesEvent> _events;
        private IMachineProvider _machineProvider;
        private IAuthenticationProvider _authentication;
        private Dictionary<EventTypes, BL.Entities.EventType> _eventTypesGuids;
        private String _hostName;
        private bool _isInitialized;
        private List<MachinesEvent> _pendingEvents;
        private List<MachinesEvent> _currentEvents;

        #region Events

        /// <summary>
        /// Occurs when a new machine event has been received.
        /// </summary>
        public event EventHandler<MachinesEvent> EventReceived;

        /// <summary>
        /// Occurs when a machine event has been resolved.
        /// </summary>
        public event EventHandler<MachinesEvent> EventResolved;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultEventLogger"/> class.
        /// </summary>
        /// <param name="machineProvider">The application manager.</param>
        /// <param name="authenticationProvider">The authentication provider.</param>
        public DefaultEventLogger(IMachineProvider machineProvider, IAuthenticationProvider authenticationProvider)
        {
            _hostName = Environment.MachineName;

            _events = new ConcurrentQueue<MachinesEvent>();
            _pendingEvents = new List<MachinesEvent>();
            _currentEvents = new List<MachinesEvent>();

            _eventTypesGuids = new Dictionary<EventTypes, BL.Entities.EventType>();

            _machineProvider = machineProvider;
            _authentication = authenticationProvider;
            _logThread = new Thread(LogThreadMethod);
            _logThread.IsBackground = true;
            _logThread.Start();

            _machineProvider.MachineOperator.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
            _machineProvider.MachineOperator.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;

            _machineProvider.MachineOperator.RequestSent += Machine_RequestSent;
            _machineProvider.MachineOperator.RequestFailed += Machine_RequestFailed;
            _machineProvider.MachineOperator.ResponseReceived += Machine_ResponseReceived;
            _machineProvider.MachineOperator.StateChanged += MachineOperator_StateChanged;
            _machineProvider.MachineOperator.PrintingStarted += MachineOperator_PrintingStarted;
            _machineProvider.MachineOperator.PrintingAborted += MachineOperator_PrintingAborted;
            _machineProvider.MachineOperator.PrintingCompleted += MachineOperator_PrintingCompleted;
            _machineProvider.MachineOperator.PrintingFailed += MachineOperator_PrintingFailed;

        }

        #endregion

        #region Private Methods

        private void Init()
        {
            if (!_isInitialized)
            {
                try
                {
                    _db = ObservablesContext.CreateDefault();

                    _db.EventTypes.ToList();

                    foreach (var type in _db.EventTypes)
                    {
                        _eventTypesGuids.Add((EventTypes)type.Code, type);
                    }

                    _isInitialized = true;
                }
                catch
                {
                    _isInitialized = false;
                }
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the PrintingFailed event of the MachineOperator.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PrintingFailedEventArgs"/> instance containing the event data.</param>
        private void MachineOperator_PrintingFailed(object sender, PrintingFailedEventArgs e)
        {
            Log(EventTypes.JOB_FAILED, e.Exception.Message);
        }

        /// <summary>
        /// Handles the PrintingCompleted event of the MachineOperator.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PrintingEventArgs"/> instance containing the event data.</param>
        private void MachineOperator_PrintingCompleted(object sender, PrintingEventArgs e)
        {
            Log(EventTypes.JOB_COMPLETED, $"Job '{e.Job.Name}' completed successfully.");
        }

        /// <summary>
        /// Handles the PrintingAborted event of the MachineOperator.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PrintingEventArgs"/> instance containing the event data.</param>
        private void MachineOperator_PrintingAborted(object sender, PrintingEventArgs e)
        {
            Log(EventTypes.JOB_ABORTED, $"Job '{e.Job.Name}' has been aborted.");
        }

        /// <summary>
        /// Handles the PrintingStarted event of the MachineOperator.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PrintingEventArgs"/> instance containing the event data.</param>
        private void MachineOperator_PrintingStarted(object sender, PrintingEventArgs e)
        {
            Log(EventTypes.JOB_STARTED, $"Job '{e.Job.Name}' started.");
        }

        /// <summary>
        /// Handles the machine operator state changed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        private void MachineOperator_StateChanged(object sender, Transport.TransportComponentState e)
        {
            if (e == Transport.TransportComponentState.Connected)
            {
                _events = new ConcurrentQueue<MachinesEvent>();
                _currentEvents.Clear();
            }
        }

        /// <summary>
        /// Handles the RequestSent event of the connected machine.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="message">The message.</param>
        private void Machine_RequestSent(object sender, IMessage message)
        {
            //Log(EventTypes.REQUEST_SENT, String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
        }

        /// <summary>
        /// Handles the RequestFailed event of the connected machine.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RequestFailedEventArgs"/> instance containing the event data.</param>
        private void Machine_RequestFailed(object sender, RequestFailedEventArgs e)
        {
            //Log(EventTypes.REQUEST_FAILED, String.Format("Request failed '{0}'...{1}{2}{1}{3}", e.Message.GetType().Name, Environment.NewLine, e.Message.ToJsonString(), e.Exception.ToString()));
        }

        /// <summary>
        /// Handles the ResponseReceived event of the connected machine.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="message">The message.</param>
        private void Machine_ResponseReceived(object sender, IMessage message)
        {
            //Log(EventTypes.RESPONSE_RECEIVED, String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
        }

        /// <summary>
        /// Handles the connected machine events state provider NewEvents event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="events">The events.</param>
        private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable<MachinesEvent> events)
        {
            foreach (var ev in events)
            {
                Log(ev);
            }
        }

        /// <summary>
        /// Handles the connected machine events state provider EventsResolved event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="events">The events.</param>
        private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> events)
        {
            foreach (var ev in events)
            {
                //Log(String.Format("Event '{0}' resolved.", ev.EventType.Name));

                var existing = _currentEvents.SingleOrDefault(x => x.Type == ev.Type);

                if (existing != null)
                {
                    _currentEvents.Remove(existing);
                    EventResolved?.Invoke(this, existing);
                }
            }
        }

        #endregion

        #region Logging

        /// <summary>
        /// Logs the specified machine event.
        /// </summary>
        /// <param name="machineEvent">The machine event.</param>
        public void Log(MachinesEvent machineEvent)
        {
            machineEvent.HostName = _hostName;
            machineEvent.EventType = _eventTypesGuids[machineEvent.Type];

            if (_machineProvider.Machine == null || _authentication.CurrentUser == null)
            {
                _pendingEvents.Add(machineEvent);
            }
            else
            {
                if (_pendingEvents.Count > 0)
                {
                    var pending = _pendingEvents.ToList();
                    _pendingEvents.Clear();

                    foreach (var ev in pending)
                    {
                        Log(ev);
                    }
                }

                LogManager.Log("Logging event " + machineEvent.EventType.Name);
                machineEvent.MachineGuid = _machineProvider.Machine.Guid;
                machineEvent.UserGuid = _authentication.CurrentUser.Guid;
                machineEvent.User = _authentication.CurrentUser;
                _events.Enqueue(machineEvent);

                if (!_currentEvents.Exists(x => x.Type == machineEvent.Type))
                {
                    if (machineEvent.Group != EventTypeGroups.Application && machineEvent.Group != EventTypeGroups.Transport)
                    {
                        _currentEvents.Add(machineEvent);
                    }
                }

                EventReceived?.Invoke(this, machineEvent);
            }
        }

        /// <summary>
        /// Logs the specified event type.
        /// </summary>
        /// <param name="eventType">Type of the event.</param>
        /// <param name="message">The message.</param>
        public void Log(EventTypes eventType, string message)
        {
            Init();

            MachinesEvent machineEvent = new MachinesEvent();
            machineEvent.DateTime = DateTime.UtcNow;
            machineEvent.Description = message;
            machineEvent.EventType = _eventTypesGuids[eventType];
            machineEvent.EventTypeGuid = machineEvent.EventType.Guid;

            Log(machineEvent);
        }

        /// <summary>
        /// Logs the specified hardware event.
        /// </summary>
        /// <param name="hardwareEvent">The hardware event.</param>
        public void Log(Event hardwareEvent)
        {
            Log((EventTypes)hardwareEvent.Type, hardwareEvent.Message);
        }

        /// <summary>
        /// Logs the specified exception using the <see cref="EventTypes.ApplicationException"/>.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public void Log(Exception exception)
        {
            Log(EventTypes.APPLICATION_EXCEPTION, exception.FlattenMessage());
        }

        /// <summary>
        /// Logs the specified exception using the <see cref="EventTypes.ApplicationException" />.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="description"></param>
        public void Log(Exception exception, string description)
        {
            Log(EventTypes.APPLICATION_EXCEPTION, description + Environment.NewLine + exception.FlattenMessage());
        }

        /// <summary>
        /// Logs the specified message using the <see cref="EventTypes.ApplicationInformation"/>.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Log(String message)
        {
            Log(EventTypes.APPLICATION_INFORMATION, message);
        }

        /// <summary>
        /// Logging thread loop.
        /// </summary>
        private void LogThreadMethod()
        {
            while (true)
            {
                FlushAll();
                Thread.Sleep(5000);
            }
        }

        /// <summary>
        /// Immediately saves all pending events to database.
        /// </summary>
        public void FlushAll()
        {
            bool _saveChanges = false;

            while (_events.Count > 0)
            {
                MachinesEvent ev = null;

                if (_events.TryDequeue(out ev))
                {
                    ev.User = null;
                    _db.MachinesEvents.Add(ev);
                    _saveChanges = true;
                }
            }

            if (_saveChanges)
            {
                try
                {
                    _db.SaveChanges();
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "Error saving machine event to database.");
                }
            }
        }

        #endregion
    }
}