Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using log4net;
- using TicketmasterSystems.Configuration;
- using TicketmasterSystems.Shared.SSETI.Internals;
- using System.Threading;
- namespace TicketmasterSystems.Shared.SSETI.Performance
- {
- public static class CounterNames
- {
- public const string CurrentConnections = "Current connections";
- public const string CurrentMessages = "Current messages";
- public const string CurrentTotalBaskets = "Current total baskets";
- public const string CurrentIdleBaskets = "Current idle baskets";
- public const string CurrentBusyBaskets = "Current busy baskets";
- public const string CurrentErroredBaskets = "Current errored baskets";
- public const string ConnectionsPerSecond = "# connections / second";
- public const string MessagesPerSecond = "# messages / second";
- public const string AverageMessageTime = "Average message duration";
- public const string AverageMessageTimeBase = "Average message duration base";
- }
- /// <summary>
- /// Stores, updates and supplies performance metrics for SSETI.NET by storing metrics internally within this instance.
- /// </summary>
- public static class SSETIPerformanceMonitor
- {
- private static ILog log = LogManager.GetLogger("PERFORMANCE");
- private static bool arecountersavailable = false;
- private static DateTime startupTime = DateTime.Now;
- private static Dictionary<string, MessagePerformanceTracker> perfitems = new Dictionary<string, MessagePerformanceTracker>();
- private static PerformanceCounter counterCurrentConnections = null;
- private static PerformanceCounter counterCurrentMessages = null;
- private static PerformanceCounter counterCurrentTotalBaskets = null;
- private static PerformanceCounter counterCurrentIdleBaskets = null;
- private static PerformanceCounter counterCurrentBusyBaskets = null;
- private static PerformanceCounter counterCurrentErroredBaskets = null;
- private static PerformanceCounter counterConnectionsPerSecond = null;
- private static PerformanceCounter counterMessagesPerSecond = null;
- private static PerformanceCounter counterAverageMessageTime = null;
- private static PerformanceCounter counterAverageMessageTimeBase = null;
- public const string CategoryName = "SSETI.NET";
- public static void Initialise()
- {
- // If we are running in mono, disable counters
- if(Config.IsMono)
- {
- log.Warn("PERFORMANCE: Performance counters are not available when running on Mono");
- return;
- }
- // Create the performance counters to track global information
- CreateCounters();
- // Register performance counters for use
- RegisterCounters();
- arecountersavailable = true;
- }
- static SSETIPerformanceMonitor()
- {
- // Reset the performance monitor when apply changes is run
- Config.Reset += new EventHandler<ConfigResetEventArgs>(Reset);
- }
- public static void Reset(object sender, EventArgs e)
- {
- // Add the performance items for each message type
- perfitems.Clear();
- foreach(Type t in MessageFactory.Current.AllMessageTypes) perfitems.Add(t.Name, new MessagePerformanceTracker(t.Name));
- }
- private static void CreateCounters()
- {
- log.InfoFormat("PERFORMANCE: Binding/creating performance counters");
- CounterCreationDataCollection counterdata = new CounterCreationDataCollection();
- counterdata.Add(new CounterCreationData(CounterNames.CurrentConnections, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.CurrentMessages, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.CurrentTotalBaskets, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.CurrentIdleBaskets, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.CurrentBusyBaskets, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.CurrentErroredBaskets, "", PerformanceCounterType.NumberOfItems32));
- counterdata.Add(new CounterCreationData(CounterNames.ConnectionsPerSecond, "", PerformanceCounterType.RateOfCountsPerSecond32));
- counterdata.Add(new CounterCreationData(CounterNames.MessagesPerSecond, "", PerformanceCounterType.RateOfCountsPerSecond32));
- counterdata.Add(new CounterCreationData(CounterNames.AverageMessageTime, "", PerformanceCounterType.AverageTimer32));
- counterdata.Add(new CounterCreationData(CounterNames.AverageMessageTimeBase, "", PerformanceCounterType.AverageBase));
- // Check if all of these already exist
- int countexist = 0;
- if(PerformanceCounterCategory.Exists(CategoryName))
- {
- foreach(CounterCreationData ccd in counterdata)
- {
- if(PerformanceCounterCategory.CounterExists(ccd.CounterName, CategoryName)) countexist++;
- }
- }
- // If some of the counters didnt exist, delete the category and recreate
- if(countexist != counterdata.Count)
- {
- if(PerformanceCounterCategory.Exists(CategoryName)) PerformanceCounterCategory.Delete(CategoryName);
- PerformanceCounterCategory.Create(CategoryName, "", PerformanceCounterCategoryType.MultiInstance, counterdata);
- log.InfoFormat("PERFORMANCE: Successfully created performance counters: Count = {0}", counterdata.Count);
- }
- else
- {
- log.InfoFormat("PERFORMANCE: Existing performance counters found: Count = {0}", countexist);
- }
- }
- private static void RegisterCounters()
- {
- counterCurrentConnections = new PerformanceCounter(CategoryName, CounterNames.CurrentConnections, Config.ServiceName, false);
- counterCurrentMessages = new PerformanceCounter(CategoryName, CounterNames.CurrentMessages, Config.ServiceName, false);
- counterCurrentTotalBaskets = new PerformanceCounter(CategoryName, CounterNames.CurrentTotalBaskets, Config.ServiceName, false);
- counterCurrentIdleBaskets = new PerformanceCounter(CategoryName, CounterNames.CurrentIdleBaskets, Config.ServiceName, false);
- counterCurrentBusyBaskets = new PerformanceCounter(CategoryName, CounterNames.CurrentBusyBaskets, Config.ServiceName, false);
- counterCurrentErroredBaskets = new PerformanceCounter(CategoryName, CounterNames.CurrentErroredBaskets, Config.ServiceName, false);
- counterConnectionsPerSecond = new PerformanceCounter(CategoryName, CounterNames.ConnectionsPerSecond, Config.ServiceName, false);
- counterMessagesPerSecond = new PerformanceCounter(CategoryName, CounterNames.MessagesPerSecond, Config.ServiceName, false);
- counterAverageMessageTime = new PerformanceCounter(CategoryName, CounterNames.AverageMessageTime, Config.ServiceName, false);
- counterAverageMessageTimeBase = new PerformanceCounter(CategoryName, CounterNames.AverageMessageTimeBase, Config.ServiceName, false);
- // Retrieve basket counts
- int openbaskets, idlebaskets, busybaskets, completedbaskets, erroredbaskets;
- Baskets.GetBasketCounts(out openbaskets, out idlebaskets, out busybaskets, out completedbaskets, out erroredbaskets);
- counterCurrentConnections.RawValue = 0;
- counterCurrentMessages.RawValue = 0;
- counterCurrentTotalBaskets.RawValue = openbaskets;
- counterCurrentIdleBaskets.RawValue = idlebaskets;
- counterCurrentBusyBaskets.RawValue = busybaskets;
- counterCurrentErroredBaskets.RawValue = erroredbaskets;
- counterConnectionsPerSecond.RawValue = 0;
- counterMessagesPerSecond.RawValue = 0;
- counterAverageMessageTime.RawValue = 0;
- counterAverageMessageTimeBase.RawValue = 0;
- }
- #region Performance Events
- public static void NewConnection(SessionState state)
- {
- try
- {
- state.ConnectionTimer = new Stopwatch();
- state.ConnectionTimer.Start();
- counterCurrentConnections.Increment();
- counterConnectionsPerSecond.Increment();
- }
- catch(Exception) { }
- }
- /// <summary>
- /// Should be called when a new message is received and before any processing is done.
- /// </summary>
- public static void NewMessage(SessionState state)
- {
- try
- {
- state.Timer = new Stopwatch();
- state.Timer.Start();
- counterCurrentMessages.Increment();
- }
- catch(Exception) { }
- }
- /// <summary>
- /// Should be called after the response to a message has been transmitted.
- /// </summary>
- /// <param name="state"></param>
- public static void CloseMessage(SessionState state)
- {
- try
- {
- if(state != null && state.Timer != null)
- {
- state.Timer.Stop();
- if(state.Message != null)
- {
- perfitems[state.Message.GetType().Name].UpdateWithTimer(1, state.Timer.ElapsedMilliseconds / 1000d);
- counterAverageMessageTime.IncrementBy(state.Timer.ElapsedTicks);
- counterAverageMessageTimeBase.Increment();
- }
- }
- counterCurrentMessages.Decrement();
- counterMessagesPerSecond.Increment(); // Messages / sec is only updated upon message completion
- }
- catch(Exception) { }
- }
- public static void CloseConnection(SessionState state)
- {
- try
- {
- if(state.ConnectionTimer != null) state.ConnectionTimer.Stop();
- counterCurrentConnections.Decrement();
- }
- catch(Exception) { }
- }
- /// <summary>
- /// Should be called when a new user session (a basket) is created.
- /// </summary>
- public static void NewBasket()
- {
- try
- {
- counterCurrentTotalBaskets.Increment();
- counterCurrentIdleBaskets.Increment();
- }
- catch(Exception) { }
- }
- /// <summary>
- /// Should be called when a user session (a basket) is destroyed.
- /// </summary>
- public static void DeleteBasket()
- {
- try
- {
- counterCurrentTotalBaskets.Decrement();
- counterCurrentIdleBaskets.Decrement();
- }
- catch(Exception) { }
- }
- #endregion
- #region Statistics
- public static long CurrentNumberConnections
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentConnections.RawValue;
- }
- }
- public static long CurrentNumberMessages
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentMessages.RawValue;
- }
- }
- public static long CurrentNumberMessagesPerSecond
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterMessagesPerSecond.RawValue;
- }
- }
- public static long CurrentTotalBaskets
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentTotalBaskets.RawValue;
- }
- set
- {
- if(!arecountersavailable) return;
- counterCurrentTotalBaskets.RawValue = value;
- }
- }
- public static long CurrentIdleBaskets
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentIdleBaskets.RawValue;
- }
- set
- {
- if(!arecountersavailable) return;
- counterCurrentIdleBaskets.RawValue = value;
- }
- }
- public static long CurrentBusyBaskets
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentBusyBaskets.RawValue;
- }
- set
- {
- if(!arecountersavailable) return;
- counterCurrentBusyBaskets.RawValue = value;
- }
- }
- public static long CurrentErroredBaskets
- {
- get
- {
- if(!arecountersavailable) return 0;
- return counterCurrentErroredBaskets.RawValue;
- }
- set
- {
- if(!arecountersavailable) return;
- counterCurrentErroredBaskets.RawValue = value;
- }
- }
- public static long TotalNumberMessages
- {
- get
- {
- long tot = 0;
- foreach(KeyValuePair<string, MessagePerformanceTracker> pi in perfitems)
- {
- if(!pi.Value.Name.StartsWith(":")) tot += pi.Value.Count;
- }
- return tot;
- }
- }
- public static DateTime StartupTime
- {
- get { return startupTime; }
- }
- public static Dictionary<string, MessagePerformanceTracker> MessageStatistics
- {
- get { return perfitems; }
- }
- #endregion
- /// <summary>
- /// Dumps a list of SSETI messages and their runtime statistics.
- /// </summary>
- public static void DumpMessageStats()
- {
- log.DebugFormat("DUMPING MESSAGE STATISTICS");
- log.DebugFormat("(timings indicate only message processing - no network latency, deferred message pre-execution timings listed here only)");
- int count = 0;
- foreach(KeyValuePair<string, MessagePerformanceTracker> mt in SSETIPerformanceMonitor.MessageStatistics)
- {
- if(mt.Value.Count == 0) continue;
- log.InfoFormat("{0} : {1}", mt.Key.PadRight(30).Substring(0, 30), mt.Value.ToString());
- count++;
- }
- if(count == 0) log.Info("- no message statistics logged yet -");
- log.Debug("END");
- }
- }
- }
Add Comment
Please, Sign In to add comment