Skip to content

Commit

Permalink
Add metric
Browse files Browse the repository at this point in the history
  • Loading branch information
mustard-mh committed Nov 13, 2023
1 parent e1dcb63 commit 198d71d
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 21 deletions.
6 changes: 6 additions & 0 deletions components/common-go/experiments/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ func WithGitpodProxy(gitpodHost string) ClientOpt {
}
}

func WithPollInterval(interval time.Duration) ClientOpt {
return func(o *options) {
o.pollInterval = interval
}
}

func WithDefaultClient(defaultClient Client) ClientOpt {
return func(o *options) {
o.defaultClient = defaultClient
Expand Down
37 changes: 26 additions & 11 deletions components/service-waiter/cmd/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package cmd
import (
"context"
"fmt"
"strconv"
"time"

"github.com/sirupsen/logrus"
Expand All @@ -15,17 +16,20 @@ import (

"github.com/gitpod-io/gitpod/common-go/experiments"
"github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/service-waiter/pkg/metrics"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

var componentCmdOpt struct {
image string
namespace string
component string
labels string
image string
namespace string
component string
labels string
ideMetricsHost string
gitpodHost string

featureFlagTimeout time.Duration
}
Expand Down Expand Up @@ -138,7 +142,9 @@ func init() {
componentCmd.Flags().StringVar(&componentCmdOpt.namespace, "namespace", "", "The namespace of deployment")
componentCmd.Flags().StringVar(&componentCmdOpt.component, "component", "", "Component name of deployment")
componentCmd.Flags().StringVar(&componentCmdOpt.labels, "labels", "", "Labels of deployment")
componentCmd.Flags().StringVar(&componentCmdOpt.ideMetricsHost, "ide-metrics-host", "", "Host of ide metrics")
componentCmd.Flags().DurationVar(&componentCmdOpt.featureFlagTimeout, "feature-flag-timeout", 3*time.Minute, "The maximum time to wait for feature flag")
componentCmd.Flags().StringVar(&componentCmdOpt.gitpodHost, "gitpod-host", "", "Domain of Gitpod installation")

_ = componentCmd.MarkFlagRequired("namespace")
_ = componentCmd.MarkFlagRequired("component")
Expand All @@ -148,18 +154,26 @@ func init() {
func startWaitFeatureFlag(ctx context.Context, timeout time.Duration) {
featureFlagCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
client := experiments.NewClient(experiments.WithDefaultClient(nil))
client := experiments.NewClient(experiments.WithDefaultClient(nil), experiments.WithPollInterval(time.Second*3))
defaultSkip := true
if client == nil {
log.Error("failed to create experiments client, skip immediately")
shouldSkipComponentWaiter = defaultSkip
metrics.AddSkipComponentsCounter(componentCmdOpt.ideMetricsHost, strconv.FormatBool(shouldSkipComponentWaiter), false)
return
}
startTime := time.Now()
value, isActualValue, fetchTimes := ActualWaitFeatureFlag(featureFlagCtx, client, defaultSkip)
avgTime := time.Since(startTime) / time.Duration(fetchTimes)
log.WithField("fetchTimes", fetchTimes).WithField("avgTime", avgTime).WithField("isActualValue", isActualValue).WithField("value", value).Info("get final value of feature flag")
shouldSkipComponentWaiter = value
getShouldSkipComponentWaiter := func() {
startTime := time.Now()
value, isActualValue, fetchTimes := ActualWaitFeatureFlag(featureFlagCtx, client, defaultSkip)
avgTime := time.Since(startTime) / time.Duration(fetchTimes)
log.WithField("fetchTimes", fetchTimes).WithField("avgTime", avgTime).WithField("isActualValue", isActualValue).WithField("value", value).Info("get final value of feature flag")
shouldSkipComponentWaiter = value
metrics.AddSkipComponentsCounter(componentCmdOpt.ideMetricsHost, strconv.FormatBool(shouldSkipComponentWaiter), isActualValue)
}
for !shouldSkipComponentWaiter {
getShouldSkipComponentWaiter()
time.Sleep(1 * time.Second)
}
}

var FeatureSleepDuration = 1 * time.Second
Expand All @@ -175,7 +189,8 @@ func ActualWaitFeatureFlag(ctx context.Context, client experiments.Client, defau
return defaultValue, false, fetchTimes
default:
stringValue := client.GetStringValue(ctx, experiments.ServiceWaiterSkipComponentsFlag, "NONE", experiments.Attributes{
Component: componentCmdOpt.component,
GitpodHost: componentCmdOpt.gitpodHost,
Component: componentCmdOpt.component,
})
fetchTimes++
if stringValue == "true" {
Expand Down
51 changes: 51 additions & 0 deletions components/service-waiter/pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package metrics

import (
"bytes"
"encoding/json"
"net/http"
"strconv"

"github.com/gitpod-io/gitpod/common-go/log"
)

// service_waiter_skip_components
const WaitComponentFeatureFlagMetricName = "service_waiter_skip_components_result_total"

func AddSkipComponentsCounter(host, value string, isActual bool) {
labels := map[string]string{
"value": value,
"ok": strconv.FormatBool(isActual),
}
addCounter(host, WaitComponentFeatureFlagMetricName, labels)
}

func addCounter(host, metricName string, labels map[string]string) {
if host == "" {
log.Error("host is empty")
return
}
body := map[string]interface{}{
"labels": labels,
"value": 1,
}
b, err := json.Marshal(body)
if err != nil {
log.WithError(err).Error("cannot marshal body")
return
}
resp, err := http.Post(host+"/metrics-api/metrics/counter/add/"+metricName, "application/json", bytes.NewReader(b))
if err != nil {
log.WithError(err).Error("cannot post metrics")
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.WithField("status", resp.Status).Error("failed to post metrics")
}
log.Info("metric reported")
}
7 changes: 5 additions & 2 deletions install/installer/pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,6 @@ func RedisWaiterContainer(ctx *RenderContext) *corev1.Container {
// ServerComponentWaiterContainer is the container used to wait for the deployment/server to be ready
// it requires
// - pods list access to the cluster
// - configcat env
func ServerComponentWaiterContainer(ctx *RenderContext) *corev1.Container {
image := ctx.ImageName(ctx.Config.Repository, ServerComponent, ctx.VersionManifest.Components.Server.Version)
return componentWaiterContainer(ctx, ServerComponent, DefaultLabelSelector(ServerComponent), image)
Expand All @@ -521,7 +520,6 @@ func ServerComponentWaiterContainer(ctx *RenderContext) *corev1.Container {
// PublicApiServerComponentWaiterContainer is the container used to wait for the deployment/public-api-server to be ready
// it requires
// - pods list access to the cluster
// - configcat env
func PublicApiServerComponentWaiterContainer(ctx *RenderContext) *corev1.Container {
image := ctx.ImageName(ctx.Config.Repository, PublicApiComponent, ctx.VersionManifest.Components.PublicAPIServer.Version)
return componentWaiterContainer(ctx, PublicApiComponent, DefaultLabelSelector(PublicApiComponent), image)
Expand All @@ -534,6 +532,10 @@ func componentWaiterContainer(ctx *RenderContext, component, labels, image strin
Args: []string{
"-v",
"component",
"--gitpod-host",
ctx.Config.Domain,
"--ide-metrics-host",
"http://" + IDEMetricsComponent + ":" + strconv.Itoa(IDEMetricsPort),
"--namespace",
ctx.Namespace,
"--component",
Expand All @@ -548,6 +550,7 @@ func componentWaiterContainer(ctx *RenderContext, component, labels, image strin
AllowPrivilegeEscalation: pointer.Bool(false),
RunAsUser: pointer.Int64(31001),
},
Env: ConfigcatEnv(ctx),
}
}

Expand Down
7 changes: 5 additions & 2 deletions install/installer/pkg/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package common_test

import (
"fmt"
"strconv"
"testing"

"github.com/gitpod-io/gitpod/common-go/baseserver"
Expand Down Expand Up @@ -58,7 +59,8 @@ func TestPublicApiServerComponentWaiterContainer(t *testing.T) {
container := common.PublicApiServerComponentWaiterContainer(ctx)
labels := common.DefaultLabelSelector(common.PublicApiComponent)
require.Equal(t, labels, "app=gitpod,component=public-api-server")
require.Equal(t, []string{"-v", "component", "--namespace", "test_namespace", "--component", common.PublicApiComponent, "--labels", labels, "--image", ctx.Config.Repository + "/public-api-server:" + "happy_path_papi_image"}, container.Args)
ideMetricsHost := "http://" + common.IDEMetricsComponent + ":" + strconv.Itoa(common.IDEMetricsPort)
require.Equal(t, []string{"-v", "component", "--gitpod-host", ctx.Config.Domain, "--ide-metrics-host", ideMetricsHost, "--namespace", "test_namespace", "--component", common.PublicApiComponent, "--labels", labels, "--image", ctx.Config.Repository + "/public-api-server:" + "happy_path_papi_image"}, container.Args)
}

func TestServerComponentWaiterContainer(t *testing.T) {
Expand All @@ -71,5 +73,6 @@ func TestServerComponentWaiterContainer(t *testing.T) {
container := common.ServerComponentWaiterContainer(ctx)
labels := common.DefaultLabelSelector(common.ServerComponent)
require.Equal(t, labels, "app=gitpod,component=server")
require.Equal(t, []string{"-v", "component", "--namespace", "test_namespace", "--component", common.ServerComponent, "--labels", labels, "--image", ctx.Config.Repository + "/server:" + "happy_path_server_image"}, container.Args)
ideMetricsHost := "http://" + common.IDEMetricsComponent + ":" + strconv.Itoa(common.IDEMetricsPort)
require.Equal(t, []string{"-v", "component", "--gitpod-host", ctx.Config.Domain, "--ide-metrics-host", ideMetricsHost, "--namespace", "test_namespace", "--component", common.ServerComponent, "--labels", labels, "--image", ctx.Config.Repository + "/server:" + "happy_path_server_image"}, container.Args)
}
3 changes: 3 additions & 0 deletions install/installer/pkg/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ const (
AuthPKISecretName = "auth-pki"
IDEServiceComponent = "ide-service"
OpenVSXProxyComponent = "openvsx-proxy"
DashboardComponent = "dashboard"
IDEMetricsComponent = "ide-metrics"
IDEMetricsPort = 3000
)

var (
Expand Down
4 changes: 3 additions & 1 deletion install/installer/pkg/components/dashboard/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

package dashboard

import "github.com/gitpod-io/gitpod/installer/pkg/common"

const (
Component = "dashboard"
Component = common.DashboardComponent
ContainerPort = 80
PortName = "http"
ServicePort = 3001
Expand Down
1 change: 0 additions & 1 deletion install/installer/pkg/components/dashboard/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ func deployment(ctx *common.RenderContext) ([]runtime.Object, error) {
},
Env: common.CustomizeEnvvar(ctx, Component, common.MergeEnv(
common.DefaultEnv(&ctx.Config),
common.ConfigcatEnv(ctx),
)),
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
Expand Down
17 changes: 17 additions & 0 deletions install/installer/pkg/components/ide-metrics/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,23 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) {
},
},
},
{
Name: "service_waiter_skip_components_result_total",
Help: "Total number of wait result of service_waiter/component service_waiter_skip_components flag",
Labels: []config.LabelAllowList{
{
Name: "value",
// possible values "true", "false"
AllowValues: []string{"*"},
DefaultValue: "NONE",
},
{
Name: "ok",
AllowValues: []string{"true", "false"},
DefaultValue: "false",
},
},
},
}

histogramMetrics := []config.HistogramMetricsConfiguration{
Expand Down
10 changes: 6 additions & 4 deletions install/installer/pkg/components/ide-metrics/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

package ide_metrics

import "github.com/gitpod-io/gitpod/installer/pkg/common"

const (
Component = "ide-metrics"
ContainerPort = 3000
Component = common.IDEMetricsComponent
ContainerPort = common.IDEMetricsPort
PortName = "http"
ServicePort = 3000
ReadinessPort = 3000
ServicePort = common.IDEMetricsPort
ReadinessPort = common.IDEMetricsPort
VolumeConfig = "config"
)
4 changes: 4 additions & 0 deletions install/installer/pkg/components/ide-metrics/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func networkpolicy(ctx *common.RenderContext) ([]runtime.Object, error) {
PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{
"component": ideproxy.Component,
}},
}, {
PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{
"component": common.DashboardComponent,
}},
}},
}},
},
Expand Down
4 changes: 4 additions & 0 deletions install/installer/pkg/components/proxy/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ func networkpolicy(ctx *common.RenderContext) ([]runtime.Object, error) {
PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{
"component": common.OpenVSXProxyComponent,
}},
}, {
PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{
"component": common.DashboardComponent,
}},
}},
}},
},
Expand Down

0 comments on commit 198d71d

Please sign in to comment.