mirror of
https://github.com/openfaas/faas.git
synced 2025-06-22 23:03:24 +00:00
Add namespace in function name for metrics
This commit adds namespace in function names while logging metrics to prometheus, irrespective of the function is invoked with namespace suffix or not. This is also required to add multiple namespace support to faas-idler https://github.com/openfaas-incubator/faas-idler/issues/37 which is part of https://github.com/openfaas/faas-netes/issues/511 Signed-off-by: Vivek Singh <vivekkmr45@yahoo.in>
This commit is contained in:
@ -6,10 +6,12 @@ package metrics
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"log"
|
||||
@ -56,8 +58,14 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
||||
|
||||
e.metricOptions.ServiceReplicasGauge.Reset()
|
||||
for _, service := range e.services {
|
||||
var serviceName string
|
||||
if len(service.Namespace) > 0 {
|
||||
serviceName = fmt.Sprintf("%s.%s", service.Name, service.Namespace)
|
||||
} else {
|
||||
serviceName = service.Name
|
||||
}
|
||||
e.metricOptions.ServiceReplicasGauge.
|
||||
WithLabelValues(service.Name).
|
||||
WithLabelValues(serviceName).
|
||||
Set(float64(service.Replicas))
|
||||
}
|
||||
|
||||
@ -72,9 +80,46 @@ func (e *Exporter) StartServiceWatcher(endpointURL url.URL, metricsOptions Metri
|
||||
ticker := time.NewTicker(interval)
|
||||
quit := make(chan struct{})
|
||||
|
||||
timeout := 3 * time.Second
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
|
||||
proxyClient := http.Client{
|
||||
namespaces, err := e.getNamespaces(endpointURL)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if len(namespaces) == 0 {
|
||||
emptyNamespace := ""
|
||||
services, err := e.getFunctions(endpointURL, emptyNamespace)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
e.services = services
|
||||
} else {
|
||||
for _, namespace := range namespaces {
|
||||
services, err := e.getFunctions(endpointURL, namespace)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
e.services = append(e.services, services...)
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (e *Exporter) getHTTPClient(timeout time.Duration) http.Client {
|
||||
|
||||
return http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
@ -87,45 +132,70 @@ func (e *Exporter) StartServiceWatcher(endpointURL url.URL, metricsOptions Metri
|
||||
ExpectContinueTimeout: 1500 * time.Millisecond,
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
|
||||
get, err := http.NewRequest(http.MethodGet, endpointURL.String()+"system/functions", nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if e.credentials != nil {
|
||||
get.SetBasicAuth(e.credentials.User, e.credentials.Password)
|
||||
}
|
||||
|
||||
services := []types.FunctionStatus{}
|
||||
res, err := proxyClient.Do(get)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
bytesOut, readErr := ioutil.ReadAll(res.Body)
|
||||
if readErr != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
unmarshalErr := json.Unmarshal(bytesOut, &services)
|
||||
if unmarshalErr != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
e.services = services
|
||||
|
||||
break
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (e *Exporter) getFunctions(endpointURL url.URL, namespace string) ([]types.FunctionStatus, error) {
|
||||
timeout := 3 * time.Second
|
||||
proxyClient := e.getHTTPClient(timeout)
|
||||
|
||||
endpointURL.Path = path.Join(endpointURL.Path, "/system/functions")
|
||||
if len(namespace) > 0 {
|
||||
q := endpointURL.Query()
|
||||
q.Set("namespace", namespace)
|
||||
endpointURL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
get, _ := http.NewRequest(http.MethodGet, endpointURL.String(), nil)
|
||||
if e.credentials != nil {
|
||||
get.SetBasicAuth(e.credentials.User, e.credentials.Password)
|
||||
}
|
||||
|
||||
services := []types.FunctionStatus{}
|
||||
res, err := proxyClient.Do(get)
|
||||
if err != nil {
|
||||
return services, err
|
||||
}
|
||||
|
||||
bytesOut, readErr := ioutil.ReadAll(res.Body)
|
||||
if readErr != nil {
|
||||
return services, readErr
|
||||
}
|
||||
|
||||
unmarshalErr := json.Unmarshal(bytesOut, &services)
|
||||
if unmarshalErr != nil {
|
||||
return services, unmarshalErr
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (e *Exporter) getNamespaces(endpointURL url.URL) ([]string, error) {
|
||||
namespaces := []string{}
|
||||
|
||||
get, _ := http.NewRequest(http.MethodGet, endpointURL.String()+"system/namespaces", nil)
|
||||
if e.credentials != nil {
|
||||
get.SetBasicAuth(e.credentials.User, e.credentials.Password)
|
||||
}
|
||||
|
||||
timeout := 3 * time.Second
|
||||
proxyClient := e.getHTTPClient(timeout)
|
||||
|
||||
res, err := proxyClient.Do(get)
|
||||
if err != nil {
|
||||
return namespaces, err
|
||||
}
|
||||
|
||||
if res.StatusCode == http.StatusNotFound {
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
bytesOut, readErr := ioutil.ReadAll(res.Body)
|
||||
if readErr != nil {
|
||||
return namespaces, readErr
|
||||
}
|
||||
|
||||
unmarshalErr := json.Unmarshal(bytesOut, &namespaces)
|
||||
if unmarshalErr != nil {
|
||||
return namespaces, unmarshalErr
|
||||
}
|
||||
return namespaces, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user