Repository: VictoriaMetrics/VictoriaMetrics
Pull request #1387 (2021-06-17 06:24:57)

dasbhoard: display tweaks
* rm cumulative visualisation for panel `Disk space used`.
It uses % threshold and cumulative display breaks it.
* remove area filling for resource usage row;
* add job name for panels in resource usage row.


Patch:
diff --git a/app/vmagent/remotewrite/remotewrite.go b/app/vmagent/remotewrite/remotewrite.go
index c187515b1..29a5ef1ff 100644
--- a/app/vmagent/remotewrite/remotewrite.go
+++ b/app/vmagent/remotewrite/remotewrite.go
@@ -28,7 +28,7 @@ var (
 		"Pass multiple -remoteWrite.url flags in order to write data concurrently to multiple remote storage systems")
 	tmpDataPath = flag.String("remoteWrite.tmpDataPath", "vmagent-remotewrite-data", "Path to directory where temporary data for remote write component is stored. "+
 		"See also -remoteWrite.maxDiskUsagePerURL")
-	queues = flag.Int("remoteWrite.queues", cgroup.AvailableCPUs() * 2, "The number of concurrent queues to each -remoteWrite.url. Set more queues if default number of queues "+
+	queues = flag.Int("remoteWrite.queues", cgroup.AvailableCPUs()*2, "The number of concurrent queues to each -remoteWrite.url. Set more queues if default number of queues "+
 		"isn't enough for sending high volume of collected data to remote storage. Default value if 2 * numberOfAvailableCPUs")
 	showRemoteWriteURL = flag.Bool("remoteWrite.showURL", false, "Whether to show -remoteWrite.url in the exported metrics. "+
 		"It is hidden by default, since it can contain sensitive info such as auth key")
diff --git a/app/vmbackupmanager/README.md b/app/vmbackupmanager/README.md
index c11b32fef..9087e8a89 100644
--- a/app/vmbackupmanager/README.md
+++ b/app/vmbackupmanager/README.md
@@ -1,8 +1,8 @@
 ## vmbackupmanager
 
-VictoriaMetrics backup manager
+***vmbackupmanager is a part of [enterprise package](https://victoriametrics.com/enterprise.html)***
 
-This service automates regular backup procedures. It supports the following backup intervals: **hourly**, **daily**, **weekly** and **monthly**. Multiple backup intervals may be configured simultaneously. I.e. the backup manager creates hourly backups every hour, while it creates daily backups every day, etc. Backup manager must have read access to the storage data, so best practice is to install it on the same machine (or as a sidecar) where the storage node is installed.
+The VictoriaMetrics backup manager automates regular backup procedures. It supports the following backup intervals: **hourly**, **daily**, **weekly** and **monthly**. Multiple backup intervals may be configured simultaneously. I.e. the backup manager creates hourly backups every hour, while it creates daily backups every day, etc. Backup manager must have read access to the storage data, so best practice is to install it on the same machine (or as a sidecar) where the storage node is installed.
 The backup service makes a backup every hour and puts it to the latest folder and then copies data to the folders which represent the backup intervals (hourly, daily, weekly and monthly)
 
 The required flags for running the service are as follows:
@@ -49,7 +49,7 @@ There are two flags which could help with performance tuning:
 * -concurrency - The number of concurrent workers. Higher concurrency may improve upload speed (default 10)
 
 
-### Example of Usage
+## Example of Usage
 
 GCS and cluster version. You need to have a credentials file in json format with following structure
 
diff --git a/app/vmgateway/README.md b/app/vmgateway/README.md
index 31cfedd7a..dfe7fe81b 100644
--- a/app/vmgateway/README.md
+++ b/app/vmgateway/README.md
@@ -1,5 +1,7 @@
 # vmgateway
 
+***vmgateway is a part of [enterprise package](https://victoriametrics.com/enterprise.html)***
+
 
 <img alt="vmgateway" src="vmgateway-overview.jpeg">
 
diff --git a/dashboards/victoriametrics.json b/dashboards/victoriametrics.json
index 8cc414ccf..58d29446d 100644
--- a/dashboards/victoriametrics.json
+++ b/dashboards/victoriametrics.json
@@ -50,7 +50,7 @@
   "gnetId": null,
   "graphTooltip": 0,
   "id": null,
-  "iteration": 1623417312757,
+  "iteration": 1623910135370,
   "links": [
     {
       "icon": "doc",
@@ -812,10 +812,6 @@
     {
       "collapsed": false,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -1463,7 +1459,7 @@
         },
         "overrides": []
       },
-      "fill": 1,
+      "fill": 0,
       "fillGradient": 0,
       "gridPos": {
         "h": 8,
@@ -1499,7 +1495,7 @@
       "renderer": "flot",
       "seriesOverrides": [],
       "spaceLength": 10,
-      "stack": true,
+      "stack": false,
       "steppedLine": false,
       "targets": [
         {
@@ -1514,6 +1510,7 @@
       ],
       "thresholds": [
         {
+          "$$hashKey": "object:89",
           "colorMode": "critical",
           "fill": true,
           "line": true,
@@ -1672,10 +1669,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -1697,13 +1690,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 0,
-            "y": 3
+            "y": 35
           },
           "hiddenSeries": false,
           "id": 66,
@@ -1737,8 +1730,10 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
-              "legendFormat": "{{instance}}",
+              "exemplar": true,
+              "expr": "sum(process_resident_memory_bytes{job=~\"$job\", instance=~\"$instance\"}) by (job, instance)",
+              "interval": "",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -1796,13 +1791,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 12,
-            "y": 3
+            "y": 35
           },
           "hiddenSeries": false,
           "id": 138,
@@ -1837,9 +1832,9 @@
           "targets": [
             {
               "exemplar": true,
-              "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}) by (instance)",
+              "expr": "sum(process_resident_memory_anon_bytes{job=~\"$job\", instance=~\"$instance\"}) by (job, instance)",
               "interval": "",
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -1896,13 +1891,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 0,
-            "y": 11
+            "y": 43
           },
           "hiddenSeries": false,
           "id": 64,
@@ -1936,10 +1931,12 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[5m])) by(instance)",
+              "exemplar": true,
+              "expr": "sum(rate(process_cpu_seconds_total{job=~\"$job\", instance=~\"$instance\"}[5m])) by(job, instance)",
               "format": "time_series",
+              "interval": "",
               "intervalFactor": 1,
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -1997,13 +1994,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 12,
-            "y": 11
+            "y": 43
           },
           "hiddenSeries": false,
           "id": 72,
@@ -2037,10 +2034,12 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(rate(go_gc_duration_seconds_sum{job=~\"$job\", instance=~\"$instance\"}[5m])) by(instance)\n/\nsum(rate(go_gc_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[5m])) by(instance)",
+              "exemplar": true,
+              "expr": "sum(rate(go_gc_duration_seconds_sum{job=~\"$job\", instance=~\"$instance\"}[5m])) by(job, instance)\n/\nsum(rate(go_gc_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[5m])) by(job, instance)",
               "format": "time_series",
+              "interval": "",
               "intervalFactor": 2,
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -2104,7 +2103,7 @@
             "h": 8,
             "w": 12,
             "x": 0,
-            "y": 19
+            "y": 51
           },
           "hiddenSeries": false,
           "id": 117,
@@ -2143,19 +2142,21 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(process_open_fds{job=~\"$job\", instance=~\"$instance\"}) by(instance)",
+              "exemplar": true,
+              "expr": "sum(process_open_fds{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)",
               "format": "time_series",
               "interval": "",
               "intervalFactor": 2,
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             },
             {
-              "expr": "sum(process_max_fds{job=~\"$job\", instance=~\"$instance\"}) by(instance)",
+              "exemplar": true,
+              "expr": "sum(process_max_fds{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)",
               "format": "time_series",
               "interval": "",
               "intervalFactor": 2,
-              "legendFormat": "max ({{instance}})",
+              "legendFormat": "max {{instance}} ({{job}})",
               "refId": "B"
             }
           ],
@@ -2207,13 +2208,13 @@
           "dashLength": 10,
           "dashes": false,
           "datasource": "$ds",
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 12,
-            "y": 19
+            "y": 51
           },
           "hiddenSeries": false,
           "id": 119,
@@ -2246,9 +2247,10 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(vm_tcplistener_conns{job=~\"$job\", instance=~\"$instance\"}) by(job)",
+              "exemplar": true,
+              "expr": "sum(vm_tcplistener_conns{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)",
               "interval": "",
-              "legendFormat": "{{job}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -2305,13 +2307,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 0,
-            "y": 27
+            "y": 59
           },
           "hiddenSeries": false,
           "id": 68,
@@ -2345,10 +2347,12 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(go_goroutines{job=~\"$job\", instance=~\"$instance\"}) by(instance)",
+              "exemplar": true,
+              "expr": "sum(go_goroutines{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)",
               "format": "time_series",
+              "interval": "",
               "intervalFactor": 2,
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -2400,13 +2404,13 @@
           "dashLength": 10,
           "dashes": false,
           "datasource": "$ds",
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 12,
-            "y": 27
+            "y": 59
           },
           "hiddenSeries": false,
           "id": 120,
@@ -2439,9 +2443,10 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(rate(vm_tcplistener_accepts_total{job=~\"$job\", instance=~\"$instance\"}[5m])) by(job)",
+              "exemplar": true,
+              "expr": "sum(rate(vm_tcplistener_accepts_total{job=~\"$job\", instance=~\"$instance\"}[5m])) by(job, instance)",
               "interval": "",
-              "legendFormat": "{{job}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -2498,13 +2503,13 @@
             },
             "overrides": []
           },
-          "fill": 1,
+          "fill": 0,
           "fillGradient": 0,
           "gridPos": {
             "h": 8,
             "w": 12,
             "x": 0,
-            "y": 35
+            "y": 67
           },
           "hiddenSeries": false,
           "id": 70,
@@ -2538,10 +2543,12 @@
           "steppedLine": false,
           "targets": [
             {
-              "expr": "sum(process_num_threads{job=~\"$job\", instance=~\"$instance\"}) by(instance)",
+              "exemplar": true,
+              "expr": "sum(process_num_threads{job=~\"$job\", instance=~\"$instance\"}) by(job, instance)",
               "format": "time_series",
+              "interval": "",
               "intervalFactor": 2,
-              "legendFormat": "{{instance}}",
+              "legendFormat": "{{instance}} ({{job}})",
               "refId": "A"
             }
           ],
@@ -2594,10 +2601,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -3033,10 +3036,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -3689,10 +3688,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -3931,10 +3926,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -5202,10 +5193,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
@@ -5555,10 +5542,6 @@
     {
       "collapsed": true,
       "datasource": "$ds",
-      "fieldConfig": {
-        "defaults": {},
-        "overrides": []
-      },
       "gridPos": {
         "h": 1,
         "w": 24,
diff --git a/docs/vmbackupmanager.md b/docs/vmbackupmanager.md
index 7be66246b..bdda531fe 100644
--- a/docs/vmbackupmanager.md
+++ b/docs/vmbackupmanager.md
@@ -4,9 +4,9 @@ sort: 10
 
 ## vmbackupmanager
 
-VictoriaMetrics backup manager
+***vmbackupmanager is a part of [enterprise package](https://victoriametrics.com/enterprise.html)***
 
-This service automates regular backup procedures. It supports the following backup intervals: **hourly**, **daily**, **weekly** and **monthly**. Multiple backup intervals may be configured simultaneously. I.e. the backup manager creates hourly backups every hour, while it creates daily backups every day, etc. Backup manager must have read access to the storage data, so best practice is to install it on the same machine (or as a sidecar) where the storage node is installed.
+The VictoriaMetrics backup manager automates regular backup procedures. It supports the following backup intervals: **hourly**, **daily**, **weekly** and **monthly**. Multiple backup intervals may be configured simultaneously. I.e. the backup manager creates hourly backups every hour, while it creates daily backups every day, etc. Backup manager must have read access to the storage data, so best practice is to install it on the same machine (or as a sidecar) where the storage node is installed.
 The backup service makes a backup every hour and puts it to the latest folder and then copies data to the folders which represent the backup intervals (hourly, daily, weekly and monthly)
 
 The required flags for running the service are as follows:
@@ -53,7 +53,7 @@ There are two flags which could help with performance tuning:
 * -concurrency - The number of concurrent workers. Higher concurrency may improve upload speed (default 10)
 
 
-### Example of Usage
+## Example of Usage
 
 GCS and cluster version. You need to have a credentials file in json format with following structure
 
diff --git a/docs/vmgateway.md b/docs/vmgateway.md
index 2aacb16d4..d39b7fcfc 100644
--- a/docs/vmgateway.md
+++ b/docs/vmgateway.md
@@ -4,6 +4,8 @@ sort: 9
 
 # vmgateway
 
+***vmgateway is a part of [enterprise package](https://victoriametrics.com/enterprise.html)***
+
 
 <img alt="vmgateway" src="vmgateway-overview.jpeg">
 
diff --git a/lib/mergeset/table.go b/lib/mergeset/table.go
index ba12ada94..00d585cda 100644
--- a/lib/mergeset/table.go
+++ b/lib/mergeset/table.go
@@ -177,7 +177,7 @@ func (ris *rawItemsShard) Len() int {
 
 func (ris *rawItemsShard) addItems(tb *Table, items [][]byte) error {
 	var err error
-	var blocksToMerge []*inmemoryBlock
+	var blocksToFlush []*inmemoryBlock
 
 	ris.mu.Lock()
 	ibs := ris.ibs
@@ -200,19 +200,16 @@ func (ris *rawItemsShard) addItems(tb *Table, items [][]byte) error {
 		}
 	}
 	if len(ibs) >= maxBlocksPerShard {
-		blocksToMerge = ibs
-		ris.ibs = make([]*inmemoryBlock, 0, maxBlocksPerShard)
+		blocksToFlush = append(blocksToFlush, ibs...)
+		for i := range ibs {
+			ibs[i] = nil
+		}
+		ris.ibs = ibs[:0]
 		ris.lastFlushTime = fasttime.UnixTimestamp()
 	}
 	ris.mu.Unlock()
 
-	if blocksToMerge == nil {
-		// Fast path.
-		return err
-	}
-
-	// Slow path: merge blocksToMerge.
-	tb.mergeRawItemsBlocks(blocksToMerge)
+	tb.mergeRawItemsBlocks(blocksToFlush)
 	return err
 }
 
@@ -586,58 +583,65 @@ func (riss *rawItemsShards) flush(tb *Table, isFinal bool) {
 	tb.rawItemsPendingFlushesWG.Add(1)
 	defer tb.rawItemsPendingFlushesWG.Done()
 
-	var wg sync.WaitGroup
-	wg.Add(len(riss.shards))
+	var blocksToFlush []*inmemoryBlock
 	for i := range riss.shards {
-		go func(ris *rawItemsShard) {
-			ris.flush(tb, isFinal)
-			wg.Done()
-		}(&riss.shards[i])
+		blocksToFlush = riss.shards[i].appendBlocksToFlush(blocksToFlush, tb, isFinal)
 	}
-	wg.Wait()
+	tb.mergeRawItemsBlocks(blocksToFlush)
 }
 
-func (ris *rawItemsShard) flush(tb *Table, isFinal bool) {
-	mustFlush := false
+func (ris *rawItemsShard) appendBlocksToFlush(dst []*inmemoryBlock, tb *Table, isFinal bool) []*inmemoryBlock {
 	currentTime := fasttime.UnixTimestamp()
 	flushSeconds := int64(rawItemsFlushInterval.Seconds())
 	if flushSeconds <= 0 {
 		flushSeconds = 1
 	}
-	var blocksToMerge []*inmemoryBlock
 
 	ris.mu.Lock()
 	if isFinal || currentTime-ris.lastFlushTime > uint64(flushSeconds) {
-		mustFlush = true
-		blocksToMerge = ris.ibs
-		ris.ibs = make([]*inmemoryBlock, 0, maxBlocksPerShard)
+		ibs := ris.ibs
+		dst = append(dst, ibs...)
+		for i := range ibs {
+			ibs[i] = nil
+		}
+		ris.ibs = ibs[:0]
 		ris.lastFlushTime = currentTime
 	}
 	ris.mu.Unlock()
 
-	if mustFlush {
-		tb.mergeRawItemsBlocks(blocksToMerge)
-	}
+	return dst
 }
 
-func (tb *Table) mergeRawItemsBlocks(blocksToMerge []*inmemoryBlock) {
+func (tb *Table) mergeRawItemsBlocks(ibs []*inmemoryBlock) {
+	if len(ibs) == 0 {
+		return
+	}
 	tb.partMergersWG.Add(1)
 	defer tb.partMergersWG.Done()
 
-	pws := make([]*partWrapper, 0, (len(blocksToMerge)+defaultPartsToMerge-1)/defaultPartsToMerge)
-	for len(blocksToMerge) > 0 {
+	pws := make([]*partWrapper, 0, (len(ibs)+defaultPartsToMerge-1)/defaultPartsToMerge)
+	var pwsLock sync.Mutex
+	var wg sync.WaitGroup
+	for len(ibs) > 0 {
 		n := defaultPartsToMerge
-		if n > len(blocksToMerge) {
-			n = len(blocksToMerge)
-		}
-		pw := tb.mergeInmemoryBlocks(blocksToMerge[:n])
-		blocksToMerge = blocksToMerge[n:]
-		if pw == nil {
-			continue
+		if n > len(ibs) {
+			n = len(ibs)
 		}
-		pw.isInMerge = true
-		pws = append(pws, pw)
+		wg.Add(1)
+		go func(ibsPart []*inmemoryBlock) {
+			defer wg.Done()
+			pw := tb.mergeInmemoryBlocks(ibsPart)
+			if pw == nil {
+				return
+			}
+			pw.isInMerge = true
+			pwsLock.Lock()
+			pws = append(pws, pw)
+			pwsLock.Unlock()
+		}(ibs[:n])
+		ibs = ibs[n:]
 	}
+	wg.Wait()
 	if len(pws) > 0 {
 		if err := tb.mergeParts(pws, nil, true); err != nil {
 			logger.Panicf("FATAL: cannot merge raw parts: %s", err)
@@ -672,10 +676,10 @@ func (tb *Table) mergeRawItemsBlocks(blocksToMerge []*inmemoryBlock) {
 	}
 }
 
-func (tb *Table) mergeInmemoryBlocks(blocksToMerge []*inmemoryBlock) *partWrapper {
-	// Convert blocksToMerge into inmemoryPart's
-	mps := make([]*inmemoryPart, 0, len(blocksToMerge))
-	for _, ib := range blocksToMerge {
+func (tb *Table) mergeInmemoryBlocks(ibs []*inmemoryBlock) *partWrapper {
+	// Convert ibs into inmemoryPart's
+	mps := make([]*inmemoryPart, 0, len(ibs))
+	for _, ib := range ibs {
 		if len(ib.items) == 0 {
 			continue
 		}
diff --git a/lib/promscrape/discovery/digitalocean/digitalocean.go b/lib/promscrape/discovery/digitalocean/digitalocean.go
index e498f201a..3c68c2b72 100644
--- a/lib/promscrape/discovery/digitalocean/digitalocean.go
+++ b/lib/promscrape/discovery/digitalocean/digitalocean.go
@@ -136,10 +136,10 @@ func addDropletLabels(droplets []droplet, defaultPort int) []map[string]string {
 		}
 		if len(droplet.Features) > 0 {
 			features := fmt.Sprintf(",%s,", strings.Join(droplet.Features, ","))
-			m["__meta_digitalocean_vpc"] = features
+			m["__meta_digitalocean_features"] = features
 		}
 		if len(droplet.Tags) > 0 {
-			tags := fmt.Sprintf(",%s,", strings.Join(droplet.Features, ","))
+			tags := fmt.Sprintf(",%s,", strings.Join(droplet.Tags, ","))
 			m["__meta_digitalocean_tags"] = tags
 		}
 		ms = append(ms, m)
diff --git a/lib/storage/partition.go b/lib/storage/partition.go
index 3288112f2..3b6213d9c 100644
--- a/lib/storage/partition.go
+++ b/lib/storage/partition.go
@@ -4,7 +4,6 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
-	"math/bits"
 	"os"
 	"path/filepath"
 	"sort"
@@ -478,81 +477,49 @@ func (rrs *rawRowsShard) Len() int {
 }
 
 func (rrs *rawRowsShard) addRows(pt *partition, rows []rawRow) {
-	var rrss []*rawRows
+	var rowsToFlush []rawRow
 
 	rrs.mu.Lock()
 	if cap(rrs.rows) == 0 {
-		rrs.rows = getRawRowsMaxSize().rows
+		n := getMaxRawRowsPerShard()
+		rrs.rows = make([]rawRow, 0, n)
 	}
 	maxRowsCount := cap(rrs.rows)
-	for {
-		capacity := maxRowsCount - len(rrs.rows)
-		if capacity >= len(rows) {
-			// Fast path - rows fit capacity.
-			rrs.rows = append(rrs.rows, rows...)
-			break
-		}
-
+	capacity := maxRowsCount - len(rrs.rows)
+	if capacity >= len(rows) {
+		// Fast path - rows fit capacity.
+		rrs.rows = append(rrs.rows, rows...)
+	} else {
 		// Slow path - rows don't fit capacity.
-		// Fill rawRows to capacity and convert it to a part.
-		rrs.rows = append(rrs.rows, rows[:capacity]...)
-		rows = rows[capacity:]
-		rr := getRawRowsMaxSize()
-		rrs.rows, rr.rows = rr.rows, rrs.rows
-		rrss = append(rrss, rr)
+		// Put rrs.rows and rows to rowsToFlush and convert it to a part.
+		rowsToFlush = append(rowsToFlush, rrs.rows...)
+		rowsToFlush = append(rowsToFlush, rows...)
+		rrs.rows = rrs.rows[:0]
 		rrs.lastFlushTime = fasttime.UnixTimestamp()
 	}
 	rrs.mu.Unlock()
 
-	for _, rr := range rrss {
-		pt.addRowsPart(rr.rows)
-		putRawRows(rr)
-	}
+	pt.flushRowsToParts(rowsToFlush)
 }
 
-type rawRows struct {
-	rows []rawRow
-}
-
-func getRawRowsMaxSize() *rawRows {
-	size := getMaxRawRowsPerShard()
-	return getRawRowsWithSize(size)
-}
-
-func getRawRowsWithSize(size int) *rawRows {
-	p, sizeRounded := getRawRowsPool(size)
-	v := p.Get()
-	if v == nil {
-		return &rawRows{
-			rows: make([]rawRow, 0, sizeRounded),
+func (pt *partition) flushRowsToParts(rows []rawRow) {
+	maxRows := getMaxRawRowsPerShard()
+	var wg sync.WaitGroup
+	for len(rows) > 0 {
+		n := maxRows
+		if n > len(rows) {
+			n = len(rows)
 		}
+		wg.Add(1)
+		go func(rowsPart []rawRow) {
+			defer wg.Done()
+			pt.addRowsPart(rowsPart)
+		}(rows[:n])
+		rows = rows[n:]
 	}
-	return v.(*rawRows)
-}
-
-func putRawRows(rr *rawRows) {
-	rr.rows = rr.rows[:0]
-	size := cap(rr.rows)
-	p, _ := getRawRowsPool(size)
-	p.Put(rr)
-}
-
-func getRawRowsPool(size int) (*sync.Pool, int) {
-	size--
-	if size < 0 {
-		size = 0
-	}
-	bucketIdx := 64 - bits.LeadingZeros64(uint64(size))
-	if bucketIdx >= len(rawRowsPools) {
-		bucketIdx = len(rawRowsPools) - 1
-	}
-	p := &rawRowsPools[bucketIdx]
-	sizeRounded := 1 << uint(bucketIdx)
-	return p, sizeRounded
+	wg.Wait()
 }
 
-var rawRowsPools [19]sync.Pool
-
 func (pt *partition) addRowsPart(rows []rawRow) {
 	if len(rows) == 0 {
 		return
@@ -749,19 +716,14 @@ func (pt *partition) flushRawRows(isFinal bool) {
 }
 
 func (rrss *rawRowsShards) flush(pt *partition, isFinal bool) {
-	var wg sync.WaitGroup
-	wg.Add(len(rrss.shards))
+	var rowsToFlush []rawRow
 	for i := range rrss.shards {
-		go func(rrs *rawRowsShard) {
-			rrs.flush(pt, isFinal)
-			wg.Done()
-		}(&rrss.shards[i])
+		rowsToFlush = rrss.shards[i].appendRawRowsToFlush(rowsToFlush, pt, isFinal)
 	}
-	wg.Wait()
+	pt.flushRowsToParts(rowsToFlush)
 }
 
-func (rrs *rawRowsShard) flush(pt *partition, isFinal bool) {
-	var rr *rawRows
+func (rrs *rawRowsShard) appendRawRowsToFlush(dst []rawRow, pt *partition, isFinal bool) []rawRow {
 	currentTime := fasttime.UnixTimestamp()
 	flushSeconds := int64(rawRowsFlushInterval.Seconds())
 	if flushSeconds <= 0 {
@@ -770,15 +732,12 @@ func (rrs *rawRowsShard) flush(pt *partition, isFinal bool) {
 
 	rrs.mu.Lock()
 	if isFinal || currentTime-rrs.lastFlushTime > uint64(flushSeconds) {
-		rr = getRawRowsMaxSize()
-		rrs.rows, rr.rows = rr.rows, rrs.rows
+		dst = append(dst, rrs.rows...)
+		rrs.rows = rrs.rows[:0]
 	}
 	rrs.mu.Unlock()
 
-	if rr != nil {
-		pt.addRowsPart(rr.rows)
-		putRawRows(rr)
-	}
+	return dst
 }
 
 func (pt *partition) startInmemoryPartsFlusher() {


Test patch:
diff --git a/lib/promscrape/discovery/digitalocean/digitalocean_test.go b/lib/promscrape/discovery/digitalocean/digitalocean_test.go
new file mode 100644
index 000000000..ecb177fbf
--- /dev/null
+++ b/lib/promscrape/discovery/digitalocean/digitalocean_test.go
@@ -0,0 +1,98 @@
+package digitalocean
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+)
+
+func Test_addDropletLabels(t *testing.T) {
+	type args struct {
+		droplets    []droplet
+		defaultPort int
+	}
+	tests := []struct {
+		name string
+		args args
+		want [][]prompbmarshal.Label
+	}{
+		{
+			name: "base labels add test",
+			args: args{
+				droplets: []droplet{
+					{
+						ID:     15,
+						Tags:   []string{"private", "test"},
+						Status: "active",
+						Name:   "ubuntu-1",
+						Region: struct {
+							Slug string `json:"slug"`
+						}(struct{ Slug string }{Slug: "do"}),
+						Features: []string{"feature-1", "feature-2"},
+						SizeSlug: "base-1",
+						VpcUUID:  "vpc-1",
+						Image: struct {
+							Name string `json:"name"`
+							Slug string `json:"slug"`
+						}(struct {
+							Name string
+							Slug string
+						}{Name: "ubuntu", Slug: "18"}),
+						Networks: networks{
+							V4: []network{
+								{
+									Type:      "public",
+									IPAddress: "100.100.100.100",
+								},
+								{
+									Type:      "private",
+									IPAddress: "10.10.10.10",
+								},
+							},
+							V6: []network{
+								{
+									Type:      "public",
+									IPAddress: "::1",
+								},
+							},
+						},
+					},
+				},
+				defaultPort: 9100,
+			},
+			want: [][]prompbmarshal.Label{
+				discoveryutils.GetSortedLabels(map[string]string{
+					"__address__":                      "100.100.100.100:9100",
+					"__meta_digitalocean_droplet_id":   "15",
+					"__meta_digitalocean_droplet_name": "ubuntu-1",
+					"__meta_digitalocean_features":     ",feature-1,feature-2,",
+					"__meta_digitalocean_image":        "18",
+					"__meta_digitalocean_image_name":   "ubuntu",
+					"__meta_digitalocean_private_ipv4": "10.10.10.10",
+					"__meta_digitalocean_public_ipv4":  "100.100.100.100",
+					"__meta_digitalocean_public_ipv6":  "::1",
+					"__meta_digitalocean_region":       "do",
+					"__meta_digitalocean_size":         "base-1",
+					"__meta_digitalocean_status":       "active",
+					"__meta_digitalocean_tags":         ",private,test,",
+					"__meta_digitalocean_vpc":          "vpc-1",
+				}),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := addDropletLabels(tt.args.droplets, tt.args.defaultPort)
+			var sortedLabelss [][]prompbmarshal.Label
+			for _, labels := range got {
+				sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
+			}
+			if !reflect.DeepEqual(sortedLabelss, tt.want) {
+				t.Errorf("addTasksLabels() \ngot  \n%v\n, \nwant \n%v\n", sortedLabelss, tt.want)
+			}
+
+		})
+	}
+}