Reuse the HTTP client for scraping pods (#102)

Signed-off-by: Arjun Naik <arjun.rn@gmail.com>
This commit is contained in:
Arjun 2020-01-30 17:49:22 +01:00 committed by GitHub
parent 8e4662b26c
commit e3330dcf43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 11 deletions

View File

@ -18,6 +18,7 @@ package main
import ( import (
"flag" "flag"
_ "net/http/pprof"
"os" "os"
"runtime" "runtime"

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math" "math"
"net"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
@ -23,11 +24,13 @@ type JSONPathMetricsGetter struct {
path string path string
port int port int
aggregator string aggregator string
client *http.Client
} }
// NewJSONPathMetricsGetter initializes a new JSONPathMetricsGetter. // NewJSONPathMetricsGetter initializes a new JSONPathMetricsGetter.
func NewJSONPathMetricsGetter(config map[string]string) (*JSONPathMetricsGetter, error) { func NewJSONPathMetricsGetter(config map[string]string) (*JSONPathMetricsGetter, error) {
getter := &JSONPathMetricsGetter{} httpClient := defaultHTTPClient()
getter := &JSONPathMetricsGetter{client: httpClient}
if v, ok := config["json-key"]; ok { if v, ok := config["json-key"]; ok {
path, err := jsonpath.Compile(v) path, err := jsonpath.Compile(v)
@ -61,11 +64,26 @@ func NewJSONPathMetricsGetter(config map[string]string) (*JSONPathMetricsGetter,
return getter, nil return getter, nil
} }
func defaultHTTPClient() *http.Client {
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 15 * time.Second,
}).DialContext,
MaxIdleConns: 50,
IdleConnTimeout: 90 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
Timeout: 15 * time.Second,
}
return client
}
// GetMetric gets metric from pod by fetching json metrics from the pods metric // GetMetric gets metric from pod by fetching json metrics from the pods metric
// endpoint and extracting the desired value using the specified json path // endpoint and extracting the desired value using the specified json path
// query. // query.
func (g *JSONPathMetricsGetter) GetMetric(pod *corev1.Pod) (float64, error) { func (g *JSONPathMetricsGetter) GetMetric(pod *corev1.Pod) (float64, error) {
data, err := getPodMetrics(pod, g.scheme, g.path, g.port) data, err := g.getPodMetrics(pod, g.scheme, g.path, g.port)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -122,16 +140,11 @@ func castSlice(in []interface{}) ([]float64, error) {
} }
// getPodMetrics returns the content of the pods metrics endpoint. // getPodMetrics returns the content of the pods metrics endpoint.
func getPodMetrics(pod *corev1.Pod, scheme, path string, port int) ([]byte, error) { func (g *JSONPathMetricsGetter) getPodMetrics(pod *corev1.Pod, scheme, path string, port int) ([]byte, error) {
if pod.Status.PodIP == "" { if pod.Status.PodIP == "" {
return nil, fmt.Errorf("pod %s/%s does not have a pod IP", pod.Namespace, pod.Namespace) return nil, fmt.Errorf("pod %s/%s does not have a pod IP", pod.Namespace, pod.Namespace)
} }
httpClient := &http.Client{
Timeout: 15 * time.Second,
Transport: &http.Transport{},
}
if scheme == "" { if scheme == "" {
scheme = "http" scheme = "http"
} }
@ -147,7 +160,7 @@ func getPodMetrics(pod *corev1.Pod, scheme, path string, port int) ([]byte, erro
return nil, err return nil, err
} }
resp, err := httpClient.Do(request) resp, err := g.client.Do(request)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -7,6 +7,13 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func compareMetricsGetter(t *testing.T, first, second *JSONPathMetricsGetter) {
require.Equal(t, first.jsonPath, second.jsonPath)
require.Equal(t, first.scheme, second.scheme)
require.Equal(t, first.path, second.path)
require.Equal(t, first.port, second.port)
}
func TestNewJSONPathMetricsGetter(t *testing.T) { func TestNewJSONPathMetricsGetter(t *testing.T) {
configNoAggregator := map[string]string{ configNoAggregator := map[string]string{
"json-key": "$.value", "json-key": "$.value",
@ -18,7 +25,7 @@ func TestNewJSONPathMetricsGetter(t *testing.T) {
getterNoAggregator, err1 := NewJSONPathMetricsGetter(configNoAggregator) getterNoAggregator, err1 := NewJSONPathMetricsGetter(configNoAggregator)
require.NoError(t, err1) require.NoError(t, err1)
require.Equal(t, &JSONPathMetricsGetter{ compareMetricsGetter(t, &JSONPathMetricsGetter{
jsonPath: jpath1, jsonPath: jpath1,
scheme: "http", scheme: "http",
path: "/metrics", path: "/metrics",
@ -36,7 +43,7 @@ func TestNewJSONPathMetricsGetter(t *testing.T) {
getterAggregator, err2 := NewJSONPathMetricsGetter(configAggregator) getterAggregator, err2 := NewJSONPathMetricsGetter(configAggregator)
require.NoError(t, err2) require.NoError(t, err2)
require.Equal(t, &JSONPathMetricsGetter{ compareMetricsGetter(t, &JSONPathMetricsGetter{
jsonPath: jpath2, jsonPath: jpath2,
scheme: "http", scheme: "http",
path: "/metrics", path: "/metrics",

View File

@ -2,6 +2,7 @@ package collector
import ( import (
"fmt" "fmt"
"net/http"
"time" "time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -37,6 +38,7 @@ type PodCollector struct {
metricType autoscalingv2.MetricSourceType metricType autoscalingv2.MetricSourceType
interval time.Duration interval time.Duration
logger *log.Entry logger *log.Entry
httpClient *http.Client
} }
type PodMetricsGetter interface { type PodMetricsGetter interface {