/// <summary>Registers all event metric definitions defined by attributes on the provided object or Type, /// and registers metric instances where EventMetricInstanceName attribute is also found (with a live object).</summary> /// <param name="metricData">An object or Type defining event metrics via attributes on itself or on its base types or interfaces.</param> /// <remarks> /// <para> /// This call ensures that the reflection scan of all members looking for /// attributes across the entire inheritance of an object instance or Type has been /// done (e.g. outside of a critical path) so that the first call to <see cref="Write(object)">Write</see> will not have to do that work within a critical path. /// Results are cached internally, so redundant calls to this method will not /// repeat the scan for types already scanned (including as part of a different /// top-level type). /// </para> /// <para> /// If a live object is given (not just a Type) then the member(s) decorated with /// an <see cref="EventMetricInstanceNameAttribute">EventMetricInstanceNameAttribute Class</see> /// will be queried and used to also register an event metric instance with the /// returned name /// </para> /// <para>If a Type is given instead of a live object, it can't be queried for instance /// name(s) and will only register the event metric definitions. Metric instances will /// still be created automatically as needed when Write is called.</para> /// </remarks> /// <seealso cref="Write(object)">Write Method</seealso> /// <exception caption="" cref="ArgumentNullException">Thrown if metricData is null.</exception> /// <exception caption="" cref="ArgumentException">The specified metricDataObjectType does not have an EventMetric attribute <br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type does not have a usable EventMetric attribute, so it can't be used to define an event metric.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric namespace which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric category name which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric has an empty metric counter name which is not allowed, so no metric can be defined.<br /> /// <br /> /// -or- <br /> /// <br /> /// The specified Type's EventMetric attribute's 3-part Key is already used for a metric definition which is not an event metric.</exception> /// <example> /// See the <see cref="EventMetric">EventMetric Class Overview</see> for an example. /// <code title="" description="" lang="neutral"></code></example> public static void Register(object metricData) { //we need a live object, not a null object or we'll fail if (metricData == null) { throw new ArgumentNullException(nameof(metricData)); } // Register all of the event metric definitions it contains, object or Type: EventMetricDefinition[] definitions = EventMetricDefinition.RegisterAll(metricData); if ((metricData is Type) == false) { // They gave us a live object, not just a Type, so see if there are metric instances we can register. foreach (EventMetricDefinition definition in definitions) { if (definition.IsBound && definition.NameBound) { string instanceName = definition.InvokeInstanceNameBinding(metricData); if (instanceName != null) // null means it didn't find one, so we won't register an instance. { // An empty string (meaning the found value was null or empty) will be registered (same as null). Register(definition, instanceName); } } } } }
public void RecordEventMetricReflection() { UserEventObject myDataObject = new UserEventObject(null); EventMetric.Register(myDataObject); EventMetricDefinition metricDefinition; Assert.IsTrue(EventMetricDefinition.TryGetValue(typeof(UserEventObject), out metricDefinition)); EventMetricDefinition.Write(myDataObject); // Now try it with inheritance and interfaces in the mix. UserMultipleEventObject bigDataObject = new UserMultipleEventObject(null); EventMetric.Register(bigDataObject); // There's no event at the top level, so this lookup should fail. Assert.IsFalse(EventMetricDefinition.TryGetValue(typeof(UserMultipleEventObject), out metricDefinition)); // Now check for interfaces... Assert.IsTrue(EventMetricDefinition.TryGetValue(typeof(IEventMetricOne), out metricDefinition)); Assert.IsTrue(EventMetricDefinition.TryGetValue(typeof(IEventMetricTwo), out metricDefinition)); Assert.IsTrue(EventMetricDefinition.TryGetValue(typeof(IEventMetricThree), out metricDefinition)); Assert.IsTrue(EventMetricDefinition.TryGetValue(typeof(IEventMetricFour), out metricDefinition)); // And sample all of them on the big object with a single call... EventMetric.Write(bigDataObject); }
internal IMetricDefinition Externalize(Loupe.Extensibility.Data.IMetricDefinition metricDefinition) { if (metricDefinition == null) { return(null); } lock (Lock) { IMetricDefinition externalDefinition; if (m_Externalized.TryGetValue(metricDefinition, out externalDefinition) == false) { Monitor.EventMetricDefinition eventDefinition = metricDefinition as Monitor.EventMetricDefinition; Monitor.CustomSampledMetricDefinition customDefinition = metricDefinition as Monitor.CustomSampledMetricDefinition; if (eventDefinition != null) { externalDefinition = new EventMetricDefinition(eventDefinition); } else if (customDefinition != null) { externalDefinition = new SampledMetricDefinition(customDefinition); } else { throw new NotSupportedException(string.Format("Unable to wrap metric definition type: {0}", metricDefinition.GetType().Name)); } m_Externalized[metricDefinition] = externalDefinition; } return(externalDefinition); } }
private void SynchronizedMetricRegistration() { string name = Thread.CurrentThread.Name; Trace.TraceInformation("{0} started", name); EventMetricDefinition newDefinition = new EventMetricDefinition("EventMetricTests", "Gibraltar.Monitor.Test", "Sync"); newDefinition.AddValue("delta", typeof(double), SummaryFunction.RunningSum, null, "Delta", "The applied delta"); try { Interlocked.Increment(ref m_ThreadCounter); lock (m_SyncLock) { // Do nothing, just release it immediately. } EventMetricDefinition.Register(ref newDefinition); EventMetric metric = EventMetric.Register(newDefinition, name); Trace.TraceInformation("{0} completed registration of event metric", name); EventMetricSample sample = metric.CreateSample(); sample.SetValue("delta", Thread.CurrentThread.ManagedThreadId); sample.Write(); } catch (Exception ex) { m_ThreadFailed = true; Trace.TraceError("{0} got {1}: {2}", name, ex.GetType().Name, ex.Message, ex); } Interlocked.Decrement(ref m_ThreadCounter); }
/// <summary> /// Record an event metric using a programmatic declaration /// </summary> /// <param name="pagesLoaded"></param> public static void RecordCacheMetric(int pagesLoaded) { EventMetricDefinition cacheMetric; //so we can be called multiple times we want to see if the definition already exists. if (EventMetricDefinition.TryGetValue("GibraltarSample", "Database.Engine", "Cache", out cacheMetric) == false) { cacheMetric = new EventMetricDefinition("GibraltarSample", "Database.Engine", "Cache"); //add the values (that are part of the definition) cacheMetric.AddValue("pages", typeof(int), SummaryFunction.Average, "Pages", "Pages in Cache", "Total number of pages in cache"); cacheMetric.AddValue("size", typeof(int), SummaryFunction.Average, "Bytes", "Cache Size", "Total number of bytes used by pages in cache"); //and now that we're done, we need to register this definition. This locks the definition //and makes it go live. Note that it's based by ref because if another thread registered the same metric, we'll get the //registered object (whoever one the race), not necessarily the one we've just created to pass in. EventMetricDefinition.Register(ref cacheMetric); } //Now we can get the specific metric we want to record samples under (this is an instance of the definition) EventMetric cacheEventMetric = EventMetric.Register(cacheMetric, null); //now go ahead and write that sample. EventMetricSample newSample = cacheEventMetric.CreateSample(); newSample.SetValue("pages", pagesLoaded); newSample.SetValue("size", pagesLoaded * 8196); newSample.Write(); }
public void EventMetricsByMethodsPerformanceTest() { EventMetricDefinition eventDefinition; if (false == EventMetricDefinition.TryGetValue("PerformanceTestsMetrics", "Performance.EventMetrics.Methods", "UserEvent", out eventDefinition)) { eventDefinition = new EventMetricDefinition("PerformanceTestsMetrics", "Performance.EventMetrics.Methods", "UserEvent"); eventDefinition.Caption = "User Event"; eventDefinition.Description = "Unit test event metric with typical data."; eventDefinition.AddValue("fileName", typeof(string), SummaryFunction.Count, null, "File name", "The name of the file"); eventDefinition.AddValue("operation", typeof(UserFileOperation), SummaryFunction.Count, null, "Operation", "The type of file operation being performed."); eventDefinition.AddValue("duration", typeof(TimeSpan), SummaryFunction.Average, "ms", "Duration", "The duration for this file operation."); EventMetricDefinition.Register(ref eventDefinition, "duration"); } Assert.IsNotNull(eventDefinition); Assert.IsTrue(eventDefinition.IsReadOnly); Trace.TraceInformation("Event metric definition registered by methods."); EventMetric eventMetric = EventMetric.Register(eventDefinition, "MethodsPerformanceTest"); Assert.IsNotNull(eventMetric); string fileName = @"C:\Dummy\File\Name.txt"; DateTimeOffset operationStart = DateTimeOffset.UtcNow; DateTimeOffset operationEnd = operationStart.AddMilliseconds(1234); //first, lets get everything to flush so we have our best initial state. Log.Information(LogWriteMode.WaitForCommit, "Test.Agent.Metrics.Performance", "Preparing for Test", "Flushing queue"); //now that we know it's flushed everything, lets do our timed loop. DateTimeOffset startTime = DateTimeOffset.UtcNow; for (int curMessage = 0; curMessage < LoopsPerEventTest; curMessage++) { EventMetricSample eventSample = eventMetric.CreateSample(); eventSample.SetValue("fileName", fileName); eventSample.SetValue("operation", UserFileOperation.Write); eventSample.SetValue("duration", operationEnd - operationStart); eventSample.Write(); } DateTimeOffset messageEndTime = DateTimeOffset.UtcNow; //one wait for commit message to force the buffer to flush. Log.Information(LogWriteMode.WaitForCommit, "Test.Agent.Metrics.Performance", "Waiting for Samples to Commit", null); //and store off our time DateTimeOffset endTime = DateTimeOffset.UtcNow; TimeSpan testDuration = endTime - startTime; TimeSpan loopDuration = messageEndTime - startTime; const int messagesPerTest = LoopsPerEventTest * MessagesPerEventLoop; Trace.TraceInformation("Event Metrics by Methods Test committed {0:N0} events in {1:F3} ms (average {2:F4} ms per message). Average loop time {3:F4} ms ({4} values per message) and final flush time {5:F3} ms.", messagesPerTest, testDuration.TotalMilliseconds, (testDuration.TotalMilliseconds / messagesPerTest), (loopDuration.TotalMilliseconds / LoopsPerEventTest), ValuesPerEventMessage, (endTime - messageEndTime).TotalMilliseconds); }
private void StopAndRecordMetric() { //record our end time if (m_Timer == null) { m_Duration = new TimeSpan(0); } else { m_Timer.Stop(); m_Duration = m_Timer.Elapsed; } //Get the METRIC DEFINITION IMetricDefinition metricDefinition; EventMetricDefinition eventDefinition; if (Log.Metrics.TryGetValue(MetricTypeName, m_Category, MetricCounterName, out metricDefinition) == false) { //it doesn't exist yet - add it eventDefinition = new EventMetricDefinition(MetricTypeName, m_Category, MetricCounterName); eventDefinition.Description = MetricDefinitionDescription; EventMetricValueDefinitionCollection valueDefinitionCollection = (EventMetricValueDefinitionCollection)eventDefinition.Values; valueDefinitionCollection.Add("operationname", typeof(string), "Operation Name", "The operation that was executed."); valueDefinitionCollection.Add("duration", typeof(TimeSpan), "Duration", "The duration the operation executed."); ((EventMetricValueDefinition)eventDefinition.Values["duration"]).UnitCaption = "Milliseconds"; eventDefinition.DefaultValue = eventDefinition.Values["duration"]; //and don't forget to register it! eventDefinition = eventDefinition.Register(); } else { eventDefinition = (EventMetricDefinition)metricDefinition; } //Get the METRIC IMetric metric; EventMetric eventMetric; if (eventDefinition.Metrics.TryGetValue(null, out metric) == false) { eventMetric = new EventMetric(eventDefinition, (string)null); } else { eventMetric = (EventMetric)metric; } //and finally we can RECORD THE SAMPLE. EventMetricSample metricSample = eventMetric.CreateSample(); metricSample.SetValue("operationname", OperationName); metricSample.SetValue("duration", Duration); metricSample.Write(); }
MetricDefinition IPacketObjectFactory <MetricDefinition, MetricDefinitionCollection> .GetDataObject(MetricDefinitionCollection optionalParent) { //this is just here for us to be able to create our derived type for the generic infrastructure EventMetricDefinition newDefinitionObject = new EventMetricDefinition(optionalParent, this); optionalParent.Add(newDefinitionObject); // We have to add it to the collection, no longer done in constructor. return(newDefinitionObject); }
public void Setup() { IMetricDefinition newMetricDefinition; EventMetricDefinition newEventMetricDefinition; // See if we already created the event metric we need if (Log.Metrics.TryGetValue("GeneralMetricCollectionTests", "Gibraltar.Monitor.Test", "Manual", out newMetricDefinition) == false) { // Didn't find it, so define an event metric manually (the hard way) newEventMetricDefinition = new EventMetricDefinition("GeneralMetricCollectionTests", "Gibraltar.Monitor.Test", "Manual"); newMetricDefinition = newEventMetricDefinition; // cast it as the base type, too // we now have a minimal definition, but we probably want to add a few attributes to make it useful // NOTE: This is designed to exactly match UserDataObject for convenience in analzing results. EventMetricValueDefinitionCollection valueDefinitions = (EventMetricValueDefinitionCollection)newEventMetricDefinition.Values; valueDefinitions.Add("short_average", typeof(short), "Short Average", "Data of type Short").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("short_sum", typeof(short), "Short Sum", "Data of type Short").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("ushort_average", typeof(ushort), "UShort Average", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("ushort_sum", typeof(ushort), "UShort Sum", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("int_average", typeof(int), "Int Average", "Data of type Int").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("int_sum", typeof(int), "Int Sum", "Data of type Int").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("uint_average", typeof(uint), "UInt Average", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("uint_sum", typeof(uint), "UInt Sum", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("long_average", typeof(long), "Long Average", "Data of type Long").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("long_sum", typeof(long), "Long Sum", "Data of type Long").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("ulong_average", typeof(ulong), "ULong Average", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("ulong_sum", typeof(ulong), "ULong Sum", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("decimal_average", typeof(decimal), "Decimal Average", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("decimal_sum", typeof(decimal), "Decimal Sum", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("double_average", typeof(double), "Double Average", "Data of type Double").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("double_sum", typeof(double), "Double Sum", "Data of type Double").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("float_average", typeof(float), "Float Average", "Data of type Float").DefaultTrend = EventMetricValueTrend.Average; valueDefinitions.Add("float_sum", typeof(float), "Float Sum", "Data of type Float").DefaultTrend = EventMetricValueTrend.Sum; valueDefinitions.Add("string", typeof(string), "String", "Data of type String"); valueDefinitions.Add("system.enum", typeof(System.Enum), "System.Enum", "Data of type System.Enum"); newEventMetricDefinition.DefaultValue = newEventMetricDefinition.Values["int_average"]; newEventMetricDefinition = newEventMetricDefinition.Register(); // Register it with the collection. } else { // Found one, try to cast it to the expected EventMetricDefinition type (raise exception if fails to match) newEventMetricDefinition = (EventMetricDefinition)newMetricDefinition; } IMetric newMetric; if (newMetricDefinition.Metrics.TryGetValue(null, out newMetric) == false) { // go ahead and add this new metric newMetric = new EventMetric(newEventMetricDefinition, (string)null); //add the default metric. } Assert.IsNotNull(newMetricDefinition); Assert.IsNotNull(newEventMetricDefinition); Assert.IsNotNull(newMetric); }
public void Setup() { // This is an example of how to create an event metric definition programatically. EventMetricDefinition newMetricDefinition; // Define an event metric manually (the long way). First, see if it's already registered... if (EventMetricDefinition.TryGetValue("EventMetricTests", "Gibraltar.Monitor.Test", "Manual", out newMetricDefinition) == false) { // It's not registered yet, so we need to fill out the template to define it. EventMetricDefinition newEventMetric = new EventMetricDefinition("EventMetricTests", "Gibraltar.Monitor.Test", "Manual"); // Now we want to add a few value columns to make it useful. // NOTE: This is designed to exactly match UserEventObject for convenience in analzing results. // The dummy data values we're using are unitless, so we'll just use null for the required unitCaption parameter. newEventMetric.AddValue("short_average", typeof(short), SummaryFunction.Average, null, "Short Average", "Data of type Short"); newEventMetric.AddValue("short_sum", typeof(short), SummaryFunction.Sum, null, "Short Sum", "Data of type Short"); newEventMetric.AddValue("short_runningaverage", typeof(short), SummaryFunction.RunningAverage, null, "Short Running Average", "Data of type Short"); newEventMetric.AddValue("short_runningsum", typeof(short), SummaryFunction.RunningSum, null, "Short Running Sum", "Data of type Short"); newEventMetric.AddValue("ushort_average", typeof(ushort), SummaryFunction.Average, null, "UShort Average", "Data of type UShort"); newEventMetric.AddValue("ushort_sum", typeof(ushort), SummaryFunction.Sum, null, "UShort Sum", "Data of type UShort"); // Pick an interesting value column as the default to be graphed for this metric. We'll pass it below. EventMetricValueDefinition defaultValue = newEventMetric.AddValue("int_average", typeof(int), SummaryFunction.Average, null, "Int Average", "Data of type Int"); newEventMetric.AddValue("int_sum", typeof(int), SummaryFunction.Sum, null, "Int Sum", "Data of type Int"); newEventMetric.AddValue("uint_average", typeof(uint), SummaryFunction.Average, null, "UInt Average", "Data of type UInt"); newEventMetric.AddValue("uint_sum", typeof(uint), SummaryFunction.Sum, null, "UInt Sum", "Data of type UInt"); newEventMetric.AddValue("long_average", typeof(long), SummaryFunction.Average, null, "Long Average", "Data of type Long"); newEventMetric.AddValue("long_sum", typeof(long), SummaryFunction.Sum, null, "Long Sum", "Data of type Long"); newEventMetric.AddValue("ulong_average", typeof(ulong), SummaryFunction.Average, null, "ULong Average", "Data of type ULong"); newEventMetric.AddValue("ulong_sum", typeof(ulong), SummaryFunction.Sum, null, "ULong Sum", "Data of type ULong"); newEventMetric.AddValue("decimal_average", typeof(decimal), SummaryFunction.Average, null, "Decimal Average", "Data of type Decimal"); newEventMetric.AddValue("decimal_sum", typeof(decimal), SummaryFunction.Sum, null, "Decimal Sum", "Data of type Decimal"); newEventMetric.AddValue("double_average", typeof(double), SummaryFunction.Average, null, "Double Average", "Data of type Double"); newEventMetric.AddValue("double_sum", typeof(double), SummaryFunction.Sum, null, "Double Sum", "Data of type Double"); newEventMetric.AddValue("float_average", typeof(float), SummaryFunction.Average, null, "Float Average", "Data of type Float"); newEventMetric.AddValue("float_sum", typeof(float), SummaryFunction.Sum, null, "Float Sum", "Data of type Float"); newEventMetric.AddValue("timespan_average", typeof(TimeSpan), SummaryFunction.Average, null, "TimeSpan Average", "Data of type TimeSpan"); newEventMetric.AddValue("timespan_sum", typeof(TimeSpan), SummaryFunction.Sum, null, "TimeSpan Sum", "Data of type TimeSpan"); newEventMetric.AddValue("timespan_runningaverage", typeof(TimeSpan), SummaryFunction.RunningAverage, null, "TimeSpan Running Average", "Data of type TimeSpan represented as a running average."); newEventMetric.AddValue("timespan_runningsum", typeof(TimeSpan), SummaryFunction.RunningSum, null, "TimeSpan Running Sum", "Data of type TimeSpan represented as a running sum."); newEventMetric.AddValue("string", typeof(string), SummaryFunction.Count, null, "String", "Data of type String"); newEventMetric.AddValue("system.enum", typeof(UserDataEnumeration), SummaryFunction.Count, null, "System.Enum", "Data of type System.Enum"); // Finally, register it with Gibraltar, and specify the default value column we saved above. EventMetricDefinition.Register(ref newEventMetric, defaultValue); } EventMetricDefinition metricDefinition; Assert.IsTrue(EventMetricDefinition.TryGetValue("EventMetricTests", "Gibraltar.Monitor.Test", "Manual", out metricDefinition)); Assert.IsNotNull(metricDefinition); }
public void RecordEventMetricPerformanceTest() { // Internally we want to make this comparable to the reflection test, just varying the part that uses reflection. EventMetricDefinition metricDefinition; Assert.IsTrue(EventMetricDefinition.TryGetValue("EventMetricTests", "Gibraltar.Monitor.Test", "Manual", out metricDefinition)); Assert.IsNotNull(metricDefinition); EventMetric thisExperimentMetric = EventMetric.Register(metricDefinition, "RecordEventMetricPerformanceTest"); Assert.IsNotNull(thisExperimentMetric); // We're going to write out a BUNCH of samples... Trace.TraceInformation("Starting performance test"); DateTime curTime = DateTime.Now; //for timing how fast we are int curSample; for (curSample = 0; curSample < 32000; curSample++) { EventMetricSample newSample = thisExperimentMetric.CreateSample(); newSample.SetValue("short_average", curSample); newSample.SetValue("short_sum", curSample); newSample.SetValue("short_runningaverage", curSample); newSample.SetValue("short_runningsum", curSample); newSample.SetValue("ushort_average", (ushort)curSample); newSample.SetValue("ushort_sum", (ushort)curSample); newSample.SetValue("int_average", curSample); newSample.SetValue("int_sum", curSample); newSample.SetValue("uint_average", (uint)curSample); newSample.SetValue("uint_sum", (uint)curSample); newSample.SetValue("long_average", curSample); newSample.SetValue("long_sum", curSample); newSample.SetValue("ulong_average", (ulong)curSample); newSample.SetValue("ulong_sum", (ulong)curSample); newSample.SetValue("decimal_average", curSample); newSample.SetValue("decimal_sum", curSample); newSample.SetValue("double_average", curSample); newSample.SetValue("double_sum", curSample); newSample.SetValue("float_average", curSample); newSample.SetValue("float_sum", curSample); newSample.SetValue("timespan_average", new TimeSpan(curSample)); newSample.SetValue("timespan_sum", new TimeSpan(curSample)); newSample.SetValue("timespan_runningaverage", new TimeSpan(curSample)); newSample.SetValue("timespan_runningsum", new TimeSpan(curSample)); newSample.SetValue("string", string.Format(CultureInfo.CurrentCulture, "The current manual sample is {0}", curSample)); newSample.SetValue("system.enum", (UserDataEnumeration)curSample); newSample.Write(); //only now does it get written because we had to wait until you populated the metrics } TimeSpan duration = DateTime.Now - curTime; Trace.TraceInformation("Completed performance test in {0} milliseconds for {1} samples", duration.TotalMilliseconds, curSample); Log.Verbose(LogWriteMode.WaitForCommit, "Test.Agent.Metrics.EventMetric.Methods", "Event Metrics performance test flush", null); }
private static EventMetricDefinition DefineRequestMetric() { var definition = new EventMetricDefinition(Constants.LogSystem, Constants.MetricCategory, "Request"); definition.AddValue("request", typeof(string), SummaryFunction.Count, "Request", "Request", "The query that was executed."); definition.AddValue("duration", typeof(TimeSpan), SummaryFunction.Average, "Duration", "Duration", "Time taken to execute the query"); definition.AddValue("error", typeof(string), SummaryFunction.Count, "Errors", "Errors", "Errors executing query."); EventMetricDefinition.Register(ref definition); return(definition); }
private static EventMetricDefinition DefineRequestMetric(string applicationName) { var definition = new EventMetricDefinition(applicationName, "AspNetCore", "Request"); definition.AddValue("request", typeof(string), SummaryFunction.Count, "Request", "Request", "The query that was executed."); definition.AddValue("duration", typeof(TimeSpan), SummaryFunction.Average, "Duration", "Duration", "Time taken to execute the query"); definition.AddValue("error", typeof(string), SummaryFunction.Count, "Errors", "Errors", "Errors executing query."); EventMetricDefinition.Register(ref definition); return(definition); }
/// <summary> /// Perform the one-time work to create a metric /// </summary> /// <param name="name">Dot-delimited display name for this metric</param> private void InitializeMetric(string name) { // Handle edge cases if (string.IsNullOrEmpty(name)) { name = DefaultInstance; } name = name.Trim(); while (!string.IsNullOrEmpty(name) && name[0] == '.') { name = name.Substring(1).Trim(); } // Set up category and instance as Loupe wants string category; string instance; var pos = name.LastIndexOf('.'); // check for delimited name if (pos <= 0) { // If not deliminated, just use base category category = RootCategory; instance = name; } else { // If delimited, just use the last part as instance name // and combine the rest with category category = RootCategory + '.' + name.Substring(0, pos); instance = name.Substring(pos + 1); } _logCategory = category + "." + instance; // Initializ category for logging EventMetricDefinition metricDefinition; // Create the metric on first call then use cached copy thereafter if (!EventMetricDefinition.TryGetValue(MetricSystem, category, instance, out metricDefinition)) { metricDefinition = new EventMetricDefinition(MetricSystem, category, instance); metricDefinition.AddValue(DurationCaption, typeof(TimeSpan), SummaryFunction.Average, null, DurationCaption, null); EventMetricDefinition.Register(ref metricDefinition); } // Grab the metric from cache Metric = EventMetric.Register(metricDefinition, null); }
public void Setup() { IMetricDefinition newMetricDefinition; //Define an event metric manually (the long way) if (Log.Metrics.TryGetValue("EventMetricTests", "Gibraltar.Monitor.Test", "Manual", out newMetricDefinition) == false) { //Define an event metric manually (the hard way) EventMetricDefinition newEventMetric = new EventMetricDefinition("EventMetricTests", "Gibraltar.Monitor.Test", "Manual"); //we now have a minimal definition, but we probably want to add a few attributes to make it useful //NOTE: This is designed to exactly match UserDataObject for convenience in analzing results. EventMetricValueDefinitionCollection valueDefinition = (EventMetricValueDefinitionCollection)newEventMetric.Values; valueDefinition.Add("short_average", typeof(short), "Short Average", "Data of type Short").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("short_sum", typeof(short), "Short Sum", "Data of type Short").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("short_runningaverage", typeof(short), "Short Running Average", "Data of type Short").DefaultTrend = EventMetricValueTrend.RunningAverage; valueDefinition.Add("short_runningsum", typeof(short), "Short Running Sum", "Data of type Short").DefaultTrend = EventMetricValueTrend.RunningSum; valueDefinition.Add("ushort_average", typeof(ushort), "UShort Average", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("ushort_sum", typeof(ushort), "UShort Sum", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("int_average", typeof(int), "Int Average", "Data of type Int").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("int_sum", typeof(int), "Int Sum", "Data of type Int").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("uint_average", typeof(uint), "UInt Average", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("uint_sum", typeof(uint), "UInt Sum", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("long_average", typeof(long), "Long Average", "Data of type Long").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("long_sum", typeof(long), "Long Sum", "Data of type Long").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("ulong_average", typeof(ulong), "ULong Average", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("ulong_sum", typeof(ulong), "ULong Sum", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("decimal_average", typeof(decimal), "Decimal Average", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("decimal_sum", typeof(decimal), "Decimal Sum", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("double_average", typeof(double), "Double Average", "Data of type Double").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("double_sum", typeof(double), "Double Sum", "Data of type Double").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("float_average", typeof(float), "Float Average", "Data of type Float").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("float_sum", typeof(float), "Float Sum", "Data of type Float").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("timespan_average", typeof(TimeSpan), "TimeSpan Average", "Data of type TimeSpan").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("timespan_sum", typeof(TimeSpan), "TimeSpan Sum", "Data of type TimeSpan").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("timespan_runningaverage", typeof(TimeSpan), "TimeSpan Running Average", "Data of type TimeSpan represented as a running average.").DefaultTrend = EventMetricValueTrend.RunningAverage; valueDefinition.Add("timespan_runningsum", typeof(TimeSpan), "TimeSpan Running Sum", "Data of type TimeSpan represented as a running sum.").DefaultTrend = EventMetricValueTrend.RunningSum; valueDefinition.Add("string", typeof(string), "String", "Data of type String"); valueDefinition.Add("system.enum", typeof(UserDataEnumeration), "System.Enum", "Data of type System.Enum"); newEventMetric.DefaultValue = newEventMetric.Values["int_average"]; newEventMetric.Register(); // Register it with the collection. } //And define a metric using reflection (not the same metric as above) //UserDataObject myDataObject = new UserDataObject(null); //EventMetric.AddOrGet(myDataObject); }
public void RecordEventMetric() { // Internally we want to make this comparable to the reflection test, just varying the part that uses reflection. EventMetricDefinition metricDefinition; Assert.IsTrue(EventMetricDefinition.TryGetValue("EventMetricTests", "Gibraltar.Monitor.Test", "Manual", out metricDefinition)); Assert.IsNotNull(metricDefinition); EventMetric thisExperimentMetric = EventMetric.Register(metricDefinition, "RecordEventMetric"); Assert.IsNotNull(thisExperimentMetric); // To write a sample manually, we must first create an empty sample for this event metric instance. EventMetricSample newSample = thisExperimentMetric.CreateSample(); // Then we set the values. newSample.SetValue("short_average", 1); newSample.SetValue("short_sum", 1); newSample.SetValue("short_runningaverage", 1); newSample.SetValue("short_runningsum", 1); newSample.SetValue("ushort_average", (ushort)1); newSample.SetValue("ushort_sum", (ushort)1); newSample.SetValue("int_average", 1); newSample.SetValue("int_sum", 1); newSample.SetValue("uint_average", (uint)1); newSample.SetValue("uint_sum", (uint)1); newSample.SetValue("long_average", 1); newSample.SetValue("long_sum", 1); newSample.SetValue("ulong_average", (ulong)1); newSample.SetValue("ulong_sum", (ulong)1); newSample.SetValue("decimal_average", 1); newSample.SetValue("decimal_sum", 1); newSample.SetValue("double_average", 1); newSample.SetValue("double_sum", 1); newSample.SetValue("float_average", 1); newSample.SetValue("float_sum", 1); newSample.SetValue("timespan_average", new TimeSpan(1)); newSample.SetValue("timespan_sum", new TimeSpan(1)); newSample.SetValue("timespan_runningaverage", new TimeSpan(1)); newSample.SetValue("timespan_runningsum", new TimeSpan(1)); newSample.SetValue("string", string.Format(CultureInfo.CurrentCulture, "The current manual sample is {0}", 1)); newSample.SetValue("system.enum", (UserDataEnumeration)1); // And finally, tell the sample to write itself to the Gibraltar log. newSample.Write(); }
public void RegisterEventMetrics() { //Define an event metric manually (the hard way) EventMetricDefinition newEventMetric = new EventMetricDefinition("EventMetricTests", "Gibraltar.Monitor.Test", "Manual"); //we now have a minimal definition, but we probably want to add a few attributes to make it useful //NOTE: This is designed to exactly match UserDataObject for convenience in analyzing results. EventMetricValueDefinitionCollection valueDefinition = (EventMetricValueDefinitionCollection)newEventMetric.Values; valueDefinition.Add("short_average", typeof(short), "Short Average", "Data of type Short").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("short_sum", typeof(short), "Short Sum", "Data of type Short").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("short_runningaverage", typeof(short), "Short Running Average", "Data of type Short").DefaultTrend = EventMetricValueTrend.RunningAverage; valueDefinition.Add("short_runningsum", typeof(short), "Short Running Sum", "Data of type Short").DefaultTrend = EventMetricValueTrend.RunningSum; valueDefinition.Add("ushort_average", typeof(ushort), "UShort Average", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("ushort_sum", typeof(ushort), "UShort Sum", "Data of type UShort").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("int_average", typeof(int), "Int Average", "Data of type Int").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("int_sum", typeof(int), "Int Sum", "Data of type Int").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("uint_average", typeof(uint), "UInt Average", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("uint_sum", typeof(uint), "UInt Sum", "Data of type UInt").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("long_average", typeof(long), "Long Average", "Data of type Long").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("long_sum", typeof(long), "Long Sum", "Data of type Long").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("ulong_average", typeof(ulong), "ULong Average", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("ulong_sum", typeof(ulong), "ULong Sum", "Data of type ULong").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("decimal_average", typeof(decimal), "Decimal Average", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("decimal_sum", typeof(decimal), "Decimal Sum", "Data of type Decimal").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("double_average", typeof(double), "Double Average", "Data of type Double").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("double_sum", typeof(double), "Double Sum", "Data of type Double").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("float_average", typeof(float), "Float Average", "Data of type Float").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("float_sum", typeof(float), "Float Sum", "Data of type Float").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("timespan_average", typeof(TimeSpan), "TimeSpan Average", "Data of type TimeSpan").DefaultTrend = EventMetricValueTrend.Average; valueDefinition.Add("timespan_sum", typeof(TimeSpan), "TimeSpan Sum", "Data of type TimeSpan").DefaultTrend = EventMetricValueTrend.Sum; valueDefinition.Add("timespan_runningaverage", typeof(TimeSpan), "TimeSpan Running Average", "Data of type TimeSpan represented as a running average.").DefaultTrend = EventMetricValueTrend.RunningAverage; valueDefinition.Add("timespan_runningsum", typeof(TimeSpan), "TimeSpan Running Sum", "Data of type TimeSpan represented as a running sum.").DefaultTrend = EventMetricValueTrend.RunningSum; valueDefinition.Add("string", typeof(string), "String", "Data of type String"); valueDefinition.Add("system.enum", typeof(UserDataEnumeration), "System.Enum", "Data of type System.Enum"); newEventMetric.DefaultValue = newEventMetric.Values["int_average"]; newEventMetric = newEventMetric.Register(); // Register it with the collection. //Create this instance of that definition newEventMetric.Metrics.Add("This Experiment"); }
public void EventMetricsByAttributesPerformanceTest() { EventMetric.Register(typeof(UserPerformanceObject)); Trace.TraceInformation("Event metrics registered by attributes."); UserPerformanceObject eventObject = new UserPerformanceObject("AttributesPerformanceTest"); DateTimeOffset operationStart = DateTimeOffset.UtcNow; DateTimeOffset operationEnd = operationStart.AddMilliseconds(1234); eventObject.SetEventData(@"C:\Dummy\File\Name.txt", UserFileOperation.Write, operationStart, operationEnd); //first, lets get everything to flush so we have our best initial state. Log.Information(LogWriteMode.WaitForCommit, "Test.Agent.Metrics.Performance", "Preparing for Test", "Flushing queue"); //now that we know it's flushed everything, lets do our timed loop. DateTimeOffset startTime = DateTimeOffset.UtcNow; for (int curMessage = 0; curMessage < LoopsPerEventTest; curMessage++) { EventMetricDefinition.Write(eventObject); } DateTimeOffset messageEndTime = DateTimeOffset.UtcNow; //one wait for commit message to force the buffer to flush. Log.Information(LogWriteMode.WaitForCommit, "Test.Agent.Metrics.Performance", "Waiting for Samples to Commit", null); //and store off our time DateTimeOffset endTime = DateTimeOffset.UtcNow; TimeSpan testDuration = endTime - startTime; TimeSpan loopDuration = messageEndTime - startTime; const int messagesPerTest = LoopsPerEventTest * MessagesPerEventLoop; Trace.TraceInformation("Event Metrics by Attributes Test committed {0:N0} events in {1:F3} ms (average {2:F4} ms per message). Average loop time {3:F4} ms ({4} values per message) and final flush time {5:F3} ms.", messagesPerTest, testDuration.TotalMilliseconds, (testDuration.TotalMilliseconds / messagesPerTest), (loopDuration.TotalMilliseconds / LoopsPerEventTest), ValuesPerEventMessage, (endTime - messageEndTime).TotalMilliseconds); }
/// <summary>Return a registered event metric instance for the provided event metric definition.</summary> /// <remarks><para>If the provided event metric definition is an unregistered raw definition, it will be registered /// as a completed definition (or a matching registered event metric definition will be used in place of it), but /// an inability to successfully register the definition will result in an ArgumentException, as with calling /// the Register() method in EventMetricDefinition. Using a properly-registered definition is preferred.</para> /// <para>If an event metric with that instance name already exists for that registered definition, it will be /// returned. Otherwise, one will be created from that definition and returned.</para></remarks> /// <param name="definition">The metric definition for the desired metric instance.</param> /// <param name="instanceName">The desired instance name (may be null for the default instance).</param> /// <returns>The EventMetric object for the requested event metric instance.</returns> /// <example> /// See the <see cref="EventMetric">EventMetric Class Overview</see> for an example. /// </example> public static EventMetric Register(EventMetricDefinition definition, string instanceName) { if (definition == null) { // Uh-oh. They gave us a non-EventMetricDefinition? return(null); } EventMetricDefinition metricDefinition; lock (definition.Lock) { if (definition.IsReadOnly == false) { // Uh-oh. They gave us a raw event metric definition which wasn't registered. // But they're calling Register(), so they'd expect us to complete registration for them in this call. metricDefinition = definition.Register(); } else { // Assume this is a registered definition. ToDo: Make sure they only get IsReadOnly when actually registered. metricDefinition = definition; } } EventMetric eventMetric; EventMetricCollection metrics = metricDefinition.Metrics; lock (metrics.Lock) { if (metrics.TryGetValue(instanceName, out eventMetric) == false) { eventMetric = metrics.Add(instanceName); } } return(eventMetric); }
/// <summary> /// Perform the one-time work to create a metric /// </summary> /// <param name="name">Dot-delimited display name for this metric</param> private void InitializeMetric(string name) { // Handle edge cases if (string.IsNullOrEmpty(name)) name = DefaultInstance; name = name.Trim(); while (!string.IsNullOrEmpty(name) && name[0] == '.') name = name.Substring(1).Trim(); // Set up category and instance as Loupe wants string category; string instance; var pos = name.LastIndexOf('.'); // check for delimited name if (pos <= 0) { // If not deliminated, just use base category category = RootCategory; instance = name; } else { // If delimited, just use the last part as instance name // and combine the rest with category category = RootCategory + '.' + name.Substring(0, pos); instance = name.Substring(pos + 1); } _logCategory = category + "." + instance; // Initializ category for logging EventMetricDefinition metricDefinition; // Create the metric on first call then use cached copy thereafter if (!EventMetricDefinition.TryGetValue(MetricSystem, category, instance, out metricDefinition)) { metricDefinition = new EventMetricDefinition(MetricSystem, category, instance); metricDefinition.AddValue(DurationCaption, typeof(TimeSpan), SummaryFunction.Average, null, DurationCaption, null); EventMetricDefinition.Register(ref metricDefinition); } // Grab the metric from cache Metric = EventMetric.Register(metricDefinition, null); }
/// <summary> /// Create a new values dictionary for the specified metric definition /// </summary> /// <param name="definition">The parent metric definition object that will own this dictionary.</param> internal EventMetricValueDefinitionCollection(EventMetricDefinition definition) { m_Definition = definition; m_WrappedCollection = (Monitor.EventMetricValueDefinitionCollection)definition.WrappedDefinition.Values; m_WrappedCollection.CollectionChanged += WrappedCollection_CollectionChanged; }
/// <summary> /// Create a new event metric object from the provided event metric definition /// </summary> /// <remarks>The new metric will automatically be added to the metric definition's metrics collection.</remarks> /// <param name="definition">The metric definition for the metric instance</param> /// <param name="instanceName">The unique name of this instance within the metric's collection.</param> internal EventMetric(EventMetricDefinition definition, string instanceName) : this(definition, new Monitor.EventMetric(definition.WrappedDefinition, instanceName)) { // Let our other constructor handle the rest. }
/// <summary> /// Create a new API value definition from a provided API event metric definition and internal value definition. /// </summary> /// <param name="definition">The API event metric definition that owns this value definition</param> /// <param name="valueDefinition">The internal value definition to wrap.</param> internal EventMetricValueDefinition(EventMetricDefinition definition, Monitor.EventMetricValueDefinition valueDefinition) { m_Definition = definition; m_WrappedValueDefinition = valueDefinition; }
/// <summary> /// Create a new metric with the provided API event metric definition and an internal event metric object to wrap. /// </summary> /// <remarks>The new metric will automatically be added to the metric definition's metrics collection.</remarks> /// <param name="definition">The API event metric definition that defines this metric</param> /// <param name="metric">The internal event metric</param> internal EventMetric(EventMetricDefinition definition, Monitor.EventMetric metric) { m_MetricDefinition = definition; m_WrappedMetric = metric; }
/// <summary> /// Create a new event metric dictionary for the provided definition. /// </summary> /// <remarks>This dictionary is created automatically by the Custom Sampled Metric Definition during its initialization.</remarks> /// <param name="metricDefinition">The definition of the event metric to create a metric dictionary for</param> public EventMetricCollection(EventMetricDefinition metricDefinition) { m_MetricDefinition = metricDefinition; m_WrappedCollection = metricDefinition.WrappedDefinition.Metrics; }
public static EventMetricDefinition AddCount(this EventMetricDefinition definition, string name, string caption, string description) { definition.AddValue(name, typeof(string), SummaryFunction.Count, null, caption, description); return(definition); }
public static EventMetricDefinition AddFlag(this EventMetricDefinition definition, string name, string caption, string description) { definition.AddValue(name, typeof(bool), SummaryFunction.Average, "Hits", caption, description); return(definition); }
/// <summary> /// Write event metric samples for all event metrics defined on the provided data object by attributes. /// </summary> /// <remarks>The provided user data object must be assignable to the bound type which defined this event metric /// via attributes.</remarks> /// <param name="metricData">The object to retrieve both metric values and definition from</param> /// <param name="fallbackInstanceName">The instance name to fall back on if a definition does not specify an instance name binding (may be null).</param> /// <example> /// See the <see cref="EventMetric">EventMetric Class Overview</see> for an example. /// </example> public static void Write(object metricData, string fallbackInstanceName) { // The real logic is in EventMetricDefinition. EventMetricDefinition.Write(metricData, fallbackInstanceName); }
private static EventMetricDefinition GetMetricDefinition() { if (!EventMetricDefinition.TryGetValue(MetricSystem, MetricCategory, MetricCaption, out var eventMetricDefinition)) { eventMetricDefinition = new EventMetricDefinition(MetricSystem, MetricCategory, MetricName) { Caption = MetricCaption, Description = MetricDescription }; eventMetricDefinition.AddHitCount(MetricValue.PageName, "Page", "The page name without path"); eventMetricDefinition.AddHitCount(MetricValue.AbsolutePath, "Absolute Path", "The full path from the root of the web site to the page that was requested including the page"); eventMetricDefinition.AddDuration(MetricValue.TotalDuration, "Total Request Duration", "The entire time it took for the request to be satisfied"); eventMetricDefinition.AddDuration(MetricValue.AuthenticateDuration, "Authenticate Request Duration", "The time it took for the request to be authenticated"); eventMetricDefinition.AddDuration(MetricValue.AuthorizeRequestDuration, "Authorize Request Duration", "The time it took for the request to be authorized"); eventMetricDefinition.AddDuration(MetricValue.ResolveRequestCacheDuration, "Resolve Request Cache Duration", "The time it took for the request to be looked up in cache"); eventMetricDefinition.AddDuration(MetricValue.AcquireRequestStateDuration, "Acquire Request State Duration", "The time it took for the request state to be acquired"); eventMetricDefinition.AddDuration(MetricValue.RequestHandlerExecuteDuration, "Request Handler Execute Duration", "The time it took for the request handler to execute. This includes the time for most ASP.NET page code"); eventMetricDefinition.AddDuration(MetricValue.ReleaseRequestStateDuration, "Release Request State Duration", "The time it took for the request state to be released"); eventMetricDefinition.AddDuration(MetricValue.UpdateRequestCacheDuration, "Update Request Cache Duration", "The time it took for the request cache to be updated"); eventMetricDefinition.AddDuration(MetricValue.LogRequestDuration, "Log Request Duration", "The time it took for the request to be logged"); eventMetricDefinition.AddFlag(MetricValue.ServedFromCache, "Cached Response", "Indicates if the response was served from the output cache instead of generated"); eventMetricDefinition.AddHitCount(MetricValue.QueryString, "Query String", "The query string used for the request"); eventMetricDefinition.AddCount(MetricValue.UserName, "User", "The user associated with the action being performed"); eventMetricDefinition.AddCount(MetricValue.SessionId, "SessionId", "Session Id associated with action being performed"); eventMetricDefinition.AddCount(MetricValue.AgentSessionId, "AgentSessionId", "Id from JavaScript agent for session"); EventMetricDefinition.Register(ref eventMetricDefinition); } return(eventMetricDefinition); }
/// <summary> /// Write event metric samples for all event metrics defined on the provided data object by attributes. /// </summary> /// <remarks>The provided user data object must be assignable to the bound type which defined this event metric /// via attributes.</remarks> /// <param name="metricData">The object to retrieve both metric values and definition from</param> /// <example> /// See the <see cref="EventMetric">EventMetric Class Overview</see> for an example. /// </example> public static void Write(object metricData) { // The real logic is in EventMetricDefinition. EventMetricDefinition.Write(metricData, null); }
/// <summary> /// Helper function to retrieve the desired EventMetric /// </summary> private static EventMetric GetMetric(string caption, string category, string instance) { EventMetricDefinition cacheMetric; //so we can be called multiple times we want to see if the definition already exists. if (EventMetricDefinition.TryGetValue("PostSharp", category, caption, out cacheMetric) == false) { cacheMetric = new EventMetricDefinition("PostSharp", category, caption); //add the values (that are part of the definition) cacheMetric.DefaultValue = cacheMetric.AddValue("duration", typeof(TimeSpan), SummaryFunction.Average, "ms", "Duration", "Average execution duration"); cacheMetric.AddValue("namespace", typeof(string), SummaryFunction.Count, "", "Namespace", "Namespace"); cacheMetric.AddValue("class", typeof(string), SummaryFunction.Count, "", "Class", "Class name ignoring namespace"); cacheMetric.AddValue("method", typeof(string), SummaryFunction.Count, "", "Method", "Method name ignoring class and namespace"); cacheMetric.AddValue("fullname", typeof(string), SummaryFunction.Count, "", "FullName", "Fully qualified name of the class and method"); EventMetricDefinition.Register(ref cacheMetric); } EventMetric cacheEventMetric = EventMetric.Register(cacheMetric, instance); return cacheEventMetric; }
public static EventMetricDefinition AddDuration(this EventMetricDefinition definition, string name, string caption, string description) { definition.AddValue(name, typeof(double), SummaryFunction.Average, "Milliseconds", caption, description); return(definition); }