From f90edad370781361c2d2864244ebc789ab7cb5d9 Mon Sep 17 00:00:00 2001 From: Vitaliy Guschin Date: Thu, 23 May 2024 12:08:04 +0400 Subject: [PATCH] Add an image with profiling enabled. Signed-off-by: Vitaliy Guschin --- .github/workflows/release.yml | 1 + Dockerfile | 8 ++++++-- README.md | 1 + internal/config/config.go | 1 + internal/imports/imports_linux.go | 2 ++ main.go | 5 +++++ profiler_off.go | 7 +++++++ profiler_on.go | 31 +++++++++++++++++++++++++++++++ 8 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 profiler_off.go create mode 100644 profiler_on.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8fcf39e9..dc5e766c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,7 @@ jobs: uses: networkservicemesh/.github/.github/workflows/docker-release.yaml@main with: tag: ${{ needs.get-tag.outputs.tag }} + build_with_profiler: true secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index c6edeb04..5a99d443 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,12 +3,12 @@ ENV GO111MODULE=on ENV CGO_ENABLED=0 ENV GOBIN=/bin ARG BUILDARCH=amd64 +ARG ENABLE_PROFILER=false RUN go install github.com/go-delve/delve/cmd/dlv@v1.8.2 RUN go install github.com/grpc-ecosystem/grpc-health-probe@v0.4.25 ADD https://github.com/spiffe/spire/releases/download/v1.8.0/spire-1.8.0-linux-${BUILDARCH}-musl.tar.gz . RUN tar xzvf spire-1.8.0-linux-${BUILDARCH}-musl.tar.gz -C /bin --strip=2 spire-1.8.0/bin/spire-server spire-1.8.0/bin/spire-agent - FROM go as build WORKDIR /build COPY go.mod go.sum ./ @@ -16,7 +16,11 @@ COPY ./local ./local COPY ./internal/imports ./internal/imports RUN go build ./internal/imports COPY . . -RUN go build -o /bin/nsmgr . +RUN if [ "$ENABLE_PROFILER" = "true" ]; then \ + go build -tags profiler -o /bin/nsmgr . ; \ + else \ + go build -o /bin/nsmgr . ; \ + fi FROM build as test CMD go test -test.v ./... diff --git a/README.md b/README.md index 4f13ad3a..4eb11173 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ docker build . * `NSM_FORWARDER_NETWORK_SERVICE_NAME` - the default service name for forwarder discovering (default: "forwarder") * `NSM_OPEN_TELEMETRY_ENDPOINT` - OpenTelemetry Collector Endpoint (default: "otel-collector.observability.svc.cluster.local:4317") * `NSM_METRICS_EXPORT_INTERVAL` - interval between mertics exports (default: "10s") +* `NSM_PROFILER_HTTP_PORT` - Profiling server HTTP port providing data in the format expected by the pprof visualization tool. Profiler is running only on images with the "-pprof" tag suffix (default: "6060") # Testing diff --git a/internal/config/config.go b/internal/config/config.go index 3a0e8c32..e28d246c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -37,4 +37,5 @@ type Config struct { ForwarderNetworkServiceName string `default:"forwarder" desc:"the default service name for forwarder discovering" split_words:"true"` OpenTelemetryEndpoint string `default:"otel-collector.observability.svc.cluster.local:4317" desc:"OpenTelemetry Collector Endpoint" split_words:"true"` MetricsExportInterval time.Duration `default:"10s" desc:"interval between mertics exports" split_words:"true"` + ProfilerHTTPPort uint16 `default:"6060" desc:"Profiling server HTTP port providing data in the format expected by the pprof visualization tool. Profiler is running only on images with the '-pprof' tag suffix" split_words:"true"` } diff --git a/internal/imports/imports_linux.go b/internal/imports/imports_linux.go index 7aedaeb5..ffc6889b 100644 --- a/internal/imports/imports_linux.go +++ b/internal/imports/imports_linux.go @@ -55,6 +55,8 @@ import ( _ "google.golang.org/grpc/health/grpc_health_v1" _ "google.golang.org/grpc/peer" _ "net" + _ "net/http" + _ "net/http/pprof" _ "net/url" _ "os" _ "os/signal" diff --git a/main.go b/main.go index 7e945672..7440d3a5 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,8 @@ // // Copyright (c) 2021-2023 Doc.ai and/or its affiliates. // +// Copyright (c) 2024 Pragmagic Inc. and/or its affiliates. +// // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,6 +77,9 @@ func main() { logrus.SetLevel(level) log.EnableTracing(true) + // Start profiling server + startProfiler(ctx, cfg.ProfilerHTTPPort) + // Configure Open Telemetry if opentelemetry.IsEnabled() { collectorAddress := cfg.OpenTelemetryEndpoint diff --git a/profiler_off.go b/profiler_off.go new file mode 100644 index 00000000..43316494 --- /dev/null +++ b/profiler_off.go @@ -0,0 +1,7 @@ +//go:build !profiler + +package main + +import "context" + +func startProfiler(ctx context.Context, profilerHTTPPort uint16) {} diff --git a/profiler_on.go b/profiler_on.go new file mode 100644 index 00000000..d1ccbf4d --- /dev/null +++ b/profiler_on.go @@ -0,0 +1,31 @@ +//go:build profiler + +package main + +import ( + "context" + "fmt" + "net/http" + _ "net/http/pprof" // #nosec + "time" + + "github.com/networkservicemesh/sdk/pkg/tools/log" +) + +func startProfiler(ctx context.Context, profilerHTTPPort uint16) { + go func() { + log.FromContext(ctx).Infof("Profiler is enabled. Starting HTTP server on %d", profilerHTTPPort) + + address := fmt.Sprintf("localhost:%d", profilerHTTPPort) + + server := &http.Server{ + Addr: address, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + } + + if err := server.ListenAndServe(); err != nil { + log.FromContext(ctx).Errorf("Failed to start profiler: %s", err.Error()) + } + }() +}