private void ReadMetricsData(BinaryReader reader, IMetricBuilder <TMetadata> metricBuilder, ushort version, int maxMetricStringsLength, int maxMetricNamespaceStringsLength, int maxMetricDimensionValueStringsLength) { long packetTime = 0; if (version >= 5) { packetTime = (long)SerializationUtils.ReadUInt64FromBase128(reader); } // Versions before 2 used variable number of bytes to write number of serialized metrics data. // From version 2 passing IEnumerable<IReadOnlyMetric> is supported, thus number of metrics data // is unknown beforehand and we cannot use variable number anymore. Thus fixed 4 bytes uint is used. var count = version >= 2 ? reader.ReadUInt32() : SerializationUtils.ReadUInt32FromBase128(reader); for (var i = 0; i < count; ++i) { metricBuilder.BeginMetricCreation(); var metadata = this.ReadMetricMetadataByIndex(reader); metricBuilder.AssignMetadata(metadata); // In versions 0-2 Monitoring Account and Metric Namespace was part of the Metric data // From version 3 Monitoring Account is removed and Metric Namespace became a part of Metric Metadata if (version < 3) { var monitoringAccount = this.ReadStringByIndex(reader); if (monitoringAccount.Length > maxMetricStringsLength) { throw new MetricSerializationException($"Monitoring account string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricStringsLength}, Value:{monitoringAccount}.", null); } var metricNamespace = this.ReadStringByIndex(reader); if (metricNamespace.Length > maxMetricNamespaceStringsLength) { throw new MetricSerializationException($"Namespace string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricNamespaceStringsLength}, Value:{metricNamespace}.", null); } metricBuilder.AssignMonitoringAccount(monitoringAccount); metricBuilder.AssignNamespace(metricNamespace); } if (version == 0) { // Skip event id this.ReadStringByIndex(reader); } if (version >= 5) { var timeInTicks = (packetTime - SerializationUtils.ReadInt64FromBase128(reader)) * SerializationUtils.OneMinuteInterval; metricBuilder.AssignTimeUtc(new DateTime(timeInTicks, DateTimeKind.Utc)); } else { metricBuilder.AssignTimeUtc(new DateTime((long)SerializationUtils.ReadUInt64FromBase128(reader), DateTimeKind.Utc)); } for (var j = 0; j < metadata.DimensionsCount; ++j) { var dimensionValue = this.ReadStringByIndex(reader); if (dimensionValue.Length > maxMetricDimensionValueStringsLength) { throw new MetricSerializationException($"Dimension value string in the packet exceeds preconfigured length. Packet is corrupted. MaxLength:{maxMetricDimensionValueStringsLength}, Value:{dimensionValue}.", null); } metricBuilder.AddDimensionValue(dimensionValue); } var samplingTypes = (SamplingTypes)SerializationUtils.ReadUInt32FromBase128(reader); metricBuilder.AssignSamplingTypes(samplingTypes); if ((samplingTypes & SamplingTypes.Min) != 0) { metricBuilder.AssignMin(SerializationUtils.ReadUInt64FromBase128(reader)); } if ((samplingTypes & SamplingTypes.Max) != 0) { metricBuilder.AssignMax(SerializationUtils.ReadUInt64FromBase128(reader)); } if ((samplingTypes & SamplingTypes.Sum) != 0) { metricBuilder.AssignSum(SerializationUtils.ReadUInt64FromBase128(reader)); } if ((samplingTypes & SamplingTypes.Count) != 0) { metricBuilder.AssignCount(SerializationUtils.ReadUInt32FromBase128(reader)); } if ((samplingTypes & SamplingTypes.SumOfSquareDiffFromMean) != 0) { var sumOfSquareDiffFromMean = reader.ReadDouble(); metricBuilder.AssignSumOfSquareDiffFromMean(sumOfSquareDiffFromMean); } if ((samplingTypes & SamplingTypes.Histogram) != 0) { metricBuilder.AssignHistogram(this.ReadHistogram(reader, version)); } if ((samplingTypes & SamplingTypes.HyperLogLogSketch) != 0) { var sizeOfHyperLogLogSketches = reader.ReadInt32(); metricBuilder.AssignHyperLogLogSketch(reader, sizeOfHyperLogLogSketches); } metricBuilder.EndMetricCreation(); } }