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"
|
2022-11-30 05:22:12 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
|
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.
|
2022-11-30 05:22:12 +00:00
|
|
|
func (sdc *SDConfig) GetLabels(baseDir string) ([]*promutils.Labels, 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)
|
|
|
|
}
|
|
|
|
|
2022-11-30 05:22:12 +00:00
|
|
|
func addInstanceLabels(apps *applications) []*promutils.Labels {
|
|
|
|
var ms []*promutils.Labels
|
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)
|
2022-11-30 05:22:12 +00:00
|
|
|
m := promutils.NewLabels(24)
|
|
|
|
m.Add("__address__", targetAddress)
|
|
|
|
m.Add("instance", instance.InstanceID)
|
|
|
|
m.Add("__meta_eureka_app_name", app.Name)
|
|
|
|
m.Add("__meta_eureka_app_instance_hostname", instance.HostName)
|
|
|
|
m.Add("__meta_eureka_app_instance_homepage_url", instance.HomePageURL)
|
|
|
|
m.Add("__meta_eureka_app_instance_statuspage_url", instance.StatusPageURL)
|
|
|
|
m.Add("__meta_eureka_app_instance_healthcheck_url", instance.HealthCheckURL)
|
|
|
|
m.Add("__meta_eureka_app_instance_ip_addr", instance.IPAddr)
|
|
|
|
m.Add("__meta_eureka_app_instance_vip_address", instance.VipAddress)
|
|
|
|
m.Add("__meta_eureka_app_instance_secure_vip_address", instance.SecureVipAddress)
|
|
|
|
m.Add("__meta_eureka_app_instance_status", instance.Status)
|
|
|
|
m.Add("__meta_eureka_app_instance_country_id", strconv.Itoa(instance.CountryID))
|
|
|
|
m.Add("__meta_eureka_app_instance_id", instance.InstanceID)
|
2020-11-20 12:00:12 +00:00
|
|
|
if instance.Port.Port != 0 {
|
2022-11-30 05:22:12 +00:00
|
|
|
m.Add("__meta_eureka_app_instance_port", strconv.Itoa(instance.Port.Port))
|
|
|
|
m.Add("__meta_eureka_app_instance_port_enabled", strconv.FormatBool(instance.Port.Enabled))
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
2020-11-20 12:00:12 +00:00
|
|
|
if instance.SecurePort.Port != 0 {
|
2022-11-30 05:22:12 +00:00
|
|
|
m.Add("__meta_eureka_app_instance_secure_port", strconv.Itoa(instance.SecurePort.Port))
|
|
|
|
m.Add("__meta_eureka_app_instance_secure_port_enabled", strconv.FormatBool(instance.SecurePort.Enabled))
|
2020-11-20 11:38:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
if len(instance.DataCenterInfo.Name) > 0 {
|
2022-11-30 05:22:12 +00:00
|
|
|
m.Add("__meta_eureka_app_instance_datacenterinfo_name", instance.DataCenterInfo.Name)
|
2020-11-20 11:38:12 +00:00
|
|
|
for _, tag := range instance.DataCenterInfo.Metadata.Items {
|
2022-11-30 05:22:12 +00:00
|
|
|
m.Add(discoveryutils.SanitizeLabelName("__meta_eureka_app_instance_datacenterinfo_metadata_"+tag.XMLName.Local), tag.Content)
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, tag := range instance.Metadata.Items {
|
2022-11-30 05:22:12 +00:00
|
|
|
m.Add(discoveryutils.SanitizeLabelName("__meta_eureka_app_instance_metadata_"+tag.XMLName.Local), tag.Content)
|
2020-11-20 11:38:12 +00:00
|
|
|
}
|
|
|
|
ms = append(ms, m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ms
|
|
|
|
}
|