diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 83d17ff..80da9a3 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -31,7 +31,7 @@ jobs: - name: Lint Playground uses: golangci/golangci-lint-action@v6 with: - version: v1.63.4 + version: v1.64.5 # Sandbox @@ -42,5 +42,5 @@ jobs: - name: Lint sandbox uses: golangci/golangci-lint-action@v6 with: - version: v1.63.4 + version: v1.64.5 working-directory: sandbox diff --git a/.golangci.yml b/.golangci.yml index 2abf744..cbd089b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,7 +6,6 @@ run: # When enabled linter will skip directories: vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ # Skipping `examples` sounds scary to me but skipping `testdata` sounds ok. - # This file contains only configs which differ from defaults. # All possible options can be found here https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml linters-settings: @@ -172,7 +171,7 @@ linters: - gocritic # provides diagnostics that check for bugs, performance and style issues - gocyclo # computes and checks the cyclomatic complexity of functions # - godot # checks if comments end in a period - - goimports # in addition to fixing imports, goimports also formats your code in the same style as gofmt +# - goimports # in addition to fixing imports, goimports also formats your code in the same style as gofmt # - mnd # detects magic numbers - gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod - gomodguard # allow and block lists linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations @@ -190,7 +189,7 @@ linters: # - nonamedreturns # reports all named returns - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL - predeclared # finds code that shadows one of Go's predeclared identifiers - - promlinter # checks Prometheus metrics naming via promlint +# - promlinter # checks Prometheus metrics naming via promlint - reassign # checks that package variables are not reassigned # - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint - rowserrcheck # checks whether Err of rows is checked successfully diff --git a/Dockerfile b/Dockerfile index 2d144ee..d683077 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,11 @@ # Initial stage: download modules -FROM golang:1.23 as modules +FROM golang:1.24 as modules ADD go.mod go.sum /m/ RUN cd /m && go mod download # Intermediate stage: Build the binary -FROM golang:1.23 as builder +FROM golang:1.24 as builder COPY --from=modules /go/pkg /go/pkg @@ -45,7 +45,7 @@ LABEL org.opencontainers.image.description="The open-source sandbox based on Doc LABEL org.opencontainers.image.licenses="Apache-2.0" LABEL org.opencontainers.image.revision="${LABEL_COMMIT}" LABEL org.opencontainers.image.source="https://github.com/codiewio/codenire" -LABEL org.opencontainers.image.title="Codenire" -LABEL org.opencontainers.image.url="https://codenire.com" -#LABEL org.opencontainers.image.vendor="Codiew INC" +LABEL org.opencontainers.image.title="Codenire Playground" +LABEL org.opencontainers.image.url="https://codenire.io" +LABEL org.opencontainers.image.vendor="I/E Maksim Fedorov" LABEL org.opencontainers.image.version="${LABEL_VERSION}" \ No newline at end of file diff --git a/go.mod b/go.mod index 3a8c8e6..6bf5276 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect @@ -23,6 +23,7 @@ require ( github.com/lestrrat-go/jwx/v2 v2.1.3 // indirect github.com/lestrrat-go/option v1.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect + github.com/stretchr/testify v1.10.0 // indirect golang.org/x/crypto v0.32.0 // indirect golang.org/x/net v0.34.0 // indirect golang.org/x/sync v0.11.0 // indirect diff --git a/go.sum b/go.sum index 171b903..9465ad6 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= @@ -70,8 +70,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/internal/handler/server.go b/internal/handler/server.go index 4902da9..9e4f2b6 100644 --- a/internal/handler/server.go +++ b/internal/handler/server.go @@ -5,11 +5,13 @@ package handler import ( + "context" "fmt" "io" "net/http" "time" + "github.com/codiewio/codenire/internal/client" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" @@ -78,6 +80,36 @@ func NewServer(config *Config) (*http.Server, error) { }) }) + router.Get("/metrics", func(w http.ResponseWriter, r *http.Request) { + req, err := http.NewRequestWithContext( + context.Background(), + http.MethodGet, + handler.Config.BackendURL+"/metrics", + nil, + ) + + if err != nil { + http.Error(w, "sandbox client metrics request error", http.StatusInternalServerError) + return + } + + resp, err := client.SandboxBackendClient().Do(req) + if err != nil { + http.Error(w, "Failed to fetch metrics from other service", http.StatusInternalServerError) + return + } + defer func() { + _ = resp.Body.Close() + }() + + w.Header().Set("Content-Type", resp.Header.Get("Content-Type")) + _, err = io.Copy(w, resp.Body) + if err != nil { + http.Error(w, "Failed to write metrics to response", http.StatusInternalServerError) + return + } + }) + return &http.Server{ Addr: ":" + config.Port, ReadHeaderTimeout: 5 * time.Second, diff --git a/main.go b/main.go index df11b25..68a9011 100644 --- a/main.go +++ b/main.go @@ -45,14 +45,17 @@ import ( ) var ( - backendURL = flag.String("backend-url", "http://sandbox_dev", "URL for sandbox backend that runs Go binaries.") - Port = flag.String("port", "8081", "URL for sandbox backend that runs Go binaries.") - PluginHookPath = flag.String("hooks-plugins", "", "URL for sandbox backend that runs Go binaries.") - FileHooksDir = flag.String("hooks-dir", "", "Directory to search for available hooks scripts") + backendURL = flag.String("backend-url", "http://sandbox_dev", "URL for sandbox backend that runs Go binaries.") + Port = flag.String("port", "8081", "URL for sandbox backend that runs Go binaries.") + PluginHookPath = flag.String("hooks-plugins", "", "URL for sandbox backend that runs Go binaries.") + FileHooksDir = flag.String("hooks-dir", "", "Directory to search for available hooks scripts") + + // deprecated ExternalTemplates = flag.String("external-templates", "", "Comma separated list of templates which will handled externally (plugin for example)") - ThrottleLimit = flag.Int("throttle-limit", 15, "currently processed requests at a time across all users") - JWTSecretKey = flag.String("jwt-secret-key", "", "secret key to enable authentication") - dev = flag.Bool("dev", false, "run in dev mode") + + ThrottleLimit = flag.Int("throttle-limit", 15, "currently processed requests at a time across all users") + JWTSecretKey = flag.String("jwt-secret-key", "", "secret key to enable authentication") + dev = flag.Bool("dev", false, "run in dev mode") CorsAllowOrigin = flag.String("cors-allow-origin", "*", "Regular expression used to determine if the Origin header is allowed. If not, no CORS headers will be sent. By default, all origins are allowed.") CorsAllowCredentials = flag.Bool("cors-allow-credentials", false, "Allow credentials by setting Access-Control-Allow-Credentials: true") diff --git a/sandbox/Dockerfile b/sandbox/Dockerfile index aec881d..73993c2 100644 --- a/sandbox/Dockerfile +++ b/sandbox/Dockerfile @@ -4,14 +4,14 @@ # environment so the sandbox server can connect to the host's # docker daemon, which has the gvisor "runsc" runtime available. -FROM golang:1.22 AS modules +FROM golang:1.24 AS modules ADD go.mod go.sum /m/ RUN cd /m && go mod download # Intermediate stage: Build the binary -FROM golang:1.22 as builder +FROM golang:1.24 as builder COPY --from=modules /go/pkg /go/pkg @@ -57,3 +57,13 @@ COPY --from=builder /app/bin/sandbox /usr/local/bin/sandbox ADD dockerfiles /dockerfiles ENTRYPOINT ["/usr/local/bin/sandbox"] + + +LABEL org.opencontainers.image.description="The open-source sandbox based on Docker containers and Google gVisor." +LABEL org.opencontainers.image.licenses="Apache-2.0" +LABEL org.opencontainers.image.revision="${LABEL_COMMIT}" +LABEL org.opencontainers.image.source="https://github.com/codiewio/codenire" +LABEL org.opencontainers.image.title="Codenire Sandbox" +LABEL org.opencontainers.image.url="https://codenire.io" +LABEL org.opencontainers.image.vendor="I/E Maksim Fedorov" +LABEL org.opencontainers.image.version="${LABEL_VERSION}" \ No newline at end of file diff --git a/sandbox/dockerfiles/golang_1_23/config.json b/sandbox/dockerfiles/golang_1_23/config.json index c91c97c..a70ba01 100644 --- a/sandbox/dockerfiles/golang_1_23/config.json +++ b/sandbox/dockerfiles/golang_1_23/config.json @@ -7,7 +7,7 @@ "ContainerOptions": { "CompileTTL": 30, "RunTTL": 5, - "MemoryLimit": 524288000 + "MemoryLimit": 314572800 }, "IsSupportPackage": true, diff --git a/sandbox/dockerfiles/golang_1_24/config.json b/sandbox/dockerfiles/golang_1_24/config.json index 02a0c90..692ac43 100644 --- a/sandbox/dockerfiles/golang_1_24/config.json +++ b/sandbox/dockerfiles/golang_1_24/config.json @@ -7,7 +7,7 @@ "ContainerOptions": { "CompileTTL": 30, "RunTTL": 5, - "MemoryLimit": 524288000 + "MemoryLimit": 314572800 }, "IsSupportPackage": true, diff --git a/sandbox/dockerfiles/run_php.http b/sandbox/dockerfiles/run_php.http index e516967..6325cc8 100644 --- a/sandbox/dockerfiles/run_php.http +++ b/sandbox/dockerfiles/run_php.http @@ -11,5 +11,6 @@ Content-Type: application/json }, "stdin": "123", "externalOptions": { + "CompileCmd": "curl -I https://4.ident.me" } } \ No newline at end of file diff --git a/sandbox/go.mod b/sandbox/go.mod index 3777789..8d3b05f 100644 --- a/sandbox/go.mod +++ b/sandbox/go.mod @@ -1,6 +1,6 @@ module sandbox -go 1.22 +go 1.24 require ( github.com/alitto/pond/v2 v2.1.4 @@ -9,6 +9,7 @@ require ( github.com/docker/docker v27.3.1+incompatible github.com/go-chi/chi/v5 v5.1.0 github.com/jackc/pgx/v4 v4.18.3 + github.com/prometheus/client_golang v1.21.0 go.opencensus.io v0.24.0 go.uber.org/automaxprocs v1.6.0 ) @@ -24,6 +25,8 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.12 // indirect github.com/aws/smithy-go v1.22.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -40,24 +43,29 @@ require ( github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.29.0 // indirect - golang.org/x/net v0.31.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/protobuf v1.36.1 // indirect gotest.tools/v3 v3.5.1 // indirect ) diff --git a/sandbox/go.sum b/sandbox/go.sum index a8de688..457c7aa 100644 --- a/sandbox/go.sum +++ b/sandbox/go.sum @@ -29,9 +29,13 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.75.3 h1:JBod0SnNqcWQ0+uAyzeRFG1zCHotW github.com/aws/aws-sdk-go-v2/service/s3 v1.75.3/go.mod h1:FHSHmyEUkzRbaFFqqm6bkLAOQHgqhsLmfCahvCBMiyA= github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= @@ -149,12 +153,16 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -171,6 +179,8 @@ github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -182,7 +192,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= +github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= @@ -208,8 +226,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= @@ -251,8 +269,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -269,8 +287,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -290,8 +308,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -299,8 +317,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -346,8 +364,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= diff --git a/sandbox/main.go b/sandbox/main.go index 05ba138..549c3c4 100644 --- a/sandbox/main.go +++ b/sandbox/main.go @@ -33,6 +33,8 @@ import ( "errors" "flag" "fmt" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "log" "net/http" "os" @@ -66,6 +68,7 @@ var ( gvisorRuntime = "runsc" isolatedPostgresDSN = flag.String("isolatedPostgresDSN", "", "isolated postgres DB instance") isolatedPostgresNetwork = flag.String("isolatedPostgresNetwork", "", "isolated postgres network") + extraNetworkHosts = flag.String("extraNetworkHosts", "", "is a comma-separated list of additional") s3DockerfilesEndpoint = flag.String("s3DockerfilesEndpoint", "", "s3 endpoint with templates") s3DockerfilesBucket = flag.String("s3DockerfilesBucket", "", "s3 bucket with templates") @@ -96,6 +99,7 @@ func main() { log.Printf("Go playground sandbox starting...") codenireManager = NewCodenireOrchestrator() + codenireManager.RegisterMetrics(prometheus.DefaultRegisterer) codenireManager.KillAll() runSem = make(chan struct{}, *numWorkers) @@ -115,20 +119,15 @@ func main() { h.Post("/run", runHandler) h.Get("/templates", listTemplatesHandler) + h.Get("/metrics", func(w http.ResponseWriter, r *http.Request) { + updateDatabaseCountMetric() + promhttp.Handler().ServeHTTP(w, r) + }) + httpServer := &http.Server{ Addr: ":" + *listenAddr, ReadHeaderTimeout: 5 * time.Second, Handler: &ochttp.Handler{Handler: h}, - - // TODO:: check connections - // ConnState: func(_ net.Conn, cs http.ConnState) { - // switch cs { - // case http.StateNew: - // MetricsOpenConnections.Inc() - // case http.StateClosed, http.StateHijacked: - // MetricsOpenConnections.Dec() - // } - // }, } err = codenireManager.Prepare() diff --git a/sandbox/manager.go b/sandbox/manager.go index af41477..2ba9d65 100644 --- a/sandbox/manager.go +++ b/sandbox/manager.go @@ -27,6 +27,7 @@ import ( docker "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" + "github.com/prometheus/client_golang/prometheus" contract "sandbox/api/gen" "sandbox/internal" @@ -53,7 +54,14 @@ type BuiltImage struct { buf bytes.Buffer } +type MetricsAware interface { + RegisterMetrics(registry prometheus.Registerer) + observeExecDuration(start time.Time, label, language string) +} + type ContainerOrchestrator interface { + MetricsAware + Prepare() error Boot() error GetTemplates() []BuiltImage @@ -75,9 +83,28 @@ type CodenireOrchestrator struct { isolated bool dockerFilesPath string + + execDurationMetric *prometheus.SummaryVec + runContainersMetric prometheus.Gauge } func NewCodenireOrchestrator() *CodenireOrchestrator { + execDurationMetric := prometheus.NewSummaryVec(prometheus.SummaryOpts{ + Name: "sand_exec_duration_ms", + Help: "Duration of compilation in milliseconds per operation", + Objectives: map[float64]float64{ + 0.5: 0.05, // 50% (median) → average execution time + 0.75: 0.02, // 75% → good execution time (around 3-4 sec) + 0.9: 0.01, // 90% → slow requests (around 7 sec) + 0.99: 0.005, // 99% → very slow requests (close to 10 sec) + }, + }, []string{"operation", "language"}) + + runContainersMetric := prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "sand_run_containers", + Help: "Current number of run containers.", + }) + c, err := client.NewClientWithOpts(client.WithVersion("1.41")) if err != nil { panic("fail on createDB docker client") @@ -92,9 +119,24 @@ func NewCodenireOrchestrator() *CodenireOrchestrator { idleContainersCount: *replicaContainerCnt, dockerFilesPath: *dockerFilesPath, isolated: *isolated, + execDurationMetric: execDurationMetric, + runContainersMetric: runContainersMetric, } } +func (m *CodenireOrchestrator) observeExecDuration(start time.Time, label, lang string) { + elapsed := time.Since(start) + ms := float64(elapsed.Nanoseconds() / int64(time.Millisecond)) + + m.execDurationMetric.WithLabelValues(label, lang).Observe(ms) +} + +func (m *CodenireOrchestrator) RegisterMetrics(registry prometheus.Registerer) { + registry.MustRegister(m.execDurationMetric) + registry.MustRegister(m.runContainersMetric) + registry.MustRegister(dbCountMetric) +} + func (m *CodenireOrchestrator) Prepare() error { templates := parseConfigFiles(m.dockerFilesPath) @@ -214,6 +256,8 @@ func (m *CodenireOrchestrator) KillContainer(c StartedContainer) (err error) { return err } + m.runContainersMetric.Dec() + return nil } @@ -300,7 +344,7 @@ func (m *CodenireOrchestrator) runSndContainer(img BuiltImage) (cont *StartedCon user := fmt.Sprintf("pguser_%s", internal.RandHex(8)) password := fmt.Sprintf("pgpassword_%s", internal.RandHex(8)) - pgErr := createDB(*isolatedPostgresDSN, name, user, password) + pgErr := createDB(name, user, password) defer func() { if err != nil { m.removeSandboxDB(name) @@ -326,6 +370,11 @@ func (m *CodenireOrchestrator) runSndContainer(img BuiltImage) (cont *StartedCon } } + extraHosts := []string{} + if *extraNetworkHosts != "" { + extraHosts = splitAndTrim(*extraNetworkHosts) + } + hostConfig := &docker.HostConfig{ Runtime: m.runtime(), AutoRemove: true, @@ -334,7 +383,7 @@ func (m *CodenireOrchestrator) runSndContainer(img BuiltImage) (cont *StartedCon Memory: int64(*img.ContainerOptions.MemoryLimit), MemorySwap: 0, }, - ExtraHosts: []string{}, + ExtraHosts: extraHosts, } if img.imageID == nil { return nil, fmt.Errorf("imageId is null") @@ -423,6 +472,8 @@ func (m *CodenireOrchestrator) startContainers() { continue } + m.runContainersMetric.Inc() + m.getContainer(img.Template) <- *c } }() @@ -451,8 +502,8 @@ func (m *CodenireOrchestrator) runtime() string { func (m *CodenireOrchestrator) removeSandboxDB(dbname string) { if *isolatedPostgresDSN != "" && dbname != "" { - // TODO:: handle it and cover by prometheus - _ = dropDB(*isolatedPostgresDSN, dbname) + // TODO:: handle it + _ = dropDB(dbname) } } @@ -615,3 +666,13 @@ func duplicates(items []contract.ImageConfig) []string { // fmt.Println("Docker Login successful:", authResponse.Status) // return nil //} + +func splitAndTrim(input string) []string { + parts := strings.Split(input, ",") + + for i, part := range parts { + parts[i] = strings.TrimSpace(part) + } + + return parts +} diff --git a/sandbox/postgres.go b/sandbox/postgres.go index 680ce57..fde7361 100644 --- a/sandbox/postgres.go +++ b/sandbox/postgres.go @@ -9,9 +9,17 @@ import ( "time" "github.com/jackc/pgx/v4" + "github.com/prometheus/client_golang/prometheus" ) -func createDB(dsn string, dbName, userName, userPassword string) error { +var dbCountMetric = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "sand_pg_database_count", + Help: "Number of databases in PostgreSQL", +}) + +func createDB(dbName, userName, userPassword string) error { + dsn := *isolatedPostgresDSN + conn, err := pgx.Connect(context.Background(), dsn) if err != nil { return fmt.Errorf("error connecting to the database: %w", err) @@ -66,7 +74,9 @@ func createDB(dsn string, dbName, userName, userPassword string) error { return nil } -func dropDB(dsn, dbName string) error { +func dropDB(dbName string) error { + dsn := *isolatedPostgresDSN + conn, err := pgx.Connect(context.Background(), dsn) if err != nil { return fmt.Errorf("error connecting to the database: %w", err) @@ -99,3 +109,26 @@ func dropDB(dsn, dbName string) error { return nil } + +func updateDatabaseCountMetric() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + dsn := *isolatedPostgresDSN + + conn, err := pgx.Connect(ctx, dsn) + if err != nil { + log.Printf("Failed to connect to the database: %v", err) + return + } + defer conn.Close(ctx) + + var count int + err = conn.QueryRow(ctx, "SELECT COUNT(*) FROM pg_database").Scan(&count) + if err != nil { + log.Printf("Error executing the query: %v", err) + return + } + + dbCountMetric.Set(float64(count)) +} diff --git a/sandbox/sandbox.go b/sandbox/sandbox.go index 68f67c7..55ce21c 100644 --- a/sandbox/sandbox.go +++ b/sandbox/sandbox.go @@ -147,6 +147,7 @@ func runHandler(w http.ResponseWriter, r *http.Request) { res.RunEnvironment.CompileCmd = compileCmd res.RunEnvironment.CompileTime = float32(time.Since(start).Seconds()) + codenireManager.observeExecDuration(start, "compile", req.SandId) if runErr != nil { if errors.Is(compileCtx.Err(), context.DeadlineExceeded) { @@ -180,6 +181,7 @@ func runHandler(w http.ResponseWriter, r *http.Request) { res.RunEnvironment.RunCmd = runCmd res.RunEnvironment.RunTime = float32(time.Since(start).Seconds()) + codenireManager.observeExecDuration(start, "run", req.SandId) if runErr != nil { if errors.Is(runTimeoutCtx.Err(), context.DeadlineExceeded) {