aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Logging/Controls/TimelineScrollViewer.cs
blob: dd1227a06dcaf38cb4b2a3e085c5157f3c03a46c (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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;

namespace Tango.MachineStudio.Logging.Controls
{
    public class TimelineScrollViewer : ScrollViewer
    {
        public event EventHandler<MouseWheelEventArgs> MouseZooming;

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftCtrl))
            {
                e.Handled = true;
                OnMouseZooming(e);
            }
            else
            {
                base.OnMouseWheel(e);
            }

            e.Handled = false;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyboardDevice.Modifiers == ModifierKeys.Control)
            {
                if (e.Key == Key.Left || e.Key == Key.Right)
                    e.Handled = true;
                return;
            }
            base.OnKeyDown(e);
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            e.Handled = true;
        }

        protected virtual void OnMouseZooming(MouseWheelEventArgs e)
        {
            if (MouseZooming != null) MouseZooming(this, e);
        }
    }
}
ght .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
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.Logging;
using Tango.MachineStudio.Common.Authentication;
using Tango.MachineStudio.Common.Diagnostics;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.PMR.Diagnostics;
using Tango.Integration.Operation;

namespace Tango.MachineStudio.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 IStudioApplicationManager _application;
        private IAuthenticationProvider _authentication;
        private Dictionary<EventTypes, BL.Entities.EventType> _eventTypesGuids;
        private String _hostName;
        private bool _isInitialized;
        private List<MachinesEvent> _pendingEvents;

        #region Events

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

        #endregion

        #region Constructors

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

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

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

            _application = applicationManager;
            _authentication = authenticationProvider;
            _logThread = new Thread(LogThreadMethod);
            _logThread.IsBackground = true;
            _logThread.Start();

            _application.ConnectedMachineChanged += _application_ConnectedMachineChanged;
        }

        #endregion

        #region Private Methods

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

                    _db.ActionTypes.ToList();
                    _db.EventTypesActions.ToList();
                    _db.EventTypesCategories.ToList();
                    _db.EventTypesGroups.ToList();
                    _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>
        /// Handle the application manager connected machine changed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="machine">The machine.</param>
        private void _application_ConnectedMachineChanged(object sender, IExternalBridgeClient machine)
        {
            if (machine != null)
            {
                if (machine.MachineEventsStateProvider != null)
                {
                    machine.MachineEventsStateProvider.NewEvents -= MachineEventsStateProvider_NewEvents;
                    machine.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
                    machine.MachineEventsStateProvider.EventsResolved -= MachineEventsStateProvider_EventsResolved;
                    machine.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;
                }

                machine.RequestSent -= Machine_RequestSent;
                machine.RequestFailed -= Machine_RequestFailed;
                machine.ResponseReceived -= Machine_ResponseReceived;

                machine.RequestSent += Machine_RequestSent;
                machine.RequestFailed += Machine_RequestFailed;
                machine.ResponseReceived += Machine_ResponseReceived;
            }
        }

        /// <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.RequestSent, 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.RequestFailed, 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.ResponseReceived, 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));
            }
        }

        #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 (_application.ConnectedMachine == null || _authentication.CurrentUser == null)
            {
                _pendingEvents.Add(machineEvent);
            }
            else
            {
                lock (_pendingEvents)
                {
                    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.Description);
                machineEvent.MachineGuid = _application.Machine.Guid;
                machineEvent.UserGuid = _authentication.CurrentUser.Guid;
                machineEvent.User = _authentication.CurrentUser;
                _events.Enqueue(machineEvent);
                NewLog?.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, bool write_to_db = true)
        {
            Init();

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

            if (write_to_db)
            {
                Log(machineEvent);
            }
            else
            {
                NewLog?.Invoke(this, 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.ApplicationException, exception.ToString());
        }

        /// <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.ApplicationException, description + Environment.NewLine + exception.ToString());
        }

        /// <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.ApplicationInformation, 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
    }
}