Skip to content

Laushinka/add metrics for server 9824 #9863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions components/public-api-server/pkg/proxy/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
gitpod "github.com/gitpod-io/gitpod/gitpod-protocol"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"net/url"
"time"
)

type ServerConnectionPool interface {
Expand All @@ -26,6 +27,10 @@ type NoConnectionPool struct {
func (p *NoConnectionPool) Get(ctx context.Context, token string) (gitpod.APIInterface, error) {
logger := ctxlogrus.Extract(ctx)

start := time.Now()
defer func() {
reportConnectionDuration(time.Since(start))
}()
server, err := gitpod.ConnectToServer(p.ServerAPI.String(), gitpod.ConnectToServerOpts{
Context: ctx,
Token: token,
Expand Down
24 changes: 24 additions & 0 deletions components/public-api-server/pkg/proxy/prometheusmetrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2022 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 proxy

import (
"github.com/prometheus/client_golang/prometheus"
"time"
)

func reportConnectionDuration(d time.Duration) {
proxyConnectionCreateDurationSeconds.Observe(d.Seconds())
}

var proxyConnectionCreateDurationSeconds = prometheus.NewHistogram(prometheus.HistogramOpts{
Namespace: "gitpod",
Name: "public_api_proxy_connection_create_duration_seconds",
Help: "Histogram of connection time in seconds",
})

func RegisterMetrics(registry *prometheus.Registry) {
registry.MustRegister(proxyConnectionCreateDurationSeconds)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2022 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 proxy

import (
"context"
"github.com/gitpod-io/gitpod/common-go/baseserver"
v1 "github.com/gitpod-io/gitpod/public-api/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
"testing"
)

func TestConnectionCreationWasTracked(t *testing.T) {
// Set up server
srv := baseserver.NewForTests(t)
baseserver.StartServerForTests(t, srv)

// Set up Prometheus registry
registry := prometheus.NewRegistry()
registry.MustRegister(proxyConnectionCreateDurationSeconds)

// Set up Workspace client
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "some-token")
conn, _ := grpc.Dial(srv.GRPCAddress(), grpc.WithTransportCredentials(insecure.NewCredentials()))
client := v1.NewWorkspacesServiceClient(conn)

// Call GetWorkspace
client.GetWorkspace(ctx, &v1.GetWorkspaceRequest{
WorkspaceId: "some-ID",
})

count, err := testutil.GatherAndCount(registry)
assert.NoError(t, err)
assert.Equal(t, 1, count)
}
7 changes: 5 additions & 2 deletions components/public-api-server/pkg/server/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"github.com/gitpod-io/gitpod/common-go/baseserver"
v1 "github.com/gitpod-io/gitpod/public-api/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
Expand All @@ -21,11 +22,12 @@ import (
func TestPublicAPIServer_v1_WorkspaceService(t *testing.T) {
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "some-token")
srv := baseserver.NewForTests(t)
registry := prometheus.NewRegistry()

gitpodAPI, err := url.Parse("wss://main.preview.gitpod-dev.com/api/v1")
require.NoError(t, err)

require.NoError(t, register(srv, Config{GitpodAPI: gitpodAPI}))
require.NoError(t, register(srv, Config{GitpodAPI: gitpodAPI}, registry))
baseserver.StartServerForTests(t, srv)

conn, err := grpc.Dial(srv.GRPCAddress(), grpc.WithTransportCredentials(insecure.NewCredentials()))
Expand Down Expand Up @@ -67,11 +69,12 @@ func TestPublicAPIServer_v1_WorkspaceService(t *testing.T) {
func TestPublicAPIServer_v1_PrebuildService(t *testing.T) {
ctx := context.Background()
srv := baseserver.NewForTests(t)
registry := prometheus.NewRegistry()

gitpodAPI, err := url.Parse("wss://main.preview.gitpod-dev.com/api/v1")
require.NoError(t, err)

require.NoError(t, register(srv, Config{GitpodAPI: gitpodAPI}))
require.NoError(t, register(srv, Config{GitpodAPI: gitpodAPI}, registry))

baseserver.StartServerForTests(t, srv)

Expand Down
10 changes: 8 additions & 2 deletions components/public-api-server/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,25 @@ import (
"github.com/gitpod-io/gitpod/public-api-server/pkg/apiv1"
"github.com/gitpod-io/gitpod/public-api-server/pkg/proxy"
v1 "github.com/gitpod-io/gitpod/public-api/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"net/http"
)

func Start(logger *logrus.Entry, cfg Config) error {
registry := prometheus.NewRegistry()

srv, err := baseserver.New("public_api_server",
baseserver.WithLogger(logger),
baseserver.WithHTTPPort(cfg.HTTPPort),
baseserver.WithGRPCPort(cfg.GRPCPort),
baseserver.WithMetricsRegistry(registry),
)
if err != nil {
return fmt.Errorf("failed to initialize public api server: %w", err)
}

if registerErr := register(srv, cfg); registerErr != nil {
if registerErr := register(srv, cfg, registry); registerErr != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of this part being quite not ergonomic, I've raised #9879 which allows us to do srv.MetricsRegistry() to get access to the registry. It just reduces the need to pass the registry along in a side-channel. We can update later if this PR lands first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

return fmt.Errorf("failed to register services: %w", registerErr)
}

Expand All @@ -37,7 +41,9 @@ func Start(logger *logrus.Entry, cfg Config) error {
return nil
}

func register(srv *baseserver.Server, cfg Config) error {
func register(srv *baseserver.Server, cfg Config, registry *prometheus.Registry) error {
proxy.RegisterMetrics(registry)

logger := log.New()
m := middleware.NewLoggingMiddleware(logger)
srv.HTTPMux().Handle("/", m(http.HandlerFunc(HelloWorldHandler)))
Expand Down