Exemple #1
0
        public void BindMetricWithoutPrefix(string name, string unit, Type type)
        {
            lock (_metricsLock)
            {
                RootMetricInfo rmi;
                if (_rootNameToInfo.TryGetValue(name, out rmi))
                {
                    if (rmi.Type != type)
                    {
                        throw new Exception($"Cannot bind metric name \"{name}\" to Type {type.FullName}. It has already been bound to {rmi.Type.FullName}");
                    }

                    if (rmi.Unit != unit)
                    {
                        throw new Exception($"Cannot bind metric name \"{name}\" to unit \"{unit}\". It has already been bound to \"{rmi.Unit}\"");
                    }

                    return;
                }

                if (!type.IsSubclassOf(typeof(BosunMetric)))
                {
                    throw new Exception($"Cannot bind metric \"{name}\" to Type {type.FullName}. It does not inherit from BosunMetric.");
                }

                _rootNameToInfo[name] = new RootMetricInfo {
                    Type = type, Unit = unit
                };
            }
        }
Exemple #2
0
        /// <summary>
        /// Binds a given metric name to a specific data model. Metrics with this name will only be allowed to use the type <paramref name="type"/>. Calling
        /// this method is usually not necessary. A metric will be bound to the type that it is first instantiated with.
        /// </summary>
        public void BindMetric(string name, string unit, Type type, bool includePrefix = true)
        {
            if (includePrefix)
            {
                name = MetricsNamePrefix + name;
            }

            lock (_metricsLock)
            {
                if (_rootNameToInfo.TryGetValue(name, out var rmi))
                {
                    if (rmi.Type != type)
                    {
                        throw new Exception($"Cannot bind metric name \"{name}\" to Type {type.FullName}. It has already been bound to {rmi.Type.FullName}");
                    }

                    if (rmi.Unit != unit)
                    {
                        throw new Exception($"Cannot bind metric name \"{name}\" to unit \"{unit}\". It has already been bound to \"{rmi.Unit}\"");
                    }

                    return;
                }

                if (!type.IsSubclassOf(typeof(MetricBase)))
                {
                    throw new Exception($"Cannot bind metric \"{name}\" to Type {type.FullName}. It does not inherit from MetricBase.");
                }

                _rootNameToInfo[name] = new RootMetricInfo {
                    Type = type, Unit = unit
                };
            }
        }
Exemple #3
0
        private T GetMetricInternal <T>(string name, bool addPrefix, string unit, string description, T metric, bool mustBeNew) where T : BosunMetric
        {
            if (addPrefix)
            {
                name = MetricsNamePrefix + name;
            }

            var metricType = typeof(T);

            if (metric == null)
            {
                // if the type has a constructor without params, then create an instance
                var constructor = metricType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
                if (constructor == null)
                {
                    throw new ArgumentNullException(nameof(metric), metricType.FullName + " has no public default constructor. Therefore the metric parameter cannot be null.");
                }
                metric = (T)constructor.Invoke(new object[0]);
            }
            metric.Collector = this;

            metric.Name        = name;
            metric.Description = description;
            metric.Unit        = unit;

            metric.LoadSuffixes();

            lock (_metricsLock)
            {
                RootMetricInfo rmi;
                if (_rootNameToInfo.TryGetValue(name, out rmi))
                {
                    if (rmi.Type != metricType)
                    {
                        throw new Exception(
                                  $"Attempted to create metric name \"{name}\" with Type {metricType.FullName}. This metric name has already been bound to Type {rmi.Type.FullName}.");
                    }

                    if (rmi.Unit != unit)
                    {
                        throw new Exception(
                                  $"Cannot bind metric name \"{name}\" to unit \"{unit}\". It has already been bound to \"{rmi.Unit}\"");
                    }
                }
                else if (_nameAndSuffixToRootName.ContainsKey(name))
                {
                    throw new Exception(
                              $"Attempted to create metric name \"{name}\" with Type {metricType.FullName}. " +
                              $"This metric name is already in use as a suffix of Type {_rootNameToInfo[_nameAndSuffixToRootName[name]].Type.FullName}.");
                }

                // claim all suffixes. Do this in two passes (check then add) so we don't end up in an inconsistent state.
                foreach (var s in metric.SuffixesArray)
                {
                    var ns = name + s;

                    // verify this is a valid metric name at all (it should be, since both parts are pre-validated, but just in case).
                    if (!BosunValidation.IsValidMetricName(ns))
                    {
                        throw new Exception($"\"{ns}\" is not a valid metric name");
                    }

                    if (_nameAndSuffixToRootName.ContainsKey(ns) && _nameAndSuffixToRootName[ns] != name)
                    {
                        throw new Exception(
                                  $"Attempted to create metric name \"{ns}\" with Type {metricType.FullName}. " +
                                  $"This metric name is already in use as a suffix of Type {_rootNameToInfo[_nameAndSuffixToRootName[ns]].Type.FullName}.");
                    }
                }

                foreach (var s in metric.SuffixesArray)
                {
                    _nameAndSuffixToRootName[name + s] = name;
                }

                // claim the root type
                _rootNameToInfo[name] = new RootMetricInfo {
                    Type = metricType, Unit = unit
                };

                // see if this metric name and tag combination already exists
                var key = metric.GetMetricKey();
                if (_rootNameAndTagsToMetric.ContainsKey(key))
                {
                    if (mustBeNew)
                    {
                        throw new Exception($"Attempted to create duplicate metric with name \"{name}\" and tags {metric.TagsJson}.");
                    }

                    return((T)_rootNameAndTagsToMetric[key]);
                }

                // metric doesn't exist yet.
                _rootNameAndTagsToMetric[key] = metric;
                metric.IsAttached             = true;

                var needsPreSerialize = metric.NeedsPreSerializeCalled();
                if (needsPreSerialize)
                {
                    _metricsNeedingPreSerialize.Add(metric);
                }

                var isExternal = metric.IsExternalCounter();
                if (isExternal)
                {
                    _externalCounterMetrics.Add(metric);
                }
                else
                {
                    _localMetrics.Add(metric);
                }

                if (metric.SerializeInitialValue)
                {
                    MetricWriter writer = null;
                    try
                    {
                        var queue = isExternal ? _externalCounterQueue : _localMetricsQueue;
                        writer = queue.GetWriter();

                        if (needsPreSerialize)
                        {
                            metric.PreSerializeInternal();
                        }

                        metric.SerializeInternal(writer, DateTime.UtcNow);
                    }
                    finally
                    {
                        writer?.EndBatch();
                    }
                }

                return(metric);
            }
        }