2020-11-20 11:38:12 +00:00
|
|
|
package eureka
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/xml"
|
2021-06-25 09:10:20 +00:00
|
|
|
"flag"
|
2020-11-20 11:38:12 +00:00
|
|
|
"fmt"
|
|
|
|
"strconv"
|
2021-06-25 09:10:20 +00:00
|
|
|
"time"
|
2020-11-20 11:38:12 +00:00
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
|
2020-12-24 08:52:37 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
|
2020-12-24 08:56:10 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/proxy"
|
2020-11-20 11:38:12 +00:00
|
|
|
)
|
|
|
|
|
2021-06-25 09:10:20 +00:00
|
|
|
// SDCheckInterval defines interval for targets refresh.
|
|
|
|
var SDCheckInterval = flag.Duration("promscrape.eurekaSDCheckInterval", 30*time.Second, "Interval for checking for changes in eureka. "+
|
|
|
|
"This works only if eureka_sd_configs is configured in '-promscrape.config' file. "+
|
2022-08-14 22:40:20 +00:00
|
|
|
"See https://docs.victoriametrics.com/sd_configs.html#eureka_sd_configs for details")
|
2020-11-20 11:38:12 +00:00
|
|
|
|
|
|
|
// SDConfig represents service discovery config for eureka.
|
|
|
|
//
|
|
|
|
// See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#eureka
|
|
|
|
type SDConfig struct {
|
2021-04-03 21:40:08 +00:00
|
|
|
Server string `yaml:"server,omitempty"`
|
2021-06-04 08:47:17 +00:00
|
|
|
HTTPClientConfig promauth.HTTPClientConfig `yaml:",inline"`
|
2021-10-26 18:21:08 +00:00
|
|
|
ProxyURL *proxy.URL `yaml:"proxy_url,omitempty"`
|
2021-04-03 21:40:08 +00:00
|
|
|
ProxyClientConfig promauth.ProxyClientConfig `yaml:",inline"`
|
2020-11-20 11:38:12 +00:00
|
|
|
// RefreshInterval time.Duration `yaml:"refresh_interval"`
|
|
|
|
// refresh_interval is obtained from `-promscrape.ec2SDCheckInterval` command-line option.
|
|
|
|
}
|
2020-11-20 12:00:12 +00:00
|
|
|
|
2020-11-20 11:38:12 +00:00
|
|
|
type applications struct {
|
|
|
|
Applications []Application `xml:"application"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Application - eureka application https://github.com/Netflix/eureka/wiki/Eureka-REST-operations/
|
|
|
|
type Application struct {
|
|
|
|
Name string `xml:"name"`
|
|
|
|
Instances []Instance `xml:"instance"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Port - eureka instance port.
|
|
|
|
type Port struct {
|
|
|
|
Port int `xml:",chardata"`
|
|
|
|
Enabled bool `xml:"enabled,attr"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instance - eureka instance https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
|
|
|
|
type Instance struct {
|
|
|
|
HostName string `xml:"hostName"`
|
|
|
|
HomePageURL string `xml:"homePageUrl"`
|
|
|
|
StatusPageURL string `xml:"statusPageUrl"`
|
|
|
|
HealthCheckURL string `xml:"healthCheckUrl"`
|
|
|
|
App string `xml:"app"`
|
|
|
|
IPAddr string `xml:"ipAddr"`
|
|
|
|
VipAddress string `xml:"vipAddress"`
|
|
|
|
SecureVipAddress string `xml:"secureVipAddress"`
|
|
|
|
Status string `xml:"status"`
|
|
|
|
Port Port `xml:"port"`
|
|
|
|
SecurePort Port `xml:"securePort"`
|
|
|
|
DataCenterInfo DataCenterInfo `xml:"dataCenterInfo"`
|
|
|
|
Metadata MetaData `xml:"metadata"`
|
|
|
|
CountryID int `xml:"countryId"`
|
|
|
|
InstanceID string `xml:"instanceId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// MetaData - eureka objects metadata.
|
|
|
|
type MetaData struct {
|
|
|
|
Items []Tag `xml:",any"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tag - eureka metadata tag - list of k/v values.
|
|
|
|
type Tag struct {
|
|
|
|
XMLName xml.Name
|
|
|
|
Content string `xml:",innerxml"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// DataCenterInfo -eureka datacentre metadata
|
|
|
|
type DataCenterInfo struct {
|
|
|
|
Name string `xml:"name"`
|
|
|
|
Metadata MetaData `xml:"metadata"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLabels returns Eureka labels according to sdc.
|
2021-02-26 13:53:42 +00:00
|
|
|
func (sdc *SDConfig) GetLabels(baseDir string) ([]map[string]string, error) {
|
2020-11-20 11:38:12 +00:00
|
|
|
cfg, err := getAPIConfig(sdc, baseDir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot get API config: %w", err)
|
|
|
|
}
|
2021-06-25 09:10:20 +00:00
|
|
|
data, err := getAPIResponse(cfg, "/apps")
|
2020-11-20 11:38:12 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
apps, err := parseAPIResponse(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-04-02 18:17:43 +00:00
|
|
|
return addInstanceLabels(apps), nil
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
|
|
|
|
2021-03-01 12:13:56 +00:00
|
|
|
// MustStop stops further usage for sdc.
|
|
|
|
func (sdc *SDConfig) MustStop() {
|
|
|
|
configMap.Delete(sdc)
|
|
|
|
}
|
|
|
|
|
2021-04-02 18:17:43 +00:00
|
|
|
func addInstanceLabels(apps *applications) []map[string]string {
|
2020-11-20 11:38:12 +00:00
|
|
|
var ms []map[string]string
|
2020-11-20 12:00:12 +00:00
|
|
|
for _, app := range apps.Applications {
|
2020-11-20 11:38:12 +00:00
|
|
|
for _, instance := range app.Instances {
|
2021-04-02 18:17:43 +00:00
|
|
|
instancePort := 80
|
2020-11-20 12:00:12 +00:00
|
|
|
if instance.Port.Port != 0 {
|
|
|
|
instancePort = instance.Port.Port
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
2020-11-20 12:00:12 +00:00
|
|
|
targetAddress := discoveryutils.JoinHostPort(instance.HostName, instancePort)
|
2020-11-20 11:38:12 +00:00
|
|
|
m := map[string]string{
|
2020-11-20 12:00:12 +00:00
|
|
|
"__address__": targetAddress,
|
|
|
|
"instance": instance.InstanceID,
|
|
|
|
"__meta_eureka_app_name": app.Name,
|
|
|
|
"__meta_eureka_app_instance_hostname": instance.HostName,
|
|
|
|
"__meta_eureka_app_instance_homepage_url": instance.HomePageURL,
|
|
|
|
"__meta_eureka_app_instance_statuspage_url": instance.StatusPageURL,
|
|
|
|
"__meta_eureka_app_instance_healthcheck_url": instance.HealthCheckURL,
|
|
|
|
"__meta_eureka_app_instance_ip_addr": instance.IPAddr,
|
|
|
|
"__meta_eureka_app_instance_vip_address": instance.VipAddress,
|
|
|
|
"__meta_eureka_app_instance_secure_vip_address": instance.SecureVipAddress,
|
|
|
|
"__meta_eureka_app_instance_status": instance.Status,
|
|
|
|
"__meta_eureka_app_instance_country_id": strconv.Itoa(instance.CountryID),
|
|
|
|
"__meta_eureka_app_instance_id": instance.InstanceID,
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
2020-11-20 12:00:12 +00:00
|
|
|
if instance.Port.Port != 0 {
|
2020-11-20 11:38:12 +00:00
|
|
|
m["__meta_eureka_app_instance_port"] = strconv.Itoa(instance.Port.Port)
|
|
|
|
m["__meta_eureka_app_instance_port_enabled"] = strconv.FormatBool(instance.Port.Enabled)
|
|
|
|
}
|
2020-11-20 12:00:12 +00:00
|
|
|
if instance.SecurePort.Port != 0 {
|
2020-11-20 11:38:12 +00:00
|
|
|
m["__meta_eureka_app_instance_secure_port"] = strconv.Itoa(instance.SecurePort.Port)
|
|
|
|
m["__meta_eureka_app_instance_secure_port_enabled"] = strconv.FormatBool(instance.SecurePort.Enabled)
|
|
|
|
|
|
|
|
}
|
|
|
|
if len(instance.DataCenterInfo.Name) > 0 {
|
|
|
|
m["__meta_eureka_app_instance_datacenterinfo_name"] = instance.DataCenterInfo.Name
|
|
|
|
for _, tag := range instance.DataCenterInfo.Metadata.Items {
|
|
|
|
m["__meta_eureka_app_instance_datacenterinfo_metadata_"+discoveryutils.SanitizeLabelName(tag.XMLName.Local)] = tag.Content
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, tag := range instance.Metadata.Items {
|
|
|
|
m["__meta_eureka_app_instance_metadata_"+discoveryutils.SanitizeLabelName(tag.XMLName.Local)] = tag.Content
|
|
|
|
}
|
|
|
|
ms = append(ms, m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ms
|
|
|
|
}
|