Open telemetry integration (#3972)

This PR adds opentelemetry and chi wrapper to have basic instrumentation

<!--start release-notes-assistant-->

## Draft release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/3972): <!--number 3972 --><!--line 0 --><!--description YWRkIHN1cHBvcnQgZm9yIGJhc2ljIHJlcXVlc3QgdHJhY2luZyB3aXRoIG9wZW50ZWxlbWV0cnk=-->add support for basic request tracing with opentelemetry<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3972
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Co-committed-by: TheFox0x7 <thefox0x7@gmail.com>
This commit is contained in:
TheFox0x7 2024-08-05 06:04:39 +00:00 committed by Earl Warren
parent 7c74def6ff
commit c738542201
19 changed files with 1281 additions and 10 deletions

View file

@ -18,6 +18,7 @@ import (
"gitea.com/go-chi/session"
"github.com/chi-middleware/proxy"
chi "github.com/go-chi/chi/v5"
"github.com/riandyrn/otelchi"
)
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
@ -68,6 +69,9 @@ func ProtocolMiddlewares() (handlers []any) {
if setting.IsAccessLogEnabled() {
handlers = append(handlers, context.AccessLogger())
}
if setting.IsOpenTelemetryEnabled() {
handlers = append(handlers, otelchi.Middleware("forgejo"))
}
return handlers
}

View file

@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/external"
"code.gitea.io/gitea/modules/opentelemetry"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/ssh"
"code.gitea.io/gitea/modules/storage"
@ -110,6 +111,7 @@ func InitWebInstallPage(ctx context.Context) {
// InitWebInstalled is for global installed configuration.
func InitWebInstalled(ctx context.Context) {
mustInitCtx(ctx, opentelemetry.Init)
mustInitCtx(ctx, git.InitFull)
log.Info("Git version: %s (home: %s)", git.VersionInfo(), git.HomeDir())

View file

@ -4,12 +4,23 @@
package install
import (
"context"
"io"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"time"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/opentelemetry"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRoutes(t *testing.T) {
@ -36,3 +47,43 @@ func TestRoutes(t *testing.T) {
func TestMain(m *testing.M) {
unittest.MainTest(m)
}
func TestOtelChi(t *testing.T) {
ServiceName := "forgejo-otelchi" + uuid.NewString()
otelURL, ok := os.LookupEnv("TEST_OTEL_URL")
if !ok {
t.Skip("TEST_OTEL_URL not set")
}
traceEndpoint, err := url.Parse(otelURL)
require.NoError(t, err)
config := &setting.OtelExporter{
Endpoint: traceEndpoint,
Protocol: "grpc",
}
defer test.MockVariableValue(&setting.OpenTelemetry.Enabled, true)()
defer test.MockVariableValue(&setting.OpenTelemetry.Traces, "otlp")() // Required due to lazy loading
defer test.MockVariableValue(&setting.OpenTelemetry.ServiceName, ServiceName)()
defer test.MockVariableValue(&setting.OpenTelemetry.OtelTraces, config)()
require.NoError(t, opentelemetry.Init(context.Background()))
r := Routes()
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/e/img/gitea.svg", nil)
r.ServeHTTP(w, req)
traceEndpoint.Host = traceEndpoint.Hostname() + ":16686"
traceEndpoint.Path = "/api/services"
require.EventuallyWithT(t, func(collect *assert.CollectT) {
resp, err := http.Get(traceEndpoint.String())
require.NoError(t, err)
apiResponse, err := io.ReadAll(resp.Body)
require.NoError(t, err)
assert.Contains(collect, string(apiResponse), ServiceName)
}, 15*time.Second, 1*time.Second)
}