API version checking and linting.
This commit is contained in:
parent
045769a292
commit
095aff540e
@ -14,19 +14,16 @@ import (
|
|||||||
// Application is a thing that responsible for all application-related
|
// Application is a thing that responsible for all application-related
|
||||||
// actions like data fetching, storing, etc. on higher level.
|
// actions like data fetching, storing, etc. on higher level.
|
||||||
type Application struct {
|
type Application struct {
|
||||||
config *Config
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
storage storage.Metrics
|
||||||
|
config *Config
|
||||||
doneChan chan struct{}
|
doneChan chan struct{}
|
||||||
logger *logger.Logger
|
logger *logger.Logger
|
||||||
name string
|
|
||||||
|
|
||||||
storage storage.Metrics
|
|
||||||
storageDone chan struct{}
|
storageDone chan struct{}
|
||||||
|
|
||||||
fetchIsRunning bool
|
|
||||||
fetchIsRunningMutex sync.RWMutex
|
|
||||||
|
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
name string
|
||||||
|
fetchIsRunningMutex sync.RWMutex
|
||||||
|
fetchIsRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewApplication creates new application.
|
// NewApplication creates new application.
|
||||||
|
@ -4,11 +4,11 @@ import "time"
|
|||||||
|
|
||||||
// Config is a generic application configuration.
|
// Config is a generic application configuration.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// Headers is a list of headers that should be added to metrics request.
|
||||||
|
Headers map[string]string `yaml:"headers"`
|
||||||
// Endpoint is a remote application endpoint which should give us metrics
|
// Endpoint is a remote application endpoint which should give us metrics
|
||||||
// in Prometheus format.
|
// in Prometheus format.
|
||||||
Endpoint string `yaml:"endpoint"`
|
Endpoint string `yaml:"endpoint"`
|
||||||
// Headers is a list of headers that should be added to metrics request.
|
|
||||||
Headers map[string]string `yaml:"headers"`
|
|
||||||
// TimeBetweenRequests is a minimal amount of time which should pass
|
// TimeBetweenRequests is a minimal amount of time which should pass
|
||||||
// between requests.
|
// between requests.
|
||||||
TimeBetweenRequests time.Duration `yaml:"time_between_requests"`
|
TimeBetweenRequests time.Duration `yaml:"time_between_requests"`
|
||||||
|
@ -29,6 +29,7 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
a.logger.Debugln("Analyzing line:", line)
|
a.logger.Debugln("Analyzing line:", line)
|
||||||
|
|
||||||
name = a.getMetricName(line)
|
name = a.getMetricName(line)
|
||||||
|
|
||||||
metric, found := data[name]
|
metric, found := data[name]
|
||||||
if !found {
|
if !found {
|
||||||
metric = models.NewMetric(name, "", "", nil)
|
metric = models.NewMetric(name, "", "", nil)
|
||||||
@ -53,9 +54,9 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
|
|
||||||
data[name] = metric
|
data[name] = metric
|
||||||
|
|
||||||
// According to https://github.com/Showmax/prometheus-docs/blob/master/content/docs/instrumenting/exposition_formats.md
|
// According to docs HELP and TYPE lines should be printed before actual metric. Do not even
|
||||||
// HELP and TYPE lines should be printed before actual metric. Do not even
|
|
||||||
// report bugs regarding that!
|
// report bugs regarding that!
|
||||||
|
// Docs: https://github.com/Showmax/prometheus-docs/blob/master/content/docs/instrumenting/exposition_formats.md
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,12 +77,12 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
|
|
||||||
metric.Value = a.getMetricValue(line)
|
metric.Value = a.getMetricValue(line)
|
||||||
|
|
||||||
a.logger.Debugln("Got metric: %+v\n", metric)
|
a.logger.Debugf("Got metric: %+v\n", metric)
|
||||||
|
|
||||||
data[name] = metric
|
data[name] = metric
|
||||||
}
|
}
|
||||||
|
|
||||||
a.logger.Debugln("Data parsed: %+v\n", data)
|
a.logger.Debugf("Data parsed: %+v\n", data)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@ -138,7 +139,7 @@ func (a *Application) getParametersForPrometheusMetric(line string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes nestif causes questions, like here. Is code below is
|
// Sometimes nestif causes questions, like here. Is code below is
|
||||||
// "deply nested"? I think not. So:
|
// "deeply nested"? I think not. So:
|
||||||
// nolint:nestif
|
// nolint:nestif
|
||||||
if !paramNameFinished {
|
if !paramNameFinished {
|
||||||
if string(r) != "=" {
|
if string(r) != "=" {
|
||||||
|
@ -39,7 +39,6 @@ func (h *handler) getAppsList() ([]byte, error) {
|
|||||||
appsList, err := json.Marshal(apps)
|
appsList, err := json.Marshal(apps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ToDo: log error
|
// ToDo: log error
|
||||||
|
|
||||||
return nil, errNoAppsRegistered
|
return nil, errNoAppsRegistered
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,23 +69,41 @@ func (h *handler) getRequestInfo(r *http.Request) (*models.RequestInfo, error) {
|
|||||||
|
|
||||||
// Parse API version.
|
// Parse API version.
|
||||||
apiVersionRaw := strings.TrimLeft(pathSplitted[2], "v")
|
apiVersionRaw := strings.TrimLeft(pathSplitted[2], "v")
|
||||||
|
|
||||||
apiVersion, err := strconv.Atoi(apiVersionRaw)
|
apiVersion, err := strconv.Atoi(apiVersionRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ToDo: log error
|
// ToDo: log error
|
||||||
return nil, errInvalidAPIVersion
|
return nil, errInvalidAPIVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check used API version.
|
||||||
|
var supportedAPIVersionUsed bool
|
||||||
|
|
||||||
|
for _, version := range supportedAPIVersions {
|
||||||
|
if apiVersion == version {
|
||||||
|
supportedAPIVersionUsed = true
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !supportedAPIVersionUsed {
|
||||||
|
return nil, errInvalidAPIVersion
|
||||||
|
}
|
||||||
|
|
||||||
// Get request type and key.
|
// Get request type and key.
|
||||||
requestType = pathSplitted[3]
|
requestType = pathSplitted[3]
|
||||||
|
|
||||||
if len(pathSplitted) >= 5 {
|
if len(pathSplitted) >= 5 {
|
||||||
appName = pathSplitted[4]
|
appName = pathSplitted[4]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pathSplitted) >= 6 {
|
if len(pathSplitted) >= 6 {
|
||||||
metricName = strings.Join(pathSplitted[5:], "/")
|
metricName = strings.Join(pathSplitted[5:], "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
reqInfo := &models.RequestInfo{
|
reqInfo := &models.RequestInfo{
|
||||||
ApiVersion: apiVersion,
|
APIVersion: apiVersion,
|
||||||
Application: appName,
|
Application: appName,
|
||||||
Metric: metricName,
|
Metric: metricName,
|
||||||
RequestType: requestType,
|
RequestType: requestType,
|
||||||
@ -103,8 +120,9 @@ func (h *handler) register(appName string, hndl common.HTTPHandlerFunc) {
|
|||||||
// ServeHTTP handles every HTTP request.
|
// ServeHTTP handles every HTTP request.
|
||||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
requestDuration := time.Now().Sub(startTime)
|
requestDuration := time.Since(startTime)
|
||||||
|
|
||||||
log.Printf("[HTTP Request] from %s to %s, duration %.4fs\n", r.RemoteAddr, r.URL.Path, requestDuration.Seconds())
|
log.Printf("[HTTP Request] from %s to %s, duration %.4fs\n", r.RemoteAddr, r.URL.Path, requestDuration.Seconds())
|
||||||
}()
|
}()
|
||||||
|
@ -2,16 +2,16 @@ package models
|
|||||||
|
|
||||||
// Metric is a generic metric structure.
|
// Metric is a generic metric structure.
|
||||||
type Metric struct {
|
type Metric struct {
|
||||||
// Metric name.
|
// Name is a metric name.
|
||||||
Name string
|
Name string
|
||||||
// HELP data, if present.
|
// Description is a metric description from HELP line.
|
||||||
Description string
|
Description string
|
||||||
// Additional parameters, data inside "{}".
|
// Type is a metric type from TYPE line.
|
||||||
Params []string
|
|
||||||
// Type is a metric type.
|
|
||||||
Type string
|
Type string
|
||||||
// Metric value.
|
// Value is a metric value.
|
||||||
Value string
|
Value string
|
||||||
|
// Params is an additional params which are placed inside "{}".
|
||||||
|
Params []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetric creates new structure for storing single metric data.
|
// NewMetric creates new structure for storing single metric data.
|
||||||
@ -21,6 +21,7 @@ func NewMetric(name, mType, description string, params []string) Metric {
|
|||||||
Description: description,
|
Description: description,
|
||||||
Type: mType,
|
Type: mType,
|
||||||
Params: params,
|
Params: params,
|
||||||
|
Value: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
@ -2,8 +2,8 @@ package models
|
|||||||
|
|
||||||
// RequestInfo is a parsed request information to throw into application's handler.
|
// RequestInfo is a parsed request information to throw into application's handler.
|
||||||
type RequestInfo struct {
|
type RequestInfo struct {
|
||||||
ApiVersion int
|
|
||||||
Application string
|
Application string
|
||||||
Metric string
|
Metric string
|
||||||
RequestType string
|
RequestType string
|
||||||
|
APIVersion int
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user