/// <summary> /// Searches for the specified value and returns the zero-based index of the first occurrence /// </summary> /// <param name="item"></param> /// <returns></returns> public int IndexOf(IMetricDefinition item) { lock (m_Lock) { return(m_List.IndexOf(item)); } }
private IWithMetricsQueryExecute CreateMetricsQuery(AggregationType metricAggregation, TimeSpan metricsInterval, string metricFilter, string metricDimension, int?metricLimit, IMetricDefinition metricDefinition, DateTime recordDateTime) { var historyStartingFromInHours = _azureMonitorIntegrationConfiguration.Value.History.StartingFromInHours; var metricQuery = metricDefinition.DefineQuery() .StartingFrom(recordDateTime.AddHours(-historyStartingFromInHours)) .EndsBefore(recordDateTime) .WithAggregation(metricAggregation.ToString()) .WithInterval(metricsInterval); var queryLimit = metricLimit ?? Defaults.MetricDefaults.Limit; if (string.IsNullOrWhiteSpace(metricFilter) == false) { var filter = metricFilter.Replace("/", "%2F"); metricQuery.WithOdataFilter(filter); metricQuery.SelectTop(queryLimit); } if (string.IsNullOrWhiteSpace(metricDimension) == false) { metricQuery.WithOdataFilter($"{metricDimension} eq '*'"); metricQuery.SelectTop(queryLimit); } return(metricQuery); }
public void MetricDefinitionCollectionOverrun() { Assert.Throws <ArgumentOutOfRangeException>(() => { IMetricDefinition testMetricDefinition = Log.Metrics[Log.Metrics.Count]; }); }
/// <summary> /// Add an existing MetricDefinition item to this collection. /// </summary> /// <remarks>If the supplied MetricDefinitin item is already in the collection, an exception will be thrown.</remarks> /// <param name="item">The new MetricDefinition item to add.</param> public void Add(IMetricDefinition item) { //we really don't want to support this method, but we have to for ICollection<T> compatibility. So we're going to ruthlessly //verify that the metric object was created correctly. if (item == null) { throw new ArgumentNullException(nameof(item)); } //we're about to modify the collection, get a lock. We don't want the lock to cover the changed event since //we really don't know how long that will take, and it could be deadlock prone. lock (m_Lock) { //make sure we don't already have it if (m_Dictionary.ContainsKey(item.Id)) { throw new ArgumentException("The specified metric definition item is already in the collection.", nameof(item)); } if (m_DictionaryByName.ContainsKey(item.Name)) { throw new ArgumentException("A metric definition item for the same metric is already in the collection.", nameof(item)); } //add it to both lookup collections m_Dictionary.Add(item.Id, item); m_DictionaryByName.Add(item.Name, item); m_List.Add(item); } //and fire our event OnCollectionChanged(new CollectionChangedEventArgs <IMetricDefinitionCollection, IMetricDefinition>(this, item, CollectionAction.Added)); }
private void Dump(IMetricDefinition metricDefinition) { var i = 0; var maxTry = 3; while (i < maxTry) { try { DumpWithErr(metricDefinition); return; } catch (Exception e) { if (i + 1 < maxTry) { Console.WriteLine($"retry even see {e.Message}"); } else { Console.WriteLine($"Fail for {e.Message} after {maxTry}"); } } i++; } }
/// <summary> /// Retrieve an item from the collection by its key if present. If not present, the default value of the object is returned. /// </summary> /// <param name="key">The key of the value to get.</param> /// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param> /// <returns>true if the collection contains an element with the specified key; otherwise false.</returns> public bool TryGetValue(Guid key, out IMetricDefinition value) { lock (m_Lock) { //gateway to our inner dictionary try get value return(m_Dictionary.TryGetValue(key, out value)); } }
/// <summary> /// Determines whether an element is in the collection. /// </summary> /// <remarks>This method determines equality using the default equality comparer for the type of values in the list. It performs /// a linear search and therefore is an O(n) operation.</remarks> /// <param name="item">The object to locate in the collection.</param> /// <returns>true if the item is found in the collection; otherwise false.</returns> public bool Contains(IMetricDefinition item) { lock (m_Lock) { //here we are relying on the fact that the comment object implements IComparable sufficiently to guarantee uniqueness return(m_List.Contains(item)); } }
/// <summary> /// Determines if the provided MetricDefinition object is identical to this object. /// </summary> /// <param name="other">The MetricDefinition object to compare this object to</param> /// <returns>True if the objects represent the same data.</returns> public bool Equals(IMetricDefinition other) { // Careful, it could be null; check it without recursion if (ReferenceEquals(other, null)) { return(false); // Since we're a live object we can't be equal to a null instance. } //they are the same if their GUID's match return(Id == other.Id); }
/// <summary> /// Create a CSV for a metric that contains only a single instance /// </summary> static public StreamWriter CreateMetricStream(IRepositoryContext context, ExportAddInConfiguration config, ISession session, IMetricDefinition metric, ref int metricFileCount) { var info = session.Summary; var subFolder = Path.Combine(info.Product, info.Application); var metricName = metric.CategoryName + "." + metric.CounterName; subFolder = Path.Combine(subFolder, metricName); var fileName = info.EndDateTime.ToString("yyyy-MM-dd HH-mm-ss") + " on " + info.HostName; fileName += " (" + ++metricFileCount + ")"; // Uniquify filename for convenience with Excel if (config.UseUniqueFilenames) fileName += " " + info.Id; return CreateStream(context, config.SessionExportPath, subFolder, fileName, ".csv"); }
/// <summary> /// Retrieve an item from the collection by its key if present. If not present, the default value of the object is returned. /// </summary> /// <param name="name">The metric name to locate in the collection</param> /// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param> /// <returns>true if the collection contains an element with the specified key; otherwise false.</returns> public bool TryGetValue(string name, out IMetricDefinition value) { //protect ourself from a null before we do the trim (or we'll get an odd user the error won't understand) if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } lock (m_Lock) { //gateway to our inner dictionary try get value return(m_DictionaryByName.TryGetValue(name.Trim(), out value)); } }
public void MetricDefinitionStringKeyTrimming() { MetricDefinition lookupMetricDefinition = GetTestMetricDefinition(); //Now try to get it using each key element with extra white space. IMetricDefinition testMetricDefinition = Log.Metrics[string.Format(CultureInfo.InvariantCulture, " {0} ", lookupMetricDefinition.Name)]; Assert.IsNotNull(testMetricDefinition); testMetricDefinition = Log.Metrics[string.Format(CultureInfo.InvariantCulture, " {0} ", lookupMetricDefinition.MetricTypeName), string.Format(CultureInfo.InvariantCulture, " {0} ", lookupMetricDefinition.CategoryName), string.Format(CultureInfo.InvariantCulture, " {0} ", lookupMetricDefinition.CounterName)]; Assert.IsNotNull(testMetricDefinition); }
private IWithMetricsQueryExecute CreateMetricsQuery(AggregationType metricAggregation, TimeSpan metricsInterval, string metricFilter, IMetricDefinition metricDefinition, DateTime recordDateTime) { var metricQuery = metricDefinition.DefineQuery() .StartingFrom(recordDateTime.AddDays(-5)) .EndsBefore(recordDateTime) .WithAggregation(metricAggregation.ToString()) .WithInterval(metricsInterval); if (string.IsNullOrWhiteSpace(metricFilter) == false) { metricQuery.WithOdataFilter(metricFilter); } return(metricQuery); }
private async Task <IMetric> GetRelevantMetric(string metricName, AggregationType metricAggregation, TimeSpan metricInterval, string metricFilter, IMetricDefinition metricDefinition, DateTime recordDateTime) { var metricQuery = CreateMetricsQuery(metricAggregation, metricInterval, metricFilter, metricDefinition, recordDateTime); var metrics = await metricQuery.ExecuteAsync(); // We already filtered this out so only expect to have one var relevantMetric = metrics.Metrics.SingleOrDefault(var => var.Name.Value.ToUpper() == metricName.ToUpper()); if (relevantMetric == null) { throw new MetricNotFoundException(metricName); } return(relevantMetric); }
private void Dump(IMetricDefinition metricDefinition) { var metricCollection = metricDefinition.DefineQuery() .StartingFrom(DateTime.Now.AddMinutes(-20).ToUniversalTime()).EndsBefore(DateTime.Now.ToUniversalTime()) //.WithAggregation("Average") //.WithInterval(TimeSpan.FromSeconds(5)) //.WithOdataFilter("name.value eq 'CpuPercentage'") .Execute(); Console.WriteLine("Metrics for '" + _argsOption.ResourceId + "':"); Console.WriteLine("Namespacse: " + metricCollection.Namespace); Console.WriteLine("Query time: " + metricCollection.Timespan); Console.WriteLine("Time Grain: " + metricCollection.Interval); Console.WriteLine("Cost: " + metricCollection.Cost); foreach (var metric in metricCollection.Metrics) { Console.WriteLine("\tMetric: " + metric.Name.LocalizedValue); Console.WriteLine("\tType: " + metric.Type); Console.WriteLine("\tUnit: " + metric.Unit); Console.WriteLine("\tTime Series: "); foreach (var timeElement in metric.Timeseries) { Console.WriteLine("\t\tMetadata: "); foreach (var metadata in timeElement.Metadatavalues) { Console.WriteLine("\t\t\t" + metadata.Name.LocalizedValue + ": " + metadata.Value); } Console.WriteLine("\t\tData: "); foreach (var data in timeElement.Data) { Console.WriteLine("\t\t\t" + data.TimeStamp + " : (Min) " + data.Minimum + " : (Max) " + data.Maximum + " : (Avg) " + data.Average + " : (Total) " + data.Total + " : (Count) " + data.Count); } } } }
/// <summary> /// Export a CSV file for each instance of a sampled metric /// </summary> private void ExportSampledMetric(ISession session, IMetricDefinition metricDefinition, ref int metricFileCount) { if (metricDefinition.Metrics.Count == 1) { try { using ( var writer = StreamCreator.CreateMetricStream(_context, Config, session, metricDefinition, ref metricFileCount)) { ExportSamples(writer, metricDefinition.Metrics[0]); } } catch (Exception ex) { _context.Log.RecordException(ex, LogCategory, true); } } else { foreach (var metric in metricDefinition.Metrics) { try { using ( var writer = StreamCreator.CreateMetricInstanceStream(_context, Config, session, metric, ref metricFileCount)) { ExportSamples(writer, metric); } } catch (Exception ex) { _context.Log.RecordException(ex, LogCategory, true); } } } }
///<summary>Inserting objects by index is not supported because the collection is sorted.</summary> ///<remarks>This method is implemented only for IList interface support and will throw an exception if called.</remarks> public void Insert(int index, IMetricDefinition item) { //we don't support setting an object by index; we are sorted. throw new NotSupportedException(); }
/// <summary> /// Adds the metric read data. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="fieldList">The field list.</param> /// <returns>System.String.</returns> private string AddMetricReadData(IProcessDefinition process, IMetricDefinition metric, IList<string> fieldList) { var sb = new StringBuilder(); var list = fieldList.Select(f => string.Format("object group{0}", f)).ToList(); sb.AppendFormat(@" public void ReadData(decimal result{0}{1}) {{ LoadProperty(ResultProperty, result); {2} {3} }}" , fieldList.Any() ? string.Format(", {0}Info info", process.Name) : null , list.Any() ? ", " + string.Join(", ", fieldList.Select(f => string.Format("object group{0} = null", f)).ToList()) : null , fieldList.Any() ? "LoadProperty(ObjProperty, info);" : null , fieldList.Any() ? string.Join(@" " , fieldList.Select(f => string.Format(@"{0}_OriginalValue = info.GetValueByPropertyName(""{0}""); LoadProperty({0}Property, group{0} ?? "" "");", f)).ToList()) : null); return sb.ToString(); }
/// <summary> /// Retrieve an item from the collection by its key if present. If not present, the default value of the object is returned. /// </summary> /// <param name="metricTypeName">The unique metric type</param> /// <param name="categoryName">The name of the category with which this definition is associated.</param> /// <param name="counterName">The name of the definition within the category.</param> /// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param> /// <returns>true if the collection contains an element with the specified key; otherwise false.</returns> /// <exception cref="ArgumentNullException">The provided metricsSystem, categoryName, or counterName was null.</exception> public bool TryGetValue(string metricTypeName, string categoryName, string counterName, out IMetricDefinition value) { //get the key for the provided values string key = MetricDefinition.GetKey(metricTypeName, categoryName, counterName); lock (m_Lock) { //gateway to our inner dictionary try get value return(m_DictionaryByName.TryGetValue(key, out value)); } }
/// <summary> /// Adds the metric aggregare result. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.String.</returns> private static string AddMetricAggregareResult(IProcessDefinition process, IMetricDefinition metric, IList<string> groupingFieldsList) { Func<string> getAggregateSource = () => { var columnType = GetMetricOrderByFieldType(process, metric, groupingFieldsList); if (columnType.HasValue && (columnType.Value == ColumnTypes.Approval || columnType.Value == ColumnTypes.Boolean)) { return "item.Value"; } if (!groupingFieldsList.Any()) { return "infoList"; } if (string.IsNullOrEmpty(metric.OrderByMetricField) || metric.MetricFieldSystemName == metric.OrderByMetricField) { return "item.ToList()"; } return "item.Source"; }; return string.Format( @" var result = {0}.CalculateAggregates({1}, new List<{2}> {{ {2}.Create( columnName: ""{3}"", summaryType: ""{4}"", targetType: typeof({5}Info).GetPropertyByName(""{3}"").PropertyType.FullName, typeName: typeof({5}Info).GetPropertyByName(""{3}"").PropertyType.ToString()) }}).First().Value; if (result == Constants.Empty || result == Constants.BlockedResult) {{ result = ""0""; }}" , typeof(AggregateProcessor).Name , getAggregateSource() , typeof(AggregateDefinition).Name , metric.MetricFieldSystemName , metric.SummaryType , process.Name); }
/// <summary> /// Metrics the order by specific field. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.String.</returns> private static string MetricOrderBySpecificField(IProcessDefinition process, IMetricDefinition metric, List<string> groupingFieldsList) { var columnType = GetMetricOrderByFieldType(process, metric, groupingFieldsList); if (columnType.HasValue && (columnType.Value == ColumnTypes.Approval || columnType.Value == ColumnTypes.Boolean)) { string executeConverter = null; switch (columnType) { case ColumnTypes.Approval: executeConverter = string.Format(@"approvalConvertMethod.Invoke(approvalInstance, new object[] {{ item.Key.{0}, null, null, null }});", metric.OrderByMetricField); break; case ColumnTypes.Boolean: var field = GetField(process, metric.OrderByMetricField); var converterParameter = string.Format("{0}~{1}~{2}", ((string) field.Value.NameValuesList["UndefinedLabel"]).Replace("\"", null), ((string) field.Value.NameValuesList["FalseLabel"]).Replace("\"", null), ((string) field.Value.NameValuesList["TrueLabel"]).Replace("\"", null)) .ToLiteral(); executeConverter = string.Format(@"boolConverter.Convert(item.Key.{0}, null, {1}, CultureInfo.InvariantCulture);", metric.OrderByMetricField, converterParameter); break; } return string.Format(@" var temporaryDictionary = new Dictionary<string, List<{0}Info>>(); {1} foreach (var item in groupedList) {{ var result = {2} temporaryDictionary.Add(result as string, item.ToList()); }}" , process.Name , columnType.Value == ColumnTypes.Approval ? "if (approvalConvertMethod != null && approvalInstance != null)" : null , executeConverter ); } return null; }
/// <summary> /// Removing objects is not supported. /// </summary> /// <remarks>This method is implemented only for ICollection interface support and will throw an exception if called.</remarks> /// <param name="item">The MetricDefinition item to remove.</param> public bool Remove(IMetricDefinition item) { throw new NotSupportedException(); }
public void InvalidateMetricDefinition(IMetricDefinition metricDefinition) { }
/// <summary> /// Compares this MetricDefinition to another MetricDefinition to determine sort order /// </summary> /// <remarks>MetricDefinition instances are sorted by their Name property.</remarks> /// <param name="other">The MetricDefinition to compare this MetricDefinition against</param> /// <returns>An int which is less than zero, equal to zero, or greater than zero to reflect whether /// this MetricDefinition should sort as being less-than, equal to, or greater-than the other /// MetricDefintion, respectively.</returns> public int CompareTo(IMetricDefinition other) { //our packet knows what to do. return(m_Packet.CompareTo(((MetricDefinition)other).Packet)); }
public void InvalidateMetricDefinition(IMetricDefinition metricDefinition) { using (readerWriterLock.AcquireWriteLock()) metricDefinitions.Remove(metricDefinition); }
/// <summary> /// Adds the metric order by2. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="fieldList">The field list.</param> /// <returns>System.String.</returns> private static string AddMetricOrderBy2(IProcessDefinition process, IMetricDefinition metric, IList<string> fieldList) { if (metric.MetricFieldSystemName == metric.OrderByMetricField || (metric.SummaryType == SummaryTypes.Count && metric.OrderByMetricField == string.Empty)) { return "aggregateValueList.Add(item.ToList().First(), Convert.ToDecimal(result));"; } return AddMetricCurrentMetricReadData(process, metric, fieldList); }
/// <summary> /// Adds the metric order by3. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="fieldList">The field list.</param> /// <returns>System.String.</returns> private static string AddMetricOrderBy3(IProcessDefinition process, IMetricDefinition metric, IList<string> fieldList) { if (metric.MetricFieldSystemName == metric.OrderByMetricField || (metric.SummaryType == SummaryTypes.Count && metric.OrderByMetricField == string.Empty)) { return string.Format(@" foreach (var item in aggregateValueList.OrderBy{0}(x => x.Value)) {{ {1} }} ", metric.OrderByAscending.HasValue && !metric.OrderByAscending.Value ? "Descending" : null , AddMetricCurrentMetricReadData(process, metric, fieldList)); } return null; }
/// <summary> /// Metrics the get converter. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.String.</returns> private static string MetricGetConverter(IProcessDefinition process, IMetricDefinition metric, List<string> groupingFieldsList) { string approvalConverter = null; string dateTimeConverter = null; string boolConverter = null; foreach (var groupField in groupingFieldsList) { var field = GetField(process, groupField); if (groupField == field.Value.SystemName) { if (field.Value.ColumnType == ColumnTypes.Approval && approvalConverter == null) { approvalConverter = @" // get approvalConverter var sharedTypesLibFullName = AppDomain.CurrentDomain.GetAssemblies().First(x => x.FullName.StartsWith(""Cebos.Veyron.SharedTypes,"")); var type = Type.GetType(""Cebos.Veyron.SharedTypes.Converters.ApprovalStateToDisplayNameConverter, "" + sharedTypesLibFullName); System.Reflection.MethodInfo approvalConvertMethod = null; object approvalInstance = null; if (type != null) { approvalConvertMethod = type.GetMethod(""Convert""); approvalInstance = Activator.CreateInstance(type); } // end"; } if (field.Value.ColumnType == ColumnTypes.DateTime && dateTimeConverter == null) { dateTimeConverter = string.Format(@" var dtConverter = new {0}();" , typeof(DateTimeFormatConverter).FullName); } if (field.Value.ColumnType == ColumnTypes.Boolean && boolConverter == null) { boolConverter = string.Format(@" var boolConverter = new {0}();" , typeof(CheckboxToCustomValueConverter).FullName); } } } return string.Format("{0}{1}{2}{1}{3}", approvalConverter, Environment.NewLine, dateTimeConverter, boolConverter); }
/// <summary> /// Gets the type of the metric order by field. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.Nullable{ColumnTypes}.</returns> private static ColumnTypes? GetMetricOrderByFieldType(IProcessDefinition process, IMetricDefinition metric, IList<string> groupingFieldsList) { foreach (var groupedField in groupingFieldsList) { var field = GetField(process, groupedField); if (groupedField == field.Value.SystemName && metric.OrderByMetricField == field.Value.SystemName) { if (field.Value.ColumnType == ColumnTypes.Approval) { return ColumnTypes.Approval; } if (field.Value.ColumnType == ColumnTypes.Boolean) { var result = field.Value.NameValuesList["IsSwitchToggle"]; if (Convert.ToBoolean(result)) { return ColumnTypes.Boolean; } } } } return null; }
public void InvalidateMetricDefinition(IMetricDefinition metricDefinition) { metricDefinitions.Remove(metricDefinition); }
async static Task <int> ProcessMetricAsync(IAzure subApi, ISubscription subscription, IResourceGroup group, IGenericResource res, IMetricDefinition metric) { int m = 0; DateTime? last = null; MetricLastDate record = null; lock (_ctx) { record = _ctx.MetricLastDates.Where(d => d.Key == metric.Id).SingleOrDefault(); } last = record?.LastDate; try { await _sem.WaitAsync(); var from = last?.AddMinutes(1.0) ?? DateTime.UtcNow.RoundMinutes().AddHours(-1.0); var to = DateTime.UtcNow.RoundMinutes().AddMinutes(10.0); var maxDataToGet = TimeSpan.FromHours(2.0); if (to - from > maxDataToGet) { to = from + maxDataToGet; } if (metric.Inner.IsDimensionRequired == true) { var dims = metric.Inner.Dimensions; // can ignore.. return(0); } var data = await metric.DefineQuery() .StartingFrom(from) .EndsBefore(to) // as much as possible .WithAggregation("Average,Minimum,Maximum,Count,Total") .WithResultType(ResultType.Data) .WithInterval(TimeSpan.FromMinutes(1)) .ExecuteAsync(); if (data.Metrics.Count != 1 || data.Metrics[0].Timeseries.Count != 1) { return(0); } /* * Console.WriteLine($"query from {from} to {to}: {data.Metrics[0].Timeseries[0].Data.Count()} results"); * Console.WriteLine($" min: {data.Metrics[0].Timeseries[0].Data.Min(d => d.Minimum)}"); * Console.WriteLine($" max: {data.Metrics[0].Timeseries[0].Data.Max(d => d.Maximum)}"); * Console.WriteLine($" avg: {data.Metrics[0].Timeseries[0].Data.Average(d => d.Average)}"); */ var dubiousCutoffUtc = DateTime.UtcNow.AddMinutes(-30.0); var pts = data.Metrics[0].Timeseries[0].Data // from future to past .OrderByDescending(d => d.TimeStamp) // skip anything with no data yet .SkipWhile(d => d.TimeStamp > dubiousCutoffUtc && (d.Average ?? 0) == 0 && (d.Maximum ?? 0) == 0 && (d.Minimum ?? 0) == 0 && (d.Total ?? 0) == 0 && ( (d.Count ?? 0) == 0 || d.TimeStamp > dubiousCutoffUtc ) ) // and the first one with data (probably the current slice) .Skip(1); /* * if (pts.Any()) * Console.WriteLine($"actual data points: {pts.Count()}, from {pts.Min(p => p.TimeStamp)} to {pts.Max(p => p.TimeStamp)}"); * else * Console.WriteLine($"all data points dismissed"); */ if (pts.Any()) { lock (_logger) { foreach (var pt in pts.Reverse()) { var entry = new Dictionary <string, object>(13) { { "@timestamp", pt.TimeStamp.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFFZ") }, { "lib", "Saffron" }, { "type", "cloud" }, { "cloud", "Azure" }, { "sub", subscription.DisplayName }, { "group", group.Name }, { "resource", new Dictionary <string, object>(3) { { "name", res.Name }, { "type", res.Type }, { "tags", res.Tags } } }, { "metric", new Dictionary <string, object>(2) { { "name", metric.Name.Value }, { "unit", metric.Unit } } }, }; if (pt.Average != null) { entry["avg"] = pt.Average; } if (pt.Count != null) { entry["num"] = pt.Count; } if (pt.Maximum != null) { entry["max"] = pt.Maximum; } if (pt.Minimum != null) { entry["min"] = pt.Minimum; } if (pt.Total != null) { entry["sum"] = pt.Total; } _logger.LogAsJson(entry); m++; } } lock (_ctx) { if (record == null) { record = new MetricLastDate { Key = metric.Id }; _ctx.MetricLastDates.Add(record); } record.LastDate = pts.First().TimeStamp; _ctx.SaveChanges(); numStats++; long ageMs = (long)(DateTime.UtcNow - record.LastDate).TotalMilliseconds; totalAgeMs += ageMs; if (ageMs > oldestAgeMs) { oldestAgeMs = ageMs; } } } } catch (ErrorResponseException ex) { // ignored //Console.WriteLine($"Error reading {metric.Name.LocalizedValue} from {res.Name} ({res.Type}): {ex.Message} - {ex.Body.Code} {ex.Body.Message}"); } catch (HttpRequestException ex) { Console.WriteLine($"HTTP error reading {metric.Name.LocalizedValue} from {res.Name} ({res.Type}): {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Error reading {metric.Name.LocalizedValue} from {res.Name} ({res.Type}): {ex.Message}"); } finally { _sem.Release(); } return(m); }
/// <summary> /// Adds the metric order by1. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.String.</returns> private static string AddMetricOrderBy1(IProcessDefinition process, IMetricDefinition metric, IList<string> groupingFieldsList) { var columnType = GetMetricOrderByFieldType(process, metric, groupingFieldsList); if (columnType.HasValue && (columnType.Value == ColumnTypes.Approval || columnType.Value == ColumnTypes.Boolean)) { return string.Format("var orderedList = temporaryDictionary.OrderBy{0}(x => x.Key);", metric.OrderByAscending.HasValue && !metric.OrderByAscending.Value ? "Descending" : null); } if (metric.MetricFieldSystemName == metric.OrderByMetricField || (metric.SummaryType == SummaryTypes.Count && metric.OrderByMetricField == string.Empty)) { return string.Format("var aggregateValueList = new Dictionary<{0}Info, decimal>();", process.Name); } if (!string.IsNullOrWhiteSpace(metric.OrderByMetricField)) { var field = GetField(process, metric.OrderByMetricField); return string.Format("var orderedList = groupedList.Select(x => new {{ Source = x.OrderBy{0}(y => y.{1}) }}).OrderBy{0}(x => x.Source.First().{1});", metric.OrderByAscending.HasValue && !metric.OrderByAscending.Value ? "Descending" : null, field.Key); } return null; }
/// <summary> /// Create a CSV for a metric that contains only a single instance /// </summary> static public StreamWriter CreateMetricStream(IRepositoryContext context, ExportAddInConfiguration config, ISession session, IMetricDefinition metric, ref int metricFileCount) { var info = session.Summary; var subFolder = Path.Combine(info.Product, info.Application); var metricName = metric.CategoryName + "." + metric.CounterName; subFolder = Path.Combine(subFolder, metricName); var fileName = info.EndDateTime.ToString("yyyy-MM-dd HH-mm-ss") + " on " + info.HostName; fileName += " (" + ++metricFileCount + ")"; // Uniquify filename for convenience with Excel if (config.UseUniqueFilenames) { fileName += " " + info.Id; } return(CreateStream(context, config.SessionExportPath, subFolder, fileName, ".csv")); }
/// <summary> /// Adds the metric aggregate calculator. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="fieldList">The field list.</param> /// <returns>System.String.</returns> private static string AddMetricAggregateCalculator(IProcessDefinition process, IMetricDefinition metric, IList<string> fieldList) { if (!fieldList.Any()) { return string.Format(@" {0} {1}", AddMetricAggregareResult(process, metric, fieldList), AddMetricCurrentMetricReadData(process, metric, fieldList)); } var sb = new StringBuilder(); sb.AppendFormat(@" {0} foreach (var item in {1}) {{ {2} {3} }} {4}" , AddMetricOrderBy1(process, metric, fieldList) , string.IsNullOrEmpty(metric.OrderByMetricField) || metric.MetricFieldSystemName == metric.OrderByMetricField ? "groupedList" : "orderedList" , AddMetricAggregareResult(process, metric, fieldList) , AddMetricOrderBy2(process, metric, fieldList) , AddMetricOrderBy3(process, metric, fieldList)); return sb.ToString(); }
/// <summary> /// FullMetricName is guaranteed to not have a period in CounterName /// </summary> public static string FullMetricName(this IMetricDefinition definition) { // Simplify parsing by ensuring CounterName has no embedded periods return(definition.CategoryName + "." + definition.CounterName.Replace(".", " ")); }
/// <summary> /// Adds the metric current metric read data. /// </summary> /// <param name="process">The process.</param> /// <param name="metric">The metric.</param> /// <param name="groupingFieldsList">The grouping fields list.</param> /// <returns>System.String.</returns> private static string AddMetricCurrentMetricReadData(IProcessDefinition process, IMetricDefinition metric, IList<string> groupingFieldsList) { string readDataFirstInfoObject = null; var columnType = GetMetricOrderByFieldType(process, metric, groupingFieldsList); Action getReadDataFirstInfoObject = () => { if (columnType.HasValue && (columnType.Value == ColumnTypes.Approval || columnType.Value == ColumnTypes.Boolean)) { readDataFirstInfoObject = "item.Value.First()"; return; } if (!groupingFieldsList.Any()) { return; } if (metric.MetricFieldSystemName == metric.OrderByMetricField || (metric.SummaryType == SummaryTypes.Count && metric.OrderByMetricField == string.Empty)) { readDataFirstInfoObject = "item.Key"; return; } if (!string.IsNullOrWhiteSpace(metric.OrderByMetricField)) { readDataFirstInfoObject = "item.Source.First()"; return; } readDataFirstInfoObject = "item.ToList().First()"; }; getReadDataFirstInfoObject(); string metricinfoClass; if (columnType.HasValue && (columnType.Value == ColumnTypes.Approval || columnType.Value == ColumnTypes.Boolean)) { metricinfoClass = "Value.First()"; } else if (!string.IsNullOrWhiteSpace(metric.OrderByMetricField) && metric.MetricFieldSystemName != metric.OrderByMetricField) { metricinfoClass = "Source.First()"; } else { metricinfoClass = "Key"; } var groupByFieldValuesList = new List<string>(); foreach (var groupedField in groupingFieldsList) { var field = GetField(process, groupedField); var groupFieldPath = groupedField; if (!string.IsNullOrWhiteSpace(metric.OrderByMetricField) && metric.MetricFieldSystemName != metric.OrderByMetricField) { groupFieldPath = field.Key; } if (groupedField == field.Value.SystemName) { var variable = string.Format("var {0}_value = ", groupedField); switch (field.Value.ColumnType) { case ColumnTypes.DateTime: variable += string.Format(@"dtConverter.Convert({0}.{1}, null, ""{2}"", null);" , readDataFirstInfoObject , field.Key , field.Value.DateTimeFormat); break; case ColumnTypes.Approval: if (metric.OrderByMetricField == field.Value.SystemName) { variable += "item.Key;"; } else { variable += string.Format(@"approvalConvertMethod.Invoke(approvalInstance, new object[] {{ item.{0}.{1}, null, null, null }});", metricinfoClass, groupFieldPath); } break; case ColumnTypes.Boolean: var result = field.Value.NameValuesList["IsSwitchToggle"]; if (Convert.ToBoolean(result)) { if (metric.OrderByMetricField == field.Value.SystemName) { variable += "item.Key;"; } else { var converterParameter = string.Format("{0}~{1}~{2}", ((string)field.Value.NameValuesList["UndefinedLabel"]).Replace("\"", null), ((string)field.Value.NameValuesList["FalseLabel"]).Replace("\"", null), ((string)field.Value.NameValuesList["TrueLabel"]).Replace("\"", null)) .ToLiteral(); variable += string.Format(@"boolConverter.Convert(item.{0}.{1}, null, {2}, CultureInfo.InvariantCulture);", metricinfoClass, groupFieldPath, converterParameter); } } else { goto default; } break; default: variable += string.Format("item.{0}.{1};", metricinfoClass, groupFieldPath); break; } variable += Environment.NewLine; groupByFieldValuesList.Add(variable); } } return string.Format(@" var currentMetric = new {0}Metric_{1}(); {2} currentMetric.ReadData(Convert.ToDecimal({3}) {4}{5}); Add(currentMetric);" , process.Name , metric.Guid.ToString().Replace("-", string.Empty) , string.Join(string.Empty, groupByFieldValuesList) , metric.MetricFieldSystemName == metric.OrderByMetricField || readDataFirstInfoObject == "item.Key" ? "item.Value" : "result" , readDataFirstInfoObject != null ? ", " + readDataFirstInfoObject : null , groupingFieldsList.IsNullOrEmpty() ? null : ", " + string.Join(",", groupingFieldsList.Select(f => string.Format("{0}_value", f)))); }