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"]);
        }
Example #4
0
        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"]);
        }
Example #8
0
        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);
        }
Example #9
0
        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();
        }