| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | // Copyright 2016 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 17:55:07 +08:00
										 |  |  | package scrape | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	"bufio" | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	"compress/gzip" | 
					
						
							| 
									
										
										
										
											2017-10-25 12:21:42 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2019-04-18 16:50:37 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	"unsafe" | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-12 02:45:52 +08:00
										 |  |  | 	"github.com/go-kit/kit/log" | 
					
						
							|  |  |  | 	"github.com/go-kit/kit/log/level" | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2018-04-26 01:19:06 +08:00
										 |  |  | 	config_util "github.com/prometheus/common/config" | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	"github.com/prometheus/common/model" | 
					
						
							| 
									
										
										
										
											2017-02-28 21:59:33 +08:00
										 |  |  | 	"github.com/prometheus/common/version" | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 18:56:09 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/config" | 
					
						
							| 
									
										
											  
											
												Refactor SD configuration to remove `config` dependency (#3629)
* refactor: move targetGroup struct and CheckOverflow() to their own package
* refactor: move auth and security related structs to a utility package, fix import error in utility package
* refactor: Azure SD, remove SD struct from config
* refactor: DNS SD, remove SD struct from config into dns package
* refactor: ec2 SD, move SD struct from config into the ec2 package
* refactor: file SD, move SD struct from config to file discovery package
* refactor: gce, move SD struct from config to gce discovery package
* refactor: move HTTPClientConfig and URL into util/config, fix import error in httputil
* refactor: consul, move SD struct from config into consul discovery package
* refactor: marathon, move SD struct from config into marathon discovery package
* refactor: triton, move SD struct from config to triton discovery package, fix test
* refactor: zookeeper, move SD structs from config to zookeeper discovery package
* refactor: openstack, remove SD struct from config, move into openstack discovery package
* refactor: kubernetes, move SD struct from config into kubernetes discovery package
* refactor: notifier, use targetgroup package instead of config
* refactor: tests for file, marathon, triton SD - use targetgroup package instead of config.TargetGroup
* refactor: retrieval, use targetgroup package instead of config.TargetGroup
* refactor: storage, use config util package
* refactor: discovery manager, use targetgroup package instead of config.TargetGroup
* refactor: use HTTPClient and TLS config from configUtil instead of config
* refactor: tests, use targetgroup package instead of config.TargetGroup
* refactor: fix tagetgroup.Group pointers that were removed by mistake
* refactor: openstack, kubernetes: drop prefixes
* refactor: remove import aliases forced due to vscode bug
* refactor: move main SD struct out of config into discovery/config
* refactor: rename configUtil to config_util
* refactor: rename yamlUtil to yaml_config
* refactor: kubernetes, remove prefixes
* refactor: move the TargetGroup package to discovery/
* refactor: fix order of imports
											
										 
											2017-12-30 04:01:34 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/discovery/targetgroup" | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/labels" | 
					
						
							| 
									
										
										
										
											2017-09-07 20:43:21 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/pool" | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/relabel" | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/textparse" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/pkg/timestamp" | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/value" | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/storage" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-25 21:44:47 +08:00
										 |  |  | // Temporary tolerance for scrape appends timestamps alignment, to enable better
 | 
					
						
							|  |  |  | // compression at the TSDB level.
 | 
					
						
							|  |  |  | // See https://github.com/prometheus/prometheus/issues/7846
 | 
					
						
							| 
									
										
										
										
											2020-10-08 00:25:52 +08:00
										 |  |  | const scrapeTimestampTolerance = 2 * time.Millisecond | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 03:44:36 +08:00
										 |  |  | // AlignScrapeTimestamps enables the tolerance for scrape appends timestamps described above.
 | 
					
						
							| 
									
										
										
										
											2020-10-08 00:25:52 +08:00
										 |  |  | var AlignScrapeTimestamps = true | 
					
						
							| 
									
										
										
										
											2020-09-25 21:44:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 15:18:05 +08:00
										 |  |  | var errNameLabelMandatory = fmt.Errorf("missing metric name (%s label)", labels.MetricName) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	targetIntervalLength = prometheus.NewSummaryVec( | 
					
						
							|  |  |  | 		prometheus.SummaryOpts{ | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 			Name:       "prometheus_target_interval_length_seconds", | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 			Help:       "Actual intervals between scrapes.", | 
					
						
							|  |  |  | 			Objectives: map[float64]float64{0.01: 0.001, 0.05: 0.005, 0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 		[]string{"interval"}, | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 	targetReloadIntervalLength = prometheus.NewSummaryVec( | 
					
						
							|  |  |  | 		prometheus.SummaryOpts{ | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 			Name:       "prometheus_target_reload_length_seconds", | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 			Help:       "Actual interval to reload the scrape pool with a given configuration.", | 
					
						
							|  |  |  | 			Objectives: map[float64]float64{0.01: 0.001, 0.05: 0.005, 0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 		[]string{"interval"}, | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	targetScrapePools = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pools_total", | 
					
						
							| 
									
										
										
										
											2019-07-30 00:08:54 +08:00
										 |  |  | 			Help: "Total number of scrape pool creation attempts.", | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolsFailed = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pools_failed_total", | 
					
						
							|  |  |  | 			Help: "Total number of scrape pool creations that failed.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolReloads = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pool_reloads_total", | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			Help: "Total number of scrape pool reloads.", | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolReloadsFailed = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pool_reloads_failed_total", | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			Help: "Total number of failed scrape pool reloads.", | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	targetScrapePoolExceededTargetLimit = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pool_exceeded_target_limit_total", | 
					
						
							|  |  |  | 			Help: "Total number of times scrape pools hit the target limit, during sync or config reload.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolTargetLimit = prometheus.NewGaugeVec( | 
					
						
							|  |  |  | 		prometheus.GaugeOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pool_target_limit", | 
					
						
							|  |  |  | 			Help: "Maximum number of targets allowed in this scrape pool.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		[]string{"scrape_job"}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolTargetsAdded = prometheus.NewGaugeVec( | 
					
						
							|  |  |  | 		prometheus.GaugeOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrape_pool_targets", | 
					
						
							|  |  |  | 			Help: "Current number of targets in this scrape pool.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		[]string{"scrape_job"}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-03-11 19:22:23 +08:00
										 |  |  | 	targetSyncIntervalLength = prometheus.NewSummaryVec( | 
					
						
							|  |  |  | 		prometheus.SummaryOpts{ | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 			Name:       "prometheus_target_sync_length_seconds", | 
					
						
							| 
									
										
										
										
											2016-03-11 19:22:23 +08:00
										 |  |  | 			Help:       "Actual interval to sync the scrape pool.", | 
					
						
							|  |  |  | 			Objectives: map[float64]float64{0.01: 0.001, 0.05: 0.005, 0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 		[]string{"scrape_job"}, | 
					
						
							| 
									
										
										
										
											2016-03-11 19:22:23 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolSyncsCounter = prometheus.NewCounterVec( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 			Name: "prometheus_target_scrape_pool_sync_total", | 
					
						
							|  |  |  | 			Help: "Total number of syncs that were executed on a scrape pool.", | 
					
						
							| 
									
										
										
										
											2016-03-11 19:22:23 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-11-23 16:17:04 +08:00
										 |  |  | 		[]string{"scrape_job"}, | 
					
						
							| 
									
										
										
										
											2016-03-11 19:22:23 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-12-16 23:08:50 +08:00
										 |  |  | 	targetScrapeSampleLimit = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrapes_exceeded_sample_limit_total", | 
					
						
							|  |  |  | 			Help: "Total number of scrapes that hit the sample limit and were rejected.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2017-08-02 20:10:18 +08:00
										 |  |  | 	targetScrapeSampleDuplicate = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrapes_sample_duplicate_timestamp_total", | 
					
						
							|  |  |  | 			Help: "Total number of samples rejected due to duplicate timestamps but different values", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapeSampleOutOfOrder = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrapes_sample_out_of_order_total", | 
					
						
							|  |  |  | 			Help: "Total number of samples rejected due to not being out of the expected order", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapeSampleOutOfBounds = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrapes_sample_out_of_bounds_total", | 
					
						
							|  |  |  | 			Help: "Total number of samples rejected due to timestamp falling outside of the time bounds", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-03-29 01:52:46 +08:00
										 |  |  | 	targetScrapeCacheFlushForced = prometheus.NewCounter( | 
					
						
							|  |  |  | 		prometheus.CounterOpts{ | 
					
						
							|  |  |  | 			Name: "prometheus_target_scrapes_cache_flush_forced_total", | 
					
						
							|  |  |  | 			Help: "How many times a scrape cache was flushed due to getting big while scrapes are failing.", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2020-01-29 19:13:18 +08:00
										 |  |  | 	prometheus.MustRegister( | 
					
						
							|  |  |  | 		targetIntervalLength, | 
					
						
							|  |  |  | 		targetReloadIntervalLength, | 
					
						
							|  |  |  | 		targetScrapePools, | 
					
						
							|  |  |  | 		targetScrapePoolsFailed, | 
					
						
							|  |  |  | 		targetScrapePoolReloads, | 
					
						
							|  |  |  | 		targetScrapePoolReloadsFailed, | 
					
						
							|  |  |  | 		targetSyncIntervalLength, | 
					
						
							|  |  |  | 		targetScrapePoolSyncsCounter, | 
					
						
							|  |  |  | 		targetScrapeSampleLimit, | 
					
						
							|  |  |  | 		targetScrapeSampleDuplicate, | 
					
						
							|  |  |  | 		targetScrapeSampleOutOfOrder, | 
					
						
							|  |  |  | 		targetScrapeSampleOutOfBounds, | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		targetScrapePoolExceededTargetLimit, | 
					
						
							|  |  |  | 		targetScrapePoolTargetLimit, | 
					
						
							|  |  |  | 		targetScrapePoolTargetsAdded, | 
					
						
							| 
									
										
										
										
											2020-01-29 19:13:18 +08:00
										 |  |  | 		targetScrapeCacheFlushForced, | 
					
						
							|  |  |  | 		targetMetadataCache, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | // scrapePool manages scrapes for sets of targets.
 | 
					
						
							|  |  |  | type scrapePool struct { | 
					
						
							| 
									
										
										
										
											2020-02-06 23:58:38 +08:00
										 |  |  | 	appendable storage.Appendable | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	logger     log.Logger | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	cancel     context.CancelFunc | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	// mtx must not be taken after targetMtx.
 | 
					
						
							|  |  |  | 	mtx            sync.Mutex | 
					
						
							|  |  |  | 	config         *config.ScrapeConfig | 
					
						
							|  |  |  | 	client         *http.Client | 
					
						
							|  |  |  | 	loops          map[uint64]loop | 
					
						
							|  |  |  | 	targetLimitHit bool // Internal state to speed up the target_limit checks.
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	targetMtx sync.Mutex | 
					
						
							|  |  |  | 	// activeTargets and loops must always be synchronized to have the same
 | 
					
						
							| 
									
										
										
										
											2016-02-29 02:56:18 +08:00
										 |  |  | 	// set of hashes.
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 	activeTargets  map[uint64]*Target | 
					
						
							| 
									
										
										
										
											2017-12-04 23:12:28 +08:00
										 |  |  | 	droppedTargets []*Target | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Constructor for new scrape loops. This is settable for testing convenience.
 | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 	newLoop func(scrapeLoopOptions) loop | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type scrapeLoopOptions struct { | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 	target          *Target | 
					
						
							|  |  |  | 	scraper         scraper | 
					
						
							|  |  |  | 	limit           int | 
					
						
							|  |  |  | 	honorLabels     bool | 
					
						
							|  |  |  | 	honorTimestamps bool | 
					
						
							|  |  |  | 	mrc             []*relabel.Config | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 	cache           *scrapeCache | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | const maxAheadTime = 10 * time.Minute | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type labelsMutator func(labels.Labels) labels.Labels | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:58:38 +08:00
										 |  |  | func newScrapePool(cfg *config.ScrapeConfig, app storage.Appendable, jitterSeed uint64, logger log.Logger) (*scrapePool, error) { | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	targetScrapePools.Inc() | 
					
						
							| 
									
										
										
										
											2017-09-16 01:45:27 +08:00
										 |  |  | 	if logger == nil { | 
					
						
							|  |  |  | 		logger = log.NewNopLogger() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-20 20:48:26 +08:00
										 |  |  | 	client, err := config_util.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName, false, false) | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 		targetScrapePoolsFailed.Inc() | 
					
						
							|  |  |  | 		return nil, errors.Wrap(err, "error creating HTTP client") | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-15 10:15:35 +08:00
										 |  |  | 	buffers := pool.New(1e3, 100e6, 3, func(sz int) interface{} { return make([]byte, 0, sz) }) | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-04 01:14:08 +08:00
										 |  |  | 	ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	sp := &scrapePool{ | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 		cancel:        cancel, | 
					
						
							|  |  |  | 		appendable:    app, | 
					
						
							|  |  |  | 		config:        cfg, | 
					
						
							|  |  |  | 		client:        client, | 
					
						
							|  |  |  | 		activeTargets: map[uint64]*Target{}, | 
					
						
							|  |  |  | 		loops:         map[uint64]loop{}, | 
					
						
							|  |  |  | 		logger:        logger, | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 	sp.newLoop = func(opts scrapeLoopOptions) loop { | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		// Update the targets retrieval function for metadata to a new scrape cache.
 | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 		cache := opts.cache | 
					
						
							|  |  |  | 		if cache == nil { | 
					
						
							|  |  |  | 			cache = newScrapeCache() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-04 23:18:27 +08:00
										 |  |  | 		opts.target.SetMetadataStore(cache) | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 23:15:15 +08:00
										 |  |  | 		return newScrapeLoop( | 
					
						
							| 
									
										
										
										
											2017-12-04 01:14:08 +08:00
										 |  |  | 			ctx, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			opts.scraper, | 
					
						
							|  |  |  | 			log.With(logger, "target", opts.target), | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 			buffers, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			func(l labels.Labels) labels.Labels { | 
					
						
							|  |  |  | 				return mutateSampleLabels(l, opts.target, opts.honorLabels, opts.mrc) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			func(l labels.Labels) labels.Labels { return mutateReportSampleLabels(l, opts.target) }, | 
					
						
							| 
									
										
										
										
											2020-07-24 22:10:51 +08:00
										 |  |  | 			func(ctx context.Context) storage.Appender { return appender(app.Appender(ctx), opts.limit) }, | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 			cache, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:46:15 +08:00
										 |  |  | 			jitterSeed, | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 			opts.honorTimestamps, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	return sp, nil | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | func (sp *scrapePool) ActiveTargets() []*Target { | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							|  |  |  | 	defer sp.targetMtx.Unlock() | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var tActive []*Target | 
					
						
							|  |  |  | 	for _, t := range sp.activeTargets { | 
					
						
							|  |  |  | 		tActive = append(tActive, t) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tActive | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (sp *scrapePool) DroppedTargets() []*Target { | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							|  |  |  | 	defer sp.targetMtx.Unlock() | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 	return sp.droppedTargets | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | // stop terminates all scrape loops and returns after they all terminated.
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | func (sp *scrapePool) stop() { | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	sp.mtx.Lock() | 
					
						
							|  |  |  | 	defer sp.mtx.Unlock() | 
					
						
							| 
									
										
										
										
											2017-12-04 01:14:08 +08:00
										 |  |  | 	sp.cancel() | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 	for fp, l := range sp.loops { | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		wg.Add(1) | 
					
						
							| 
									
										
										
										
											2016-02-18 02:33:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		go func(l loop) { | 
					
						
							|  |  |  | 			l.stop() | 
					
						
							|  |  |  | 			wg.Done() | 
					
						
							|  |  |  | 		}(l) | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		delete(sp.loops, fp) | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 		delete(sp.activeTargets, fp) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sp.targetMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	wg.Wait() | 
					
						
							| 
									
										
										
										
											2019-04-10 20:20:00 +08:00
										 |  |  | 	sp.client.CloseIdleConnections() | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if sp.config != nil { | 
					
						
							|  |  |  | 		targetScrapePoolSyncsCounter.DeleteLabelValues(sp.config.JobName) | 
					
						
							|  |  |  | 		targetScrapePoolTargetLimit.DeleteLabelValues(sp.config.JobName) | 
					
						
							|  |  |  | 		targetScrapePoolTargetsAdded.DeleteLabelValues(sp.config.JobName) | 
					
						
							|  |  |  | 		targetSyncIntervalLength.DeleteLabelValues(sp.config.JobName) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | // reload the scrape pool with the given scrape configuration. The target state is preserved
 | 
					
						
							|  |  |  | // but all scrape loops are restarted with the new scrape configuration.
 | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | // This method returns after all scrape loops that were stopped have stopped scraping.
 | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | func (sp *scrapePool) reload(cfg *config.ScrapeConfig) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	sp.mtx.Lock() | 
					
						
							|  |  |  | 	defer sp.mtx.Unlock() | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	targetScrapePoolReloads.Inc() | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 	start := time.Now() | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-20 20:48:26 +08:00
										 |  |  | 	client, err := config_util.NewClientFromConfig(cfg.HTTPClientConfig, cfg.JobName, false, false) | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 		targetScrapePoolReloadsFailed.Inc() | 
					
						
							|  |  |  | 		return errors.Wrap(err, "error creating HTTP client") | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	reuseCache := reusableCache(sp.config, cfg) | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 	sp.config = cfg | 
					
						
							| 
									
										
										
										
											2019-04-10 20:20:00 +08:00
										 |  |  | 	oldClient := sp.client | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	sp.client = client | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	targetScrapePoolTargetLimit.WithLabelValues(sp.config.JobName).Set(float64(sp.config.TargetLimit)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 		wg              sync.WaitGroup | 
					
						
							|  |  |  | 		interval        = time.Duration(sp.config.ScrapeInterval) | 
					
						
							|  |  |  | 		timeout         = time.Duration(sp.config.ScrapeTimeout) | 
					
						
							|  |  |  | 		limit           = int(sp.config.SampleLimit) | 
					
						
							|  |  |  | 		honorLabels     = sp.config.HonorLabels | 
					
						
							|  |  |  | 		honorTimestamps = sp.config.HonorTimestamps | 
					
						
							|  |  |  | 		mrc             = sp.config.MetricRelabelConfigs | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	forcedErr := sp.refreshTargetLimitErr() | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	for fp, oldLoop := range sp.loops { | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 		var cache *scrapeCache | 
					
						
							|  |  |  | 		if oc := oldLoop.getCache(); reuseCache && oc != nil { | 
					
						
							| 
									
										
										
										
											2020-03-21 00:43:26 +08:00
										 |  |  | 			oldLoop.disableEndOfRunStalenessMarkers() | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 			cache = oc | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			cache = newScrapeCache() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		var ( | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 			t       = sp.activeTargets[fp] | 
					
						
							| 
									
										
										
										
											2017-04-27 16:19:55 +08:00
										 |  |  | 			s       = &targetScraper{Target: t, client: sp.client, timeout: timeout} | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			newLoop = sp.newLoop(scrapeLoopOptions{ | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 				target:          t, | 
					
						
							|  |  |  | 				scraper:         s, | 
					
						
							|  |  |  | 				limit:           limit, | 
					
						
							|  |  |  | 				honorLabels:     honorLabels, | 
					
						
							|  |  |  | 				honorTimestamps: honorTimestamps, | 
					
						
							|  |  |  | 				mrc:             mrc, | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 				cache:           cache, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		) | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		go func(oldLoop, newLoop loop) { | 
					
						
							|  |  |  | 			oldLoop.stop() | 
					
						
							|  |  |  | 			wg.Done() | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			newLoop.setForcedError(forcedErr) | 
					
						
							| 
									
										
										
										
											2020-09-02 23:26:42 +08:00
										 |  |  | 			newLoop.run(interval, timeout, nil) | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 		}(oldLoop, newLoop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sp.loops[fp] = newLoop | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | 	wg.Wait() | 
					
						
							| 
									
										
										
										
											2019-04-10 20:20:00 +08:00
										 |  |  | 	oldClient.CloseIdleConnections() | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 	targetReloadIntervalLength.WithLabelValues(interval.String()).Observe( | 
					
						
							| 
									
										
										
										
											2016-07-07 21:24:35 +08:00
										 |  |  | 		time.Since(start).Seconds(), | 
					
						
							| 
									
										
										
										
											2016-03-09 23:33:10 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-02-13 21:24:22 +08:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2016-02-23 20:34:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | // Sync converts target groups into actual scrape targets and synchronizes
 | 
					
						
							| 
									
										
										
										
											2018-04-09 22:18:25 +08:00
										 |  |  | // the currently running scraper with the resulting set and returns all scraped and dropped targets.
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | func (sp *scrapePool) Sync(tgs []*targetgroup.Group) { | 
					
						
							| 
									
										
										
										
											2020-11-13 00:06:25 +08:00
										 |  |  | 	sp.mtx.Lock() | 
					
						
							|  |  |  | 	defer sp.mtx.Unlock() | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 	start := time.Now() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 	var all []*Target | 
					
						
							| 
									
										
										
										
											2018-01-04 22:13:31 +08:00
										 |  |  | 	sp.droppedTargets = []*Target{} | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 	for _, tg := range tgs { | 
					
						
							|  |  |  | 		targets, err := targetsFromGroup(tg, sp.config) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-08-12 02:45:52 +08:00
										 |  |  | 			level.Error(sp.logger).Log("msg", "creating targets failed", "err", err) | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-12-04 23:12:28 +08:00
										 |  |  | 		for _, t := range targets { | 
					
						
							|  |  |  | 			if t.Labels().Len() > 0 { | 
					
						
							|  |  |  | 				all = append(all, t) | 
					
						
							|  |  |  | 			} else if t.DiscoveredLabels().Len() > 0 { | 
					
						
							|  |  |  | 				sp.droppedTargets = append(sp.droppedTargets, t) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Unlock() | 
					
						
							| 
									
										
										
										
											2016-11-22 19:48:30 +08:00
										 |  |  | 	sp.sync(all) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	targetSyncIntervalLength.WithLabelValues(sp.config.JobName).Observe( | 
					
						
							|  |  |  | 		time.Since(start).Seconds(), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	targetScrapePoolSyncsCounter.WithLabelValues(sp.config.JobName).Inc() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | // sync takes a list of potentially duplicated targets, deduplicates them, starts
 | 
					
						
							|  |  |  | // scrape loops for new targets, and stops scrape loops for disappeared targets.
 | 
					
						
							|  |  |  | // It returns after all stopped scrape loops terminated.
 | 
					
						
							|  |  |  | func (sp *scrapePool) sync(targets []*Target) { | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		uniqueLoops     = make(map[uint64]loop) | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 		interval        = time.Duration(sp.config.ScrapeInterval) | 
					
						
							|  |  |  | 		timeout         = time.Duration(sp.config.ScrapeTimeout) | 
					
						
							|  |  |  | 		limit           = int(sp.config.SampleLimit) | 
					
						
							|  |  |  | 		honorLabels     = sp.config.HonorLabels | 
					
						
							|  |  |  | 		honorTimestamps = sp.config.HonorTimestamps | 
					
						
							|  |  |  | 		mrc             = sp.config.MetricRelabelConfigs | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Lock() | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	for _, t := range targets { | 
					
						
							| 
									
										
										
										
											2016-02-29 02:56:18 +08:00
										 |  |  | 		hash := t.hash() | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 		if _, ok := sp.activeTargets[hash]; !ok { | 
					
						
							| 
									
										
										
										
											2017-04-27 16:19:55 +08:00
										 |  |  | 			s := &targetScraper{Target: t, client: sp.client, timeout: timeout} | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			l := sp.newLoop(scrapeLoopOptions{ | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 				target:          t, | 
					
						
							|  |  |  | 				scraper:         s, | 
					
						
							|  |  |  | 				limit:           limit, | 
					
						
							|  |  |  | 				honorLabels:     honorLabels, | 
					
						
							|  |  |  | 				honorTimestamps: honorTimestamps, | 
					
						
							|  |  |  | 				mrc:             mrc, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:26:18 +08:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 			sp.activeTargets[hash] = t | 
					
						
							| 
									
										
										
										
											2016-02-29 02:56:18 +08:00
										 |  |  | 			sp.loops[hash] = l | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			uniqueLoops[hash] = l | 
					
						
							| 
									
										
										
										
											2018-02-07 18:29:27 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			// This might be a duplicated target.
 | 
					
						
							|  |  |  | 			if _, ok := uniqueLoops[hash]; !ok { | 
					
						
							|  |  |  | 				uniqueLoops[hash] = nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-02-07 18:29:27 +08:00
										 |  |  | 			// Need to keep the most updated labels information
 | 
					
						
							|  |  |  | 			// for displaying it in the Service Discovery web page.
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 			sp.activeTargets[hash].SetDiscoveredLabels(t.DiscoveredLabels()) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	var wg sync.WaitGroup | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 	// Stop and remove old targets and scraper loops.
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 	for hash := range sp.activeTargets { | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		if _, ok := uniqueLoops[hash]; !ok { | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 			wg.Add(1) | 
					
						
							|  |  |  | 			go func(l loop) { | 
					
						
							|  |  |  | 				l.stop() | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 				wg.Done() | 
					
						
							| 
									
										
										
										
											2016-02-29 02:56:18 +08:00
										 |  |  | 			}(sp.loops[hash]) | 
					
						
							| 
									
										
										
										
											2016-02-23 21:37:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 02:56:18 +08:00
										 |  |  | 			delete(sp.loops, hash) | 
					
						
							| 
									
										
										
										
											2018-09-26 17:20:56 +08:00
										 |  |  | 			delete(sp.activeTargets, hash) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-26 22:46:20 +08:00
										 |  |  | 	sp.targetMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	targetScrapePoolTargetsAdded.WithLabelValues(sp.config.JobName).Set(float64(len(uniqueLoops))) | 
					
						
							|  |  |  | 	forcedErr := sp.refreshTargetLimitErr() | 
					
						
							|  |  |  | 	for _, l := range sp.loops { | 
					
						
							|  |  |  | 		l.setForcedError(forcedErr) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, l := range uniqueLoops { | 
					
						
							|  |  |  | 		if l != nil { | 
					
						
							|  |  |  | 			go l.run(interval, timeout, nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	// Wait for all potentially stopped scrapers to terminate.
 | 
					
						
							|  |  |  | 	// This covers the case of flapping targets. If the server is under high load, a new scraper
 | 
					
						
							|  |  |  | 	// may be active and tries to insert. The old scraper that didn't terminate yet could still
 | 
					
						
							|  |  |  | 	// be inserting a previous sample set.
 | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | // refreshTargetLimitErr returns an error that can be passed to the scrape loops
 | 
					
						
							|  |  |  | // if the number of targets exceeds the configured limit.
 | 
					
						
							|  |  |  | func (sp *scrapePool) refreshTargetLimitErr() error { | 
					
						
							|  |  |  | 	if sp.config == nil || sp.config.TargetLimit == 0 && !sp.targetLimitHit { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	l := len(sp.activeTargets) | 
					
						
							|  |  |  | 	if l <= int(sp.config.TargetLimit) && !sp.targetLimitHit { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	sp.targetLimitHit = l > int(sp.config.TargetLimit) | 
					
						
							|  |  |  | 	if sp.targetLimitHit { | 
					
						
							|  |  |  | 		targetScrapePoolExceededTargetLimit.Inc() | 
					
						
							|  |  |  | 		err = fmt.Errorf("target_limit exceeded (number of targets: %d, limit: %d)", l, sp.config.TargetLimit) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-18 19:26:36 +08:00
										 |  |  | func mutateSampleLabels(lset labels.Labels, target *Target, honor bool, rc []*relabel.Config) labels.Labels { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	lb := labels.NewBuilder(lset) | 
					
						
							| 
									
										
										
										
											2017-01-31 00:30:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | 	if honor { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		for _, l := range target.Labels() { | 
					
						
							| 
									
										
										
										
											2018-02-15 01:03:58 +08:00
										 |  |  | 			if !lset.Has(l.Name) { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 				lb.Set(l.Name, l.Value) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-07-04 20:55:33 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		for _, l := range target.Labels() { | 
					
						
							| 
									
										
										
										
											2019-08-13 18:19:17 +08:00
										 |  |  | 			// existingValue will be empty if l.Name doesn't exist.
 | 
					
						
							|  |  |  | 			existingValue := lset.Get(l.Name) | 
					
						
							| 
									
										
										
										
											2019-11-20 23:50:05 +08:00
										 |  |  | 			if existingValue != "" { | 
					
						
							|  |  |  | 				lb.Set(model.ExportedLabelPrefix+l.Name, existingValue) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-13 18:19:17 +08:00
										 |  |  | 			// It is now safe to set the target label.
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 			lb.Set(l.Name, l.Value) | 
					
						
							| 
									
										
										
										
											2017-01-31 00:30:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	res := lb.Labels() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | 	if len(rc) > 0 { | 
					
						
							|  |  |  | 		res = relabel.Process(res, rc...) | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | func mutateReportSampleLabels(lset labels.Labels, target *Target) labels.Labels { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	lb := labels.NewBuilder(lset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, l := range target.Labels() { | 
					
						
							| 
									
										
										
										
											2019-08-13 18:19:17 +08:00
										 |  |  | 		lb.Set(model.ExportedLabelPrefix+l.Name, lset.Get(l.Name)) | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		lb.Set(l.Name, l.Value) | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return lb.Labels() | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | // appender returns an appender for ingested samples from the target.
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | func appender(app storage.Appender, limit int) storage.Appender { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	app = &timeLimitAppender{ | 
					
						
							| 
									
										
										
										
											2016-12-31 04:35:35 +08:00
										 |  |  | 		Appender: app, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		maxTime:  timestamp.FromTime(time.Now().Add(maxAheadTime)), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The limit is applied after metrics are potentially dropped via relabeling.
 | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | 	if limit > 0 { | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		app = &limitAppender{ | 
					
						
							|  |  |  | 			Appender: app, | 
					
						
							| 
									
										
										
										
											2018-04-12 22:54:53 +08:00
										 |  |  | 			limit:    limit, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	return app | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-25 20:58:46 +08:00
										 |  |  | // A scraper retrieves samples and accepts a status report at the end.
 | 
					
						
							|  |  |  | type scraper interface { | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 	scrape(ctx context.Context, w io.Writer) (string, error) | 
					
						
							| 
									
										
										
										
											2019-11-12 05:42:24 +08:00
										 |  |  | 	Report(start time.Time, dur time.Duration, err error) | 
					
						
							| 
									
										
										
										
											2019-03-12 18:46:15 +08:00
										 |  |  | 	offset(interval time.Duration, jitterSeed uint64) time.Duration | 
					
						
							| 
									
										
										
										
											2016-02-25 20:58:46 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | // targetScraper implements the scraper interface for a target.
 | 
					
						
							|  |  |  | type targetScraper struct { | 
					
						
							|  |  |  | 	*Target | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-05 01:26:28 +08:00
										 |  |  | 	client  *http.Client | 
					
						
							| 
									
										
										
										
											2017-04-27 16:19:55 +08:00
										 |  |  | 	req     *http.Request | 
					
						
							| 
									
										
										
										
											2017-04-05 01:26:28 +08:00
										 |  |  | 	timeout time.Duration | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	gzipr *gzip.Reader | 
					
						
							|  |  |  | 	buf   *bufio.Reader | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | const acceptHeader = `application/openmetrics-text; version=0.0.1,text/plain;version=0.0.4;q=0.5,*/*;q=0.1` | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 21:59:33 +08:00
										 |  |  | var userAgentHeader = fmt.Sprintf("Prometheus/%s", version.Version) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) { | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	if s.req == nil { | 
					
						
							|  |  |  | 		req, err := http.NewRequest("GET", s.URL().String(), nil) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 			return "", err | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-23 00:06:43 +08:00
										 |  |  | 		req.Header.Add("Accept", acceptHeader) | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 		req.Header.Add("Accept-Encoding", "gzip") | 
					
						
							| 
									
										
										
										
											2017-03-17 23:27:07 +08:00
										 |  |  | 		req.Header.Set("User-Agent", userAgentHeader) | 
					
						
							| 
									
										
										
										
											2017-04-27 16:19:55 +08:00
										 |  |  | 		req.Header.Set("X-Prometheus-Scrape-Timeout-Seconds", fmt.Sprintf("%f", s.timeout.Seconds())) | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		s.req = req | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-09 22:30:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-19 19:31:16 +08:00
										 |  |  | 	resp, err := s.client.Do(s.req.WithContext(ctx)) | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 		return "", err | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-18 16:50:37 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		io.Copy(ioutil.Discard, resp.Body) | 
					
						
							|  |  |  | 		resp.Body.Close() | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if resp.StatusCode != http.StatusOK { | 
					
						
							| 
									
										
										
										
											2019-03-26 07:01:12 +08:00
										 |  |  | 		return "", errors.Errorf("server returned HTTP status %s", resp.Status) | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	if resp.Header.Get("Content-Encoding") != "gzip" { | 
					
						
							|  |  |  | 		_, err = io.Copy(w, resp.Body) | 
					
						
							| 
									
										
										
										
											2018-11-26 21:05:07 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return "", err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return resp.Header.Get("Content-Type"), nil | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if s.gzipr == nil { | 
					
						
							|  |  |  | 		s.buf = bufio.NewReader(resp.Body) | 
					
						
							|  |  |  | 		s.gzipr, err = gzip.NewReader(s.buf) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 			return "", err | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		s.buf.Reset(resp.Body) | 
					
						
							| 
									
										
										
										
											2018-08-17 23:24:35 +08:00
										 |  |  | 		if err = s.gzipr.Reset(s.buf); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 			return "", err | 
					
						
							| 
									
										
										
										
											2018-08-17 23:24:35 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = io.Copy(w, s.gzipr) | 
					
						
							|  |  |  | 	s.gzipr.Close() | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return resp.Header.Get("Content-Type"), nil | 
					
						
							| 
									
										
										
										
											2016-02-29 02:21:50 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 16:51:02 +08:00
										 |  |  | // A loop can run and be stopped again. It must not be reused after it was stopped.
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | type loop interface { | 
					
						
							| 
									
										
										
										
											2016-02-23 01:49:26 +08:00
										 |  |  | 	run(interval, timeout time.Duration, errc chan<- error) | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	setForcedError(err error) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	stop() | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 	getCache() *scrapeCache | 
					
						
							| 
									
										
										
										
											2020-03-21 00:43:26 +08:00
										 |  |  | 	disableEndOfRunStalenessMarkers() | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | type cacheEntry struct { | 
					
						
							| 
									
										
										
										
											2017-09-07 20:14:41 +08:00
										 |  |  | 	ref      uint64 | 
					
						
							| 
									
										
										
										
											2017-05-26 14:44:24 +08:00
										 |  |  | 	lastIter uint64 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 	hash     uint64 | 
					
						
							|  |  |  | 	lset     labels.Labels | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | type scrapeLoop struct { | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 	scraper         scraper | 
					
						
							|  |  |  | 	l               log.Logger | 
					
						
							|  |  |  | 	cache           *scrapeCache | 
					
						
							|  |  |  | 	lastScrapeSize  int | 
					
						
							|  |  |  | 	buffers         *pool.Pool | 
					
						
							|  |  |  | 	jitterSeed      uint64 | 
					
						
							|  |  |  | 	honorTimestamps bool | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	forcedErr       error | 
					
						
							|  |  |  | 	forcedErrMtx    sync.Mutex | 
					
						
							| 
									
										
										
										
											2017-05-26 14:44:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 22:10:51 +08:00
										 |  |  | 	appender            func(ctx context.Context) storage.Appender | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	sampleMutator       labelsMutator | 
					
						
							|  |  |  | 	reportSampleMutator labelsMutator | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	parentCtx context.Context | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 	ctx       context.Context | 
					
						
							|  |  |  | 	cancel    func() | 
					
						
							|  |  |  | 	stopped   chan struct{} | 
					
						
							| 
									
										
										
										
											2020-03-21 00:43:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	disabledEndOfRunStalenessMarkers bool | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // scrapeCache tracks mappings of exposed metric strings to label sets and
 | 
					
						
							|  |  |  | // storage references. Additionally, it tracks staleness of series between
 | 
					
						
							|  |  |  | // scrapes.
 | 
					
						
							|  |  |  | type scrapeCache struct { | 
					
						
							|  |  |  | 	iter uint64 // Current scrape iteration.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 01:52:46 +08:00
										 |  |  | 	// How many series and metadata entries there were at the last success.
 | 
					
						
							|  |  |  | 	successfulCount int | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 	// Parsed string to an entry with information about the actual label set
 | 
					
						
							|  |  |  | 	// and its storage reference.
 | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	series map[string]*cacheEntry | 
					
						
							| 
									
										
										
										
											2017-05-24 22:23:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	// Cache of dropped metric strings and their iteration. The iteration must
 | 
					
						
							|  |  |  | 	// be a pointer so we can update it without setting a new entry with an unsafe
 | 
					
						
							|  |  |  | 	// string in addDropped().
 | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	droppedSeries map[string]*uint64 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 22:23:48 +08:00
										 |  |  | 	// seriesCur and seriesPrev store the labels of series that were seen
 | 
					
						
							|  |  |  | 	// in the current and previous scrape.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 23:05:42 +08:00
										 |  |  | 	// We hold two maps and swap them out to save allocations.
 | 
					
						
							| 
									
										
										
										
											2017-05-26 14:44:24 +08:00
										 |  |  | 	seriesCur  map[uint64]labels.Labels | 
					
						
							|  |  |  | 	seriesPrev map[uint64]labels.Labels | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	metaMtx  sync.Mutex | 
					
						
							|  |  |  | 	metadata map[string]*metaEntry | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // metaEntry holds meta information about a metric.
 | 
					
						
							|  |  |  | type metaEntry struct { | 
					
						
							| 
									
										
										
										
											2018-06-05 18:30:19 +08:00
										 |  |  | 	lastIter uint64 // Last scrape iteration the entry was observed at.
 | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	typ      textparse.MetricType | 
					
						
							|  |  |  | 	help     string | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 	unit     string | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 19:13:18 +08:00
										 |  |  | func (m *metaEntry) size() int { | 
					
						
							|  |  |  | 	// The attribute lastIter although part of the struct it is not metadata.
 | 
					
						
							|  |  |  | 	return len(m.help) + len(m.unit) + len(m.typ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | func newScrapeCache() *scrapeCache { | 
					
						
							|  |  |  | 	return &scrapeCache{ | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		series:        map[string]*cacheEntry{}, | 
					
						
							|  |  |  | 		droppedSeries: map[string]*uint64{}, | 
					
						
							|  |  |  | 		seriesCur:     map[uint64]labels.Labels{}, | 
					
						
							|  |  |  | 		seriesPrev:    map[uint64]labels.Labels{}, | 
					
						
							|  |  |  | 		metadata:      map[string]*metaEntry{}, | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 01:52:46 +08:00
										 |  |  | func (c *scrapeCache) iterDone(flushCache bool) { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 	count := len(c.series) + len(c.droppedSeries) + len(c.metadata) | 
					
						
							|  |  |  | 	c.metaMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if flushCache { | 
					
						
							|  |  |  | 		c.successfulCount = count | 
					
						
							|  |  |  | 	} else if count > c.successfulCount*2+1000 { | 
					
						
							|  |  |  | 		// If a target had varying labels in scrapes that ultimately failed,
 | 
					
						
							|  |  |  | 		// the caches would grow indefinitely. Force a flush when this happens.
 | 
					
						
							|  |  |  | 		// We use the heuristic that this is a doubling of the cache size
 | 
					
						
							|  |  |  | 		// since the last scrape, and allow an additional 1000 in case
 | 
					
						
							|  |  |  | 		// initial scrapes all fail.
 | 
					
						
							|  |  |  | 		flushCache = true | 
					
						
							|  |  |  | 		targetScrapeCacheFlushForced.Inc() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if flushCache { | 
					
						
							| 
									
										
										
										
											2019-03-29 01:07:14 +08:00
										 |  |  | 		// All caches may grow over time through series churn
 | 
					
						
							|  |  |  | 		// or multiple string representations of the same metric. Clean up entries
 | 
					
						
							|  |  |  | 		// that haven't appeared in the last scrape.
 | 
					
						
							|  |  |  | 		for s, e := range c.series { | 
					
						
							|  |  |  | 			if c.iter != e.lastIter { | 
					
						
							|  |  |  | 				delete(c.series, s) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-29 01:07:14 +08:00
										 |  |  | 		for s, iter := range c.droppedSeries { | 
					
						
							|  |  |  | 			if c.iter != *iter { | 
					
						
							|  |  |  | 				delete(c.droppedSeries, s) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-29 01:07:14 +08:00
										 |  |  | 		c.metaMtx.Lock() | 
					
						
							|  |  |  | 		for m, e := range c.metadata { | 
					
						
							|  |  |  | 			// Keep metadata around for 10 scrapes after its metric disappeared.
 | 
					
						
							|  |  |  | 			if c.iter-e.lastIter > 10 { | 
					
						
							|  |  |  | 				delete(c.metadata, m) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-29 01:07:14 +08:00
										 |  |  | 		c.metaMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		c.iter++ | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Swap current and previous series.
 | 
					
						
							|  |  |  | 	c.seriesPrev, c.seriesCur = c.seriesCur, c.seriesPrev | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We have to delete every single key in the map.
 | 
					
						
							|  |  |  | 	for k := range c.seriesCur { | 
					
						
							|  |  |  | 		delete(c.seriesCur, k) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | func (c *scrapeCache) get(met string) (*cacheEntry, bool) { | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	e, ok := c.series[met] | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 		return nil, false | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	e.lastIter = c.iter | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 	return e, true | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 20:14:41 +08:00
										 |  |  | func (c *scrapeCache) addRef(met string, ref uint64, lset labels.Labels, hash uint64) { | 
					
						
							|  |  |  | 	if ref == 0 { | 
					
						
							| 
									
										
										
										
											2017-06-26 14:56:40 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	c.series[met] = &cacheEntry{ref: ref, lastIter: c.iter, lset: lset, hash: hash} | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | func (c *scrapeCache) addDropped(met string) { | 
					
						
							|  |  |  | 	iter := c.iter | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	c.droppedSeries[met] = &iter | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *scrapeCache) getDropped(met string) bool { | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	iterp, ok := c.droppedSeries[met] | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	if ok { | 
					
						
							|  |  |  | 		*iterp = c.iter | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ok | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-26 14:56:40 +08:00
										 |  |  | func (c *scrapeCache) trackStaleness(hash uint64, lset labels.Labels) { | 
					
						
							|  |  |  | 	c.seriesCur[hash] = lset | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *scrapeCache) forEachStale(f func(labels.Labels) bool) { | 
					
						
							|  |  |  | 	for h, lset := range c.seriesPrev { | 
					
						
							|  |  |  | 		if _, ok := c.seriesCur[h]; !ok { | 
					
						
							|  |  |  | 			if !f(lset) { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | func (c *scrapeCache) setType(metric []byte, t textparse.MetricType) { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	e, ok := c.metadata[yoloString(metric)] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 		e = &metaEntry{typ: textparse.MetricTypeUnknown} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		c.metadata[string(metric)] = e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	e.typ = t | 
					
						
							|  |  |  | 	e.lastIter = c.iter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.metaMtx.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *scrapeCache) setHelp(metric, help []byte) { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	e, ok := c.metadata[yoloString(metric)] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 		e = &metaEntry{typ: textparse.MetricTypeUnknown} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		c.metadata[string(metric)] = e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if e.help != yoloString(help) { | 
					
						
							|  |  |  | 		e.help = string(help) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	e.lastIter = c.iter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.metaMtx.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | func (c *scrapeCache) setUnit(metric, unit []byte) { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	e, ok := c.metadata[yoloString(metric)] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		e = &metaEntry{typ: textparse.MetricTypeUnknown} | 
					
						
							|  |  |  | 		c.metadata[string(metric)] = e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if e.unit != yoloString(unit) { | 
					
						
							|  |  |  | 		e.unit = string(unit) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	e.lastIter = c.iter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.metaMtx.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-04 23:18:27 +08:00
										 |  |  | func (c *scrapeCache) GetMetadata(metric string) (MetricMetadata, bool) { | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 	defer c.metaMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m, ok := c.metadata[metric] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return MetricMetadata{}, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return MetricMetadata{ | 
					
						
							|  |  |  | 		Metric: metric, | 
					
						
							|  |  |  | 		Type:   m.typ, | 
					
						
							|  |  |  | 		Help:   m.help, | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 		Unit:   m.unit, | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	}, true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-04 23:18:27 +08:00
										 |  |  | func (c *scrapeCache) ListMetadata() []MetricMetadata { | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 	defer c.metaMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-05 18:30:19 +08:00
										 |  |  | 	res := make([]MetricMetadata, 0, len(c.metadata)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	for m, e := range c.metadata { | 
					
						
							|  |  |  | 		res = append(res, MetricMetadata{ | 
					
						
							|  |  |  | 			Metric: m, | 
					
						
							|  |  |  | 			Type:   e.typ, | 
					
						
							|  |  |  | 			Help:   e.help, | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 			Unit:   e.unit, | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 19:13:18 +08:00
										 |  |  | // MetadataSize returns the size of the metadata cache.
 | 
					
						
							|  |  |  | func (c *scrapeCache) SizeMetadata() (s int) { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 	defer c.metaMtx.Unlock() | 
					
						
							|  |  |  | 	for _, e := range c.metadata { | 
					
						
							|  |  |  | 		s += e.size() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return s | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MetadataLen returns the number of metadata entries in the cache.
 | 
					
						
							|  |  |  | func (c *scrapeCache) LengthMetadata() int { | 
					
						
							|  |  |  | 	c.metaMtx.Lock() | 
					
						
							|  |  |  | 	defer c.metaMtx.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return len(c.metadata) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 23:15:15 +08:00
										 |  |  | func newScrapeLoop(ctx context.Context, | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 	sc scraper, | 
					
						
							|  |  |  | 	l log.Logger, | 
					
						
							| 
									
										
										
										
											2018-02-14 04:44:51 +08:00
										 |  |  | 	buffers *pool.Pool, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 	sampleMutator labelsMutator, | 
					
						
							|  |  |  | 	reportSampleMutator labelsMutator, | 
					
						
							| 
									
										
										
										
											2020-07-24 22:10:51 +08:00
										 |  |  | 	appender func(ctx context.Context) storage.Appender, | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	cache *scrapeCache, | 
					
						
							| 
									
										
										
										
											2019-03-12 18:46:15 +08:00
										 |  |  | 	jitterSeed uint64, | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 	honorTimestamps bool, | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | ) *scrapeLoop { | 
					
						
							| 
									
										
										
										
											2017-05-16 21:04:37 +08:00
										 |  |  | 	if l == nil { | 
					
						
							| 
									
										
										
										
											2017-08-12 02:45:52 +08:00
										 |  |  | 		l = log.NewNopLogger() | 
					
						
							| 
									
										
										
										
											2017-05-16 21:04:37 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-07 20:43:21 +08:00
										 |  |  | 	if buffers == nil { | 
					
						
							| 
									
										
										
										
											2018-02-14 04:44:51 +08:00
										 |  |  | 		buffers = pool.New(1e3, 1e6, 3, func(sz int) interface{} { return make([]byte, 0, sz) }) | 
					
						
							| 
									
										
										
										
											2017-09-07 20:43:21 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 	if cache == nil { | 
					
						
							|  |  |  | 		cache = newScrapeCache() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	sl := &scrapeLoop{ | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		scraper:             sc, | 
					
						
							|  |  |  | 		buffers:             buffers, | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		cache:               cache, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		appender:            appender, | 
					
						
							|  |  |  | 		sampleMutator:       sampleMutator, | 
					
						
							|  |  |  | 		reportSampleMutator: reportSampleMutator, | 
					
						
							|  |  |  | 		stopped:             make(chan struct{}), | 
					
						
							| 
									
										
										
										
											2019-03-12 18:46:15 +08:00
										 |  |  | 		jitterSeed:          jitterSeed, | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		l:                   l, | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 		parentCtx:           ctx, | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 		honorTimestamps:     honorTimestamps, | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	sl.ctx, sl.cancel = context.WithCancel(ctx) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return sl | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-23 01:49:26 +08:00
										 |  |  | func (sl *scrapeLoop) run(interval, timeout time.Duration, errc chan<- error) { | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	select { | 
					
						
							| 
									
										
										
										
											2019-03-12 18:46:15 +08:00
										 |  |  | 	case <-time.After(sl.scraper.offset(interval, sl.jitterSeed)): | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		// Continue after a scraping offset.
 | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	case <-sl.ctx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 		close(sl.stopped) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var last time.Time | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 	alignedScrapeTime := time.Now() | 
					
						
							| 
									
										
										
										
											2020-10-07 03:17:16 +08:00
										 |  |  | 	ticker := time.NewTicker(interval) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	defer ticker.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | mainLoop: | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 		case <-sl.parentCtx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 			close(sl.stopped) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 		case <-sl.ctx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 			break mainLoop | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 		// Temporary workaround for a jitter in go timers that causes disk space
 | 
					
						
							|  |  |  | 		// increase in TSDB.
 | 
					
						
							|  |  |  | 		// See https://github.com/prometheus/prometheus/issues/7846
 | 
					
						
							|  |  |  | 		scrapeTime := time.Now() | 
					
						
							| 
									
										
										
										
											2020-10-08 00:25:52 +08:00
										 |  |  | 		if AlignScrapeTimestamps && interval > 100*scrapeTimestampTolerance { | 
					
						
							| 
									
										
										
										
											2020-10-06 19:48:24 +08:00
										 |  |  | 			// For some reason, a tick might have been skipped, in which case we
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 			// would call alignedScrapeTime.Add(interval) multiple times.
 | 
					
						
							|  |  |  | 			for scrapeTime.Sub(alignedScrapeTime) >= interval { | 
					
						
							|  |  |  | 				alignedScrapeTime = alignedScrapeTime.Add(interval) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Align the scrape time if we are in the tolerance boundaries.
 | 
					
						
							| 
									
										
										
										
											2020-10-08 00:25:52 +08:00
										 |  |  | 			if scrapeTime.Sub(alignedScrapeTime) <= scrapeTimestampTolerance { | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 				scrapeTime = alignedScrapeTime | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		last = sl.scrapeAndReport(interval, timeout, last, scrapeTime, errc) | 
					
						
							| 
									
										
										
										
											2016-02-23 01:49:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 		select { | 
					
						
							|  |  |  | 		case <-sl.parentCtx.Done(): | 
					
						
							|  |  |  | 			close(sl.stopped) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		case <-sl.ctx.Done(): | 
					
						
							|  |  |  | 			break mainLoop | 
					
						
							|  |  |  | 		case <-ticker.C: | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-20 19:32:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	close(sl.stopped) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	if !sl.disabledEndOfRunStalenessMarkers { | 
					
						
							|  |  |  | 		sl.endOfRunStaleness(last, ticker, interval) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-07 20:43:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | // scrapeAndReport performs a scrape and then appends the result to the storage
 | 
					
						
							|  |  |  | // together with reporting metrics, by using as few appenders as possible.
 | 
					
						
							|  |  |  | // In the happy scenario, a single appender is used.
 | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | // This function uses sl.parentCtx instead of sl.ctx on purpose. A scrape should
 | 
					
						
							|  |  |  | // only be cancelled on shutdown, not on reloads.
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | func (sl *scrapeLoop) scrapeAndReport(interval, timeout time.Duration, last, appendTime time.Time, errc chan<- error) time.Time { | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	start := time.Now() | 
					
						
							| 
									
										
										
										
											2017-06-15 10:08:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	// Only record after the first scrape.
 | 
					
						
							|  |  |  | 	if !last.IsZero() { | 
					
						
							|  |  |  | 		targetIntervalLength.WithLabelValues(interval.String()).Observe( | 
					
						
							|  |  |  | 			time.Since(last).Seconds(), | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	b := sl.buffers.Get(sl.lastScrapeSize).([]byte) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 	defer sl.buffers.Put(b) | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	buf := bytes.NewBuffer(b) | 
					
						
							| 
									
										
										
										
											2017-09-07 20:43:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	var total, added, seriesAdded int | 
					
						
							|  |  |  | 	var err, appErr, scrapeErr error | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | 	app := sl.appender(sl.parentCtx) | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			app.Rollback() | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		err = app.Commit() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			level.Error(sl.l).Log("msg", "Scrape commit failed", "err", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 		if err = sl.report(app, appendTime, time.Since(start), total, added, seriesAdded, scrapeErr); err != nil { | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 			level.Warn(sl.l).Log("msg", "Appending scrape report failed", "err", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	if forcedErr := sl.getForcedError(); forcedErr != nil { | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 		scrapeErr = forcedErr | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		// Add stale markers.
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 		if _, _, _, err := sl.append(app, []byte{}, "", appendTime); err != nil { | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 			app.Rollback() | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | 			app = sl.appender(sl.parentCtx) | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 			level.Warn(sl.l).Log("msg", "Append failed", "err", err) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		if errc != nil { | 
					
						
							|  |  |  | 			errc <- forcedErr | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return start | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var contentType string | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | 	scrapeCtx, cancel := context.WithTimeout(sl.parentCtx, timeout) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 	contentType, scrapeErr = sl.scraper.scrape(scrapeCtx, buf) | 
					
						
							|  |  |  | 	cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if scrapeErr == nil { | 
					
						
							|  |  |  | 		b = buf.Bytes() | 
					
						
							|  |  |  | 		// NOTE: There were issues with misbehaving clients in the past
 | 
					
						
							|  |  |  | 		// that occasionally returned empty results. We don't want those
 | 
					
						
							|  |  |  | 		// to falsely reset our buffer size.
 | 
					
						
							|  |  |  | 		if len(b) > 0 { | 
					
						
							|  |  |  | 			sl.lastScrapeSize = len(b) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2020-08-01 16:56:21 +08:00
										 |  |  | 		level.Debug(sl.l).Log("msg", "Scrape failed", "err", scrapeErr) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 		if errc != nil { | 
					
						
							|  |  |  | 			errc <- scrapeErr | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 	// A failed scrape is the same as an empty scrape,
 | 
					
						
							|  |  |  | 	// we still call sl.append to trigger stale markers.
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 	total, added, seriesAdded, appErr = sl.append(app, b, contentType, appendTime) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 	if appErr != nil { | 
					
						
							|  |  |  | 		app.Rollback() | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | 		app = sl.appender(sl.parentCtx) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 		level.Debug(sl.l).Log("msg", "Append failed", "err", appErr) | 
					
						
							|  |  |  | 		// The append failed, probably due to a parse error or sample limit.
 | 
					
						
							|  |  |  | 		// Call sl.append again with an empty scrape to trigger stale markers.
 | 
					
						
							| 
									
										
										
										
											2020-10-06 00:17:50 +08:00
										 |  |  | 		if _, _, _, err := sl.append(app, []byte{}, "", appendTime); err != nil { | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 			app.Rollback() | 
					
						
							| 
									
										
										
										
											2020-08-07 21:58:16 +08:00
										 |  |  | 			app = sl.appender(sl.parentCtx) | 
					
						
							| 
									
										
										
										
											2020-08-01 01:11:08 +08:00
										 |  |  | 			level.Warn(sl.l).Log("msg", "Append failed", "err", err) | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	if scrapeErr == nil { | 
					
						
							|  |  |  | 		scrapeErr = appErr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return start | 
					
						
							| 
									
										
										
										
											2017-05-16 20:12:21 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 20:20:24 +08:00
										 |  |  | func (sl *scrapeLoop) setForcedError(err error) { | 
					
						
							|  |  |  | 	sl.forcedErrMtx.Lock() | 
					
						
							|  |  |  | 	defer sl.forcedErrMtx.Unlock() | 
					
						
							|  |  |  | 	sl.forcedErr = err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (sl *scrapeLoop) getForcedError() error { | 
					
						
							|  |  |  | 	sl.forcedErrMtx.Lock() | 
					
						
							|  |  |  | 	defer sl.forcedErrMtx.Unlock() | 
					
						
							|  |  |  | 	return sl.forcedErr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 20:12:21 +08:00
										 |  |  | func (sl *scrapeLoop) endOfRunStaleness(last time.Time, ticker *time.Ticker, interval time.Duration) { | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 	// Scraping has stopped. We want to write stale markers but
 | 
					
						
							|  |  |  | 	// the target may be recreated, so we wait just over 2 scrape intervals
 | 
					
						
							|  |  |  | 	// before creating them.
 | 
					
						
							| 
									
										
										
										
											2018-11-28 00:44:29 +08:00
										 |  |  | 	// If the context is canceled, we presume the server is shutting down
 | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 	// and will restart where is was. We do not attempt to write stale markers
 | 
					
						
							|  |  |  | 	// in this case.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if last.IsZero() { | 
					
						
							|  |  |  | 		// There never was a scrape, so there will be no stale markers.
 | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait for when the next scrape would have been, record its timestamp.
 | 
					
						
							|  |  |  | 	var staleTime time.Time | 
					
						
							|  |  |  | 	select { | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	case <-sl.parentCtx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	case <-ticker.C: | 
					
						
							|  |  |  | 		staleTime = time.Now() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait for when the next scrape would have been, if the target was recreated
 | 
					
						
							|  |  |  | 	// samples should have been ingested by now.
 | 
					
						
							|  |  |  | 	select { | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	case <-sl.parentCtx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	case <-ticker.C: | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait for an extra 10% of the interval, just to be safe.
 | 
					
						
							|  |  |  | 	select { | 
					
						
							| 
									
										
										
										
											2019-08-28 21:55:09 +08:00
										 |  |  | 	case <-sl.parentCtx.Done(): | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	case <-time.After(interval / 10): | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Call sl.append again with an empty scrape to trigger stale markers.
 | 
					
						
							|  |  |  | 	// If the target has since been recreated and scraped, the
 | 
					
						
							|  |  |  | 	// stale markers will be out of order and ignored.
 | 
					
						
							| 
									
										
										
										
											2020-07-24 22:10:51 +08:00
										 |  |  | 	app := sl.appender(sl.ctx) | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	var err error | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			app.Rollback() | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err = app.Commit() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			level.Warn(sl.l).Log("msg", "Stale commit failed", "err", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	if _, _, _, err = sl.append(app, []byte{}, "", staleTime); err != nil { | 
					
						
							|  |  |  | 		app.Rollback() | 
					
						
							| 
									
										
										
										
											2020-07-24 22:10:51 +08:00
										 |  |  | 		app = sl.appender(sl.ctx) | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 		level.Warn(sl.l).Log("msg", "Stale append failed", "err", err) | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | 	if err = sl.reportStale(app, staleTime); err != nil { | 
					
						
							|  |  |  | 		level.Warn(sl.l).Log("msg", "Stale report failed", "err", err) | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | // Stop the scraping. May still write data and stale markers after it has
 | 
					
						
							|  |  |  | // returned. Cancel the context to stop all writes.
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | func (sl *scrapeLoop) stop() { | 
					
						
							|  |  |  | 	sl.cancel() | 
					
						
							| 
									
										
										
										
											2017-05-10 23:59:02 +08:00
										 |  |  | 	<-sl.stopped | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-21 00:43:26 +08:00
										 |  |  | func (sl *scrapeLoop) disableEndOfRunStalenessMarkers() { | 
					
						
							|  |  |  | 	sl.disabledEndOfRunStalenessMarkers = true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | func (sl *scrapeLoop) getCache() *scrapeCache { | 
					
						
							|  |  |  | 	return sl.cache | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | type appendErrors struct { | 
					
						
							|  |  |  | 	numOutOfOrder  int | 
					
						
							|  |  |  | 	numDuplicates  int | 
					
						
							|  |  |  | 	numOutOfBounds int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | func (sl *scrapeLoop) append(app storage.Appender, b []byte, contentType string, ts time.Time) (total, added, seriesAdded int, err error) { | 
					
						
							| 
									
										
										
										
											2016-04-25 22:43:52 +08:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2018-10-04 21:52:03 +08:00
										 |  |  | 		p              = textparse.New(b, contentType) | 
					
						
							| 
									
										
										
										
											2017-07-04 17:24:13 +08:00
										 |  |  | 		defTime        = timestamp.FromTime(ts) | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 		appErrs        = appendErrors{} | 
					
						
							|  |  |  | 		sampleLimitErr error | 
					
						
							| 
									
										
										
										
											2016-04-25 22:43:52 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Only perform cache cleaning if the scrape was not empty.
 | 
					
						
							|  |  |  | 		// An empty scrape (usually) is used to indicate a failed scrape.
 | 
					
						
							|  |  |  | 		sl.cache.iterDone(len(b) > 0) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:59:37 +08:00
										 |  |  | loop: | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 		var ( | 
					
						
							|  |  |  | 			et          textparse.Entry | 
					
						
							|  |  |  | 			sampleAdded bool | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 		if et, err = p.Next(); err != nil { | 
					
						
							|  |  |  | 			if err == io.EOF { | 
					
						
							|  |  |  | 				err = nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		switch et { | 
					
						
							|  |  |  | 		case textparse.EntryType: | 
					
						
							|  |  |  | 			sl.cache.setType(p.Type()) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		case textparse.EntryHelp: | 
					
						
							|  |  |  | 			sl.cache.setHelp(p.Help()) | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2018-10-06 00:11:16 +08:00
										 |  |  | 		case textparse.EntryUnit: | 
					
						
							|  |  |  | 			sl.cache.setUnit(p.Unit()) | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2018-05-18 15:32:11 +08:00
										 |  |  | 		case textparse.EntryComment: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-31 00:30:28 +08:00
										 |  |  | 		total++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 		t := defTime | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 		met, tp, v := p.Series() | 
					
						
							| 
									
										
										
										
											2019-03-15 18:04:15 +08:00
										 |  |  | 		if !sl.honorTimestamps { | 
					
						
							|  |  |  | 			tp = nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 		if tp != nil { | 
					
						
							|  |  |  | 			t = *tp | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 		if sl.cache.getDropped(yoloString(met)) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 		ce, ok := sl.cache.get(yoloString(met)) | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		var ( | 
					
						
							|  |  |  | 			ref  uint64 | 
					
						
							|  |  |  | 			lset labels.Labels | 
					
						
							|  |  |  | 			mets string | 
					
						
							|  |  |  | 			hash uint64 | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 		if ok { | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 			ref = ce.ref | 
					
						
							|  |  |  | 			lset = ce.lset | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			mets = p.Metric(&lset) | 
					
						
							|  |  |  | 			hash = lset.Hash() | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Hash label set as it is seen local to the target. Then add target labels
 | 
					
						
							|  |  |  | 			// and relabeling and store the final label set.
 | 
					
						
							|  |  |  | 			lset = sl.sampleMutator(lset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// The label set may be set to nil to indicate dropping.
 | 
					
						
							|  |  |  | 			if lset == nil { | 
					
						
							|  |  |  | 				sl.cache.addDropped(mets) | 
					
						
							|  |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2017-06-26 14:56:40 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-31 00:30:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 15:18:05 +08:00
										 |  |  | 			if !lset.Has(labels.MetricName) { | 
					
						
							|  |  |  | 				err = errNameLabelMandatory | 
					
						
							|  |  |  | 				break loop | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-02 15:18:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		ref, err = app.Append(ref, lset, t, v) | 
					
						
							|  |  |  | 		sampleAdded, err = sl.checkAddError(ce, met, tp, err, &sampleLimitErr, &appErrs) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if err != storage.ErrNotFound { | 
					
						
							|  |  |  | 				level.Debug(sl.l).Log("msg", "Unexpected error", "series", string(met), "err", err) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 			break loop | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		if !ok { | 
					
						
							| 
									
										
										
										
											2017-04-28 23:36:36 +08:00
										 |  |  | 			if tp == nil { | 
					
						
							|  |  |  | 				// Bypass staleness logic if there is an explicit timestamp.
 | 
					
						
							| 
									
										
										
										
											2017-06-26 14:56:40 +08:00
										 |  |  | 				sl.cache.trackStaleness(hash, lset) | 
					
						
							| 
									
										
										
										
											2017-04-28 23:36:36 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-26 14:56:40 +08:00
										 |  |  | 			sl.cache.addRef(mets, ref, lset, hash) | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 			if sampleAdded && sampleLimitErr == nil { | 
					
						
							|  |  |  | 				seriesAdded++ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-04 23:00:37 +08:00
										 |  |  | 		// Increment added even if there's an error so we correctly report the
 | 
					
						
							| 
									
										
										
										
											2020-07-11 21:37:13 +08:00
										 |  |  | 		// number of samples remaining after relabeling.
 | 
					
						
							| 
									
										
										
										
											2020-06-04 23:00:37 +08:00
										 |  |  | 		added++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-09 23:43:28 +08:00
										 |  |  | 	if sampleLimitErr != nil { | 
					
						
							| 
									
										
										
										
											2018-05-15 04:19:53 +08:00
										 |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			err = sampleLimitErr | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-09 23:43:28 +08:00
										 |  |  | 		// We only want to increment this once per scrape, so this is Inc'd outside the loop.
 | 
					
						
							| 
									
										
										
										
											2017-05-29 21:08:55 +08:00
										 |  |  | 		targetScrapeSampleLimit.Inc() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 	if appErrs.numOutOfOrder > 0 { | 
					
						
							|  |  |  | 		level.Warn(sl.l).Log("msg", "Error on ingesting out-of-order samples", "num_dropped", appErrs.numOutOfOrder) | 
					
						
							| 
									
										
										
										
											2017-05-16 20:30:40 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 	if appErrs.numDuplicates > 0 { | 
					
						
							|  |  |  | 		level.Warn(sl.l).Log("msg", "Error on ingesting samples with different value but same timestamp", "num_dropped", appErrs.numDuplicates) | 
					
						
							| 
									
										
										
										
											2017-05-16 20:30:40 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 	if appErrs.numOutOfBounds > 0 { | 
					
						
							|  |  |  | 		level.Warn(sl.l).Log("msg", "Error on ingesting samples that are too old or are too far into the future", "num_dropped", appErrs.numOutOfBounds) | 
					
						
							| 
									
										
										
										
											2017-07-04 17:24:13 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | 	if err == nil { | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 		sl.cache.forEachStale(func(lset labels.Labels) bool { | 
					
						
							|  |  |  | 			// Series no longer exposed, mark it stale.
 | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 			_, err = app.Append(0, lset, defTime, math.Float64frombits(value.StaleNaN)) | 
					
						
							| 
									
										
										
										
											2020-03-17 05:52:02 +08:00
										 |  |  | 			switch errors.Cause(err) { | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 			case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: | 
					
						
							|  |  |  | 				// Do not count these in logging, as this is expected if a target
 | 
					
						
							|  |  |  | 				// goes away and comes back again with a new scrape loop.
 | 
					
						
							|  |  |  | 				err = nil | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-05-26 16:44:48 +08:00
										 |  |  | 			return err == nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2017-04-14 01:07:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | func yoloString(b []byte) string { | 
					
						
							| 
									
										
										
										
											2017-03-07 18:41:11 +08:00
										 |  |  | 	return *((*string)(unsafe.Pointer(&b))) | 
					
						
							| 
									
										
										
										
											2017-02-22 20:00:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | // Adds samples to the appender, checking the error, and then returns the # of samples added,
 | 
					
						
							|  |  |  | // whether the caller should continue to process more samples, and any sample limit errors.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 22:14:55 +08:00
										 |  |  | func (sl *scrapeLoop) checkAddError(ce *cacheEntry, met []byte, tp *int64, err error, sampleLimitErr *error, appErrs *appendErrors) (bool, error) { | 
					
						
							| 
									
										
										
										
											2020-03-26 10:31:48 +08:00
										 |  |  | 	switch errors.Cause(err) { | 
					
						
							|  |  |  | 	case nil: | 
					
						
							|  |  |  | 		if tp == nil && ce != nil { | 
					
						
							|  |  |  | 			sl.cache.trackStaleness(ce.hash, ce.lset) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true, nil | 
					
						
							|  |  |  | 	case storage.ErrNotFound: | 
					
						
							|  |  |  | 		return false, storage.ErrNotFound | 
					
						
							|  |  |  | 	case storage.ErrOutOfOrderSample: | 
					
						
							|  |  |  | 		appErrs.numOutOfOrder++ | 
					
						
							|  |  |  | 		level.Debug(sl.l).Log("msg", "Out of order sample", "series", string(met)) | 
					
						
							|  |  |  | 		targetScrapeSampleOutOfOrder.Inc() | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	case storage.ErrDuplicateSampleForTimestamp: | 
					
						
							|  |  |  | 		appErrs.numDuplicates++ | 
					
						
							|  |  |  | 		level.Debug(sl.l).Log("msg", "Duplicate sample for timestamp", "series", string(met)) | 
					
						
							|  |  |  | 		targetScrapeSampleDuplicate.Inc() | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	case storage.ErrOutOfBounds: | 
					
						
							|  |  |  | 		appErrs.numOutOfBounds++ | 
					
						
							|  |  |  | 		level.Debug(sl.l).Log("msg", "Out of bounds metric", "series", string(met)) | 
					
						
							|  |  |  | 		targetScrapeSampleOutOfBounds.Inc() | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	case errSampleLimit: | 
					
						
							|  |  |  | 		// Keep on parsing output if we hit the limit, so we report the correct
 | 
					
						
							|  |  |  | 		// total number of samples scraped.
 | 
					
						
							|  |  |  | 		*sampleLimitErr = err | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | // The constants are suffixed with the invalid \xff unicode rune to avoid collisions
 | 
					
						
							|  |  |  | // with scraped metrics in the cache.
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	scrapeHealthMetricName       = "up" + "\xff" | 
					
						
							|  |  |  | 	scrapeDurationMetricName     = "scrape_duration_seconds" + "\xff" | 
					
						
							|  |  |  | 	scrapeSamplesMetricName      = "scrape_samples_scraped" + "\xff" | 
					
						
							|  |  |  | 	samplesPostRelabelMetricName = "scrape_samples_post_metric_relabeling" + "\xff" | 
					
						
							| 
									
										
										
										
											2019-05-09 05:24:00 +08:00
										 |  |  | 	scrapeSeriesAddedMetricName  = "scrape_series_added" + "\xff" | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | func (sl *scrapeLoop) report(app storage.Appender, start time.Time, duration time.Duration, scraped, added, seriesAdded int, scrapeErr error) (err error) { | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	sl.scraper.Report(start, duration, scrapeErr) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 	ts := timestamp.FromTime(start) | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 	var health float64 | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if scrapeErr == nil { | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | 		health = 1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-13 21:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeHealthMetricName, ts, health); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-01-13 21:48:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeDurationMetricName, ts, duration.Seconds()); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-05-19 22:22:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeSamplesMetricName, ts, float64(scraped)); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-10-27 00:43:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-04 23:00:37 +08:00
										 |  |  | 	if err = sl.addReportSample(app, samplesPostRelabelMetricName, ts, float64(added)); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeSeriesAddedMetricName, ts, float64(seriesAdded)); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-05-09 05:24:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 19:53:39 +08:00
										 |  |  | func (sl *scrapeLoop) reportStale(app storage.Appender, start time.Time) (err error) { | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	ts := timestamp.FromTime(start) | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	stale := math.Float64frombits(value.StaleNaN) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeHealthMetricName, ts, stale); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeDurationMetricName, ts, stale); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeSamplesMetricName, ts, stale); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, samplesPostRelabelMetricName, ts, stale); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	if err = sl.addReportSample(app, scrapeSeriesAddedMetricName, ts, stale); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-05-09 05:24:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-14 03:54:47 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | func (sl *scrapeLoop) addReportSample(app storage.Appender, s string, t int64, v float64) error { | 
					
						
							| 
									
										
										
										
											2017-09-15 17:08:51 +08:00
										 |  |  | 	ce, ok := sl.cache.get(s) | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 	var ref uint64 | 
					
						
							|  |  |  | 	var lset labels.Labels | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 	if ok { | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		ref = ce.ref | 
					
						
							|  |  |  | 		lset = ce.lset | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		lset = labels.Labels{ | 
					
						
							|  |  |  | 			// The constants are suffixed with the invalid \xff unicode rune to avoid collisions
 | 
					
						
							|  |  |  | 			// with scraped metrics in the cache.
 | 
					
						
							|  |  |  | 			// We have to drop it when building the actual metric.
 | 
					
						
							|  |  |  | 			labels.Label{Name: labels.MetricName, Value: s[:len(s)-1]}, | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		lset = sl.reportSampleMutator(lset) | 
					
						
							| 
									
										
										
										
											2017-01-13 21:48:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-08 20:34:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 	ref, err := app.Append(ref, lset, t, v) | 
					
						
							| 
									
										
										
										
											2020-03-17 05:52:02 +08:00
										 |  |  | 	switch errors.Cause(err) { | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 	case nil: | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			sl.cache.addRef(s, ref, lset, lset.Hash()) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: | 
					
						
							| 
									
										
										
										
											2021-02-18 20:07:00 +08:00
										 |  |  | 		// Do not log here, as this is expected if a target goes away and comes back
 | 
					
						
							|  |  |  | 		// again with a new scrape loop.
 | 
					
						
							| 
									
										
										
										
											2017-05-11 21:43:43 +08:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2017-01-16 00:33:07 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2017-01-13 21:48:01 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-22 23:46:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // zeroConfig returns a new scrape config that only contains configuration items
 | 
					
						
							|  |  |  | // that alter metrics.
 | 
					
						
							|  |  |  | func zeroConfig(c *config.ScrapeConfig) *config.ScrapeConfig { | 
					
						
							|  |  |  | 	z := *c | 
					
						
							|  |  |  | 	// We zero out the fields that for sure don't affect scrape.
 | 
					
						
							|  |  |  | 	z.ScrapeInterval = 0 | 
					
						
							|  |  |  | 	z.ScrapeTimeout = 0 | 
					
						
							|  |  |  | 	z.SampleLimit = 0 | 
					
						
							|  |  |  | 	z.HTTPClientConfig = config_util.HTTPClientConfig{} | 
					
						
							|  |  |  | 	return &z | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 16:21:24 +08:00
										 |  |  | // reusableCache compares two scrape config and tells whether the cache is still
 | 
					
						
							| 
									
										
										
										
											2020-01-22 20:13:47 +08:00
										 |  |  | // valid.
 | 
					
						
							|  |  |  | func reusableCache(r, l *config.ScrapeConfig) bool { | 
					
						
							|  |  |  | 	if r == nil || l == nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return reflect.DeepEqual(zeroConfig(r), zeroConfig(l)) | 
					
						
							|  |  |  | } |