public void ReadOnlyFieldReturnsValue() { var metric = new MetricWithTaggedReadOnlyField("test"); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value); var tags = metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()); Assert.True(tags.ContainsKey("Tag")); Assert.Equal("test", tags["Tag"]); }
public void ReadWriteFieldThrows() { var metric = new MetricWithTaggedReadWriteField(); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value); Assert.Throws <InvalidOperationException>( () => metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()) ); }
public void TagValuesAreConverted() { var metric = new MetricWithTaggedReadOnlyProperty("value"); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value.ToUpper()); var tags = metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()); Assert.True(tags.ContainsKey("Tag")); Assert.Equal("VALUE", tags["Tag"]); }
internal string GetTagsJson( ReadOnlyDictionary <string, string> defaultTags, TagValueConverterDelegate tagValueConverter, Dictionary <Type, List <BosunTag> > tagsByTypeCache) { var sb = new StringBuilder(); foreach (var tag in GetTagsList(defaultTags, tagsByTypeCache)) { var value = tag.IsFromDefault ? defaultTags[tag.Name] : tag.FieldInfo.GetValue(this)?.ToString(); if (tagValueConverter != null) { value = tagValueConverter(tag.Name, value); } if (value == null) { if (tag.IsOptional) { continue; } throw new InvalidOperationException( $"null is not a valid tag value for {GetType().FullName}.{tag.FieldInfo.Name}. This tag was declared as non-optional."); } if (!BosunValidation.IsValidTagValue(value)) { throw new InvalidOperationException( $"Invalid value for tag {GetType().FullName}.{tag.FieldInfo.Name}. \"{value}\" is not a valid tag value. " + $"Only characters in the regex class [a-zA-Z0-9\\-_./] are allowed."); } // everything is already validated, so we can skip a more formal JSON parser which would handle escaping sb.Append(",\"" + tag.Name + "\":\"" + value + "\""); } if (sb.Length == 0) { if (!IsExternalCounter()) { throw new InvalidOperationException( $"At least one tag value must be specified for every metric. {GetType().FullName} was instantiated without any tag values."); } sb.Append('{'); } else { sb[0] = '{'; // replaces the first comma } sb.Append('}'); return(sb.ToString()); }
public void CustomTagName() { var metric = new MetricWithCustomNaming("custom-name"); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value); var tags = metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()); Assert.True(tags.ContainsKey("my-awesome-tag")); Assert.False(tags.ContainsKey("Tag")); Assert.Equal("custom-name", tags["my-awesome-tag"]); }
public void InvalidFieldTypesThrow(Type type) { var metricType = typeof(MetricWithInvalidField <>).MakeGenericType(type); var metric = (MetricBase)Activator.CreateInstance(metricType); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value); Assert.Throws <InvalidOperationException>( () => metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()) ); }
public void EnumMembersReturnValues() { var metric = new MetricWithTaggedEnumMembers(TagValue.One, TagValue.Two); var defaultTags = ImmutableDictionary <string, string> .Empty; var tagConverter = new TagValueConverterDelegate((name, value) => value); var tags = metric.GetTags(defaultTags, tagConverter, x => x, new Dictionary <Type, List <MetricTag> >()); Assert.True(tags.ContainsKey("Field")); Assert.Equal("One", tags["Field"]); Assert.True(tags.ContainsKey("Property")); Assert.Equal("Two", tags["Property"]); }
internal IReadOnlyDictionary <string, string> GetTags( IReadOnlyDictionary <string, string> defaultTags, TagValueConverterDelegate tagValueConverter, Func <string, string> propertyToTagConverter, Dictionary <Type, List <MetricTag> > tagsByTypeCache) { var tags = new Dictionary <string, string>(); foreach (var tag in GetTagsList(defaultTags, propertyToTagConverter, tagsByTypeCache)) { var value = tag.IsFromDefault ? defaultTags[tag.Name] : tag.GetValue(this); if (tagValueConverter != null) { value = tagValueConverter(tag.Name, value); } if (value == null) { if (tag.IsOptional) { continue; } throw new InvalidOperationException( $"null is not a valid tag value for {GetType().FullName}.{tag.MemberInfo.Name}. This tag was declared as non-optional."); } if (!MetricValidation.IsValidTagValue(value)) { throw new InvalidOperationException( $"Invalid value for tag {GetType().FullName}.{tag.MemberInfo.Name}. \"{value}\" is not a valid tag value. " + $"Only characters in the regex class [a-zA-Z0-9\\-_./] are allowed."); } tags.Add(tag.Name, value); } if (tags.Count == 0) { throw new InvalidOperationException( $"At least one tag value must be specified for every metric. {GetType().FullName} was instantiated without any tag values."); } return(tags); }
internal string GetTagsJson(ReadOnlyDictionary<string, string> defaultTags, TagValueConverterDelegate tagValueConverter, Dictionary<Type, List<BosunTag>> tagsByTypeCache) { var sb = new StringBuilder(); foreach (var tag in GetTagsList(defaultTags, tagsByTypeCache)) { var value = tag.IsFromDefault ? defaultTags[tag.Name] : tag.FieldInfo.GetValue(this)?.ToString(); if (tagValueConverter != null) value = tagValueConverter(tag.Name, value); if (value == null) { if (tag.IsOptional) continue; throw new InvalidOperationException( $"null is not a valid tag value for {GetType().FullName}.{tag.FieldInfo.Name}. This tag was declared as non-optional."); } if (!BosunValidation.IsValidTagValue(value)) { throw new InvalidOperationException( $"Invalid value for tag {GetType().FullName}.{tag.FieldInfo.Name}. \"{value}\" is not a valid tag value. " + $"Only characters in the regex class [a-zA-Z0-9\\-_./] are allowed."); } // everything is already validated, so we can skip a more formal JSON parser which would handle escaping sb.Append(",\"" + tag.Name + "\":\"" + value + "\""); } if (sb.Length == 0) { throw new InvalidOperationException( $"At least one tag value must be specified for every metric. {GetType().FullName} was instantiated without any tag values."); } sb[0] = '{'; // replaces the first comma sb.Append('}'); return sb.ToString(); }