2020-06-28 11:26:22 +00:00
package datasource
import (
"flag"
"fmt"
"net/http"
2021-12-02 12:45:08 +00:00
"net/url"
2021-05-10 08:11:45 +00:00
"strings"
2022-09-23 08:22:53 +00:00
"time"
2020-06-28 11:26:22 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/utils"
2022-08-11 07:56:40 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
2024-02-08 14:52:00 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputils"
2024-07-15 21:00:14 +00:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
2020-06-28 11:26:22 +00:00
)
var (
2024-05-22 08:52:51 +00:00
addr = flag . String ( "datasource.url" , "" , "Datasource compatible with Prometheus HTTP API. It can be single node VictoriaMetrics or vmselect endpoint. Required parameter. " +
2024-08-16 09:32:04 +00:00
"Supports address in the form of IP address with a port (e.g., http://127.0.0.1:8428) or DNS SRV record. " +
2024-05-22 08:52:51 +00:00
"See also -remoteRead.disablePathAppend and -datasource.showURL" )
2022-08-11 07:56:40 +00:00
appendTypePrefix = flag . Bool ( "datasource.appendTypePrefix" , false , "Whether to add type prefix to -datasource.url based on the query type. Set to true if sending different query types to the vmselect URL." )
2023-10-10 09:40:27 +00:00
showDatasourceURL = flag . Bool ( "datasource.showURL" , false , "Whether to avoid stripping sensitive information such as auth headers or passwords from URLs in log messages or UI and exported metrics. " +
2022-08-11 07:56:40 +00:00
"It is hidden by default, since it can contain sensitive info such as auth key" )
2022-03-10 11:09:12 +00:00
2022-07-21 13:59:55 +00:00
headers = flag . String ( "datasource.headers" , "" , "Optional HTTP extraHeaders to send with each request to the corresponding -datasource.url. " +
2022-07-21 11:57:53 +00:00
"For example, -datasource.headers='My-Auth:foobar' would send 'My-Auth: foobar' HTTP header with every request to the corresponding -datasource.url. " +
"Multiple headers must be delimited by '^^': -datasource.headers='header1:value1^^header2:value2'" )
2021-09-14 11:32:06 +00:00
basicAuthUsername = flag . String ( "datasource.basicAuth.username" , "" , "Optional basic auth username for -datasource.url" )
basicAuthPassword = flag . String ( "datasource.basicAuth.password" , "" , "Optional basic auth password for -datasource.url" )
basicAuthPasswordFile = flag . String ( "datasource.basicAuth.passwordFile" , "" , "Optional path to basic auth password to use for -datasource.url" )
2022-03-10 11:09:12 +00:00
bearerToken = flag . String ( "datasource.bearerToken" , "" , "Optional bearer auth token to use for -datasource.url." )
bearerTokenFile = flag . String ( "datasource.bearerTokenFile" , "" , "Optional path to bearer token file to use for -datasource.url." )
2020-06-28 11:26:22 +00:00
tlsInsecureSkipVerify = flag . Bool ( "datasource.tlsInsecureSkipVerify" , false , "Whether to skip tls verification when connecting to -datasource.url" )
tlsCertFile = flag . String ( "datasource.tlsCertFile" , "" , "Optional path to client-side TLS certificate file to use when connecting to -datasource.url" )
tlsKeyFile = flag . String ( "datasource.tlsKeyFile" , "" , "Optional path to client-side TLS certificate key to use when connecting to -datasource.url" )
2021-04-12 09:28:04 +00:00
tlsCAFile = flag . String ( "datasource.tlsCAFile" , "" , ` Optional path to TLS CA file to use for verifying connections to -datasource.url. By default, system CA is used ` )
tlsServerName = flag . String ( "datasource.tlsServerName" , "" , ` Optional TLS server name to use for connections to -datasource.url. By default, the server name from -datasource.url is used ` )
2020-09-21 12:53:49 +00:00
2023-12-20 19:35:16 +00:00
oauth2ClientID = flag . String ( "datasource.oauth2.clientID" , "" , "Optional OAuth2 clientID to use for -datasource.url" )
oauth2ClientSecret = flag . String ( "datasource.oauth2.clientSecret" , "" , "Optional OAuth2 clientSecret to use for -datasource.url" )
oauth2ClientSecretFile = flag . String ( "datasource.oauth2.clientSecretFile" , "" , "Optional OAuth2 clientSecretFile to use for -datasource.url" )
oauth2EndpointParams = flag . String ( "datasource.oauth2.endpointParams" , "" , "Optional OAuth2 endpoint parameters to use for -datasource.url . " +
` The endpoint parameters must be set in JSON format: { "param1":"value1",...,"paramN":"valueN"} ` )
oauth2TokenURL = flag . String ( "datasource.oauth2.tokenUrl" , "" , "Optional OAuth2 tokenURL to use for -datasource.url" )
oauth2Scopes = flag . String ( "datasource.oauth2.scopes" , "" , "Optional OAuth2 scopes to use for -datasource.url. Scopes must be delimited by ';'" )
2022-03-10 11:09:12 +00:00
2024-11-14 10:21:35 +00:00
queryStep = flag . Duration ( "datasource.queryStep" , 5 * time . Minute , "How far a value can fallback to when evaluating queries to the configured -datasource.url and -remoteRead.url. Only valid for prometheus datasource. " +
2022-09-26 05:46:21 +00:00
"For example, if -datasource.queryStep=15s then param \"step\" with value \"15s\" will be added to every query. " +
"If set to 0, rule's evaluation interval will be used instead." )
2024-05-30 15:54:42 +00:00
maxIdleConnections = flag . Int ( "datasource.maxIdleConnections" , 100 , ` Defines the number of idle (keep-alive connections) to each configured datasource. Consider setting this value equal to the value: groups_total * group.concurrency. Too low a value may result in a high number of sockets in TIME_WAIT state. ` )
idleConnectionTimeout = flag . Duration ( "datasource.idleConnTimeout" , 50 * time . Second , ` Defines a duration for idle (keep-alive connections) to exist. Consider setting this value less than "-http.idleConnTimeout". It must prevent possible "write: broken pipe" and "read: connection reset by peer" errors. ` )
disableKeepAlive = flag . Bool ( "datasource.disableKeepAlive" , false , ` Whether to disable long-lived connections to the datasource. ` +
2024-06-03 08:26:57 +00:00
` If true, disables HTTP keep-alive and will only use the connection to the server for a single HTTP request. ` )
2024-11-14 10:21:35 +00:00
roundDigits = flag . Int ( "datasource.roundDigits" , 0 , ` Adds "round_digits" GET param to datasource requests which limits the number of digits after the decimal point in response values. ` +
` Only valid for VictoriaMetrics as the datasource. ` )
2020-06-28 11:26:22 +00:00
)
2022-08-11 07:56:40 +00:00
// InitSecretFlags must be called after flag.Parse and before any logging
func InitSecretFlags ( ) {
if ! * showDatasourceURL {
flagutil . RegisterSecretFlag ( "datasource.url" )
}
}
2023-10-10 09:40:27 +00:00
// ShowDatasourceURL whether to show -datasource.url with sensitive information
func ShowDatasourceURL ( ) bool {
return * showDatasourceURL
}
2021-08-31 11:57:47 +00:00
// Param represents an HTTP GET param
type Param struct {
Key , Value string
}
2020-06-28 11:26:22 +00:00
// Init creates a Querier from provided flag values.
2021-12-02 12:45:08 +00:00
// Provided extraParams will be added as GET params for
2021-08-31 11:57:47 +00:00
// each request.
2021-12-02 12:45:08 +00:00
func Init ( extraParams url . Values ) ( QuerierBuilder , error ) {
2020-06-28 11:26:22 +00:00
if * addr == "" {
return nil , fmt . Errorf ( "datasource.url is empty" )
}
2021-05-10 08:11:45 +00:00
2024-02-08 14:52:00 +00:00
tr , err := httputils . Transport ( * addr , * tlsCertFile , * tlsKeyFile , * tlsCAFile , * tlsServerName , * tlsInsecureSkipVerify )
2020-06-28 11:26:22 +00:00
if err != nil {
2024-08-16 09:32:04 +00:00
return nil , fmt . Errorf ( "failed to create transport for -datasource.url=%q: %w" , * addr , err )
2020-06-28 11:26:22 +00:00
}
2024-07-15 21:00:14 +00:00
tr . DialContext = netutil . NewStatDialFunc ( "vmalert_datasource" )
2022-04-04 09:59:04 +00:00
tr . DisableKeepAlives = * disableKeepAlive
2021-05-14 15:10:19 +00:00
tr . MaxIdleConnsPerHost = * maxIdleConnections
2021-10-13 14:29:28 +00:00
if tr . MaxIdleConns != 0 && tr . MaxIdleConns < tr . MaxIdleConnsPerHost {
tr . MaxIdleConns = tr . MaxIdleConnsPerHost
}
2024-05-30 15:54:42 +00:00
tr . IdleConnTimeout = * idleConnectionTimeout
2021-05-10 08:11:45 +00:00
2021-12-02 12:45:08 +00:00
if extraParams == nil {
extraParams = url . Values { }
}
2021-05-10 08:11:45 +00:00
if * roundDigits > 0 {
2021-12-02 12:45:08 +00:00
extraParams . Set ( "round_digits" , fmt . Sprintf ( "%d" , * roundDigits ) )
2021-05-10 08:11:45 +00:00
}
2023-12-20 19:35:16 +00:00
endpointParams , err := flagutil . ParseJSONMap ( * oauth2EndpointParams )
if err != nil {
return nil , fmt . Errorf ( "cannot parse JSON for -datasource.oauth2.endpointParams=%s: %w" , * oauth2EndpointParams , err )
}
2022-03-10 11:09:12 +00:00
authCfg , err := utils . AuthConfig (
utils . WithBasicAuth ( * basicAuthUsername , * basicAuthPassword , * basicAuthPasswordFile ) ,
utils . WithBearer ( * bearerToken , * bearerTokenFile ) ,
2023-12-20 19:35:16 +00:00
utils . WithOAuth ( * oauth2ClientID , * oauth2ClientSecret , * oauth2ClientSecretFile , * oauth2TokenURL , * oauth2Scopes , endpointParams ) ,
2022-07-21 11:57:53 +00:00
utils . WithHeaders ( * headers ) )
2021-09-14 11:32:06 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to configure auth: %w" , err )
}
2023-10-17 09:58:19 +00:00
_ , err = authCfg . GetAuthHeader ( )
if err != nil {
2023-10-25 19:24:01 +00:00
return nil , fmt . Errorf ( "failed to set request auth header to datasource %q: %w" , * addr , err )
2023-10-17 09:58:19 +00:00
}
2021-09-14 11:32:06 +00:00
2024-10-29 15:30:39 +00:00
return & Client {
2021-05-10 08:11:45 +00:00
c : & http . Client { Transport : tr } ,
2021-09-14 11:32:06 +00:00
authCfg : authCfg ,
2021-05-10 08:11:45 +00:00
datasourceURL : strings . TrimSuffix ( * addr , "/" ) ,
appendTypePrefix : * appendTypePrefix ,
queryStep : * queryStep ,
2021-08-31 11:57:47 +00:00
extraParams : extraParams ,
2021-05-10 08:11:45 +00:00
} , nil
2020-06-28 11:26:22 +00:00
}