mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	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>
		
			
				
	
	
		
			96 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2024 TheFox0x7. All rights reserved.
 | |
| // SPDX-License-Identifier: EUPL-1.2
 | |
| 
 | |
| package opentelemetry
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"crypto/tls"
 | |
| 	"crypto/x509"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"code.gitea.io/gitea/modules/graceful"
 | |
| 	"code.gitea.io/gitea/modules/log"
 | |
| 
 | |
| 	"github.com/go-logr/logr/funcr"
 | |
| 	"go.opentelemetry.io/otel"
 | |
| 	"go.opentelemetry.io/otel/propagation"
 | |
| )
 | |
| 
 | |
| func Init(ctx context.Context) error {
 | |
| 	// Redirect otel logger to write to common forgejo log at info
 | |
| 	logWrap := funcr.New(func(prefix, args string) {
 | |
| 		log.Info(fmt.Sprint(prefix, args))
 | |
| 	}, funcr.Options{})
 | |
| 	otel.SetLogger(logWrap)
 | |
| 	// Redirect error handling to forgejo log as well
 | |
| 	otel.SetErrorHandler(otel.ErrorHandlerFunc(func(cause error) {
 | |
| 		log.Error("internal opentelemetry error was raised: %s", cause)
 | |
| 	}))
 | |
| 	var shutdownFuncs []func(context.Context) error
 | |
| 	shutdownCtx := context.Background()
 | |
| 
 | |
| 	otel.SetTextMapPropagator(newPropagator())
 | |
| 
 | |
| 	res, err := newResource(ctx)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	traceShutdown, err := setupTraceProvider(ctx, res)
 | |
| 	if err != nil {
 | |
| 		log.Warn("OpenTelemetry trace setup failed, err=%s", err)
 | |
| 	} else {
 | |
| 		shutdownFuncs = append(shutdownFuncs, traceShutdown)
 | |
| 	}
 | |
| 
 | |
| 	graceful.GetManager().RunAtShutdown(ctx, func() {
 | |
| 		for _, fn := range shutdownFuncs {
 | |
| 			if err := fn(shutdownCtx); err != nil {
 | |
| 				log.Warn("exporter shutdown failed, err=%s", err)
 | |
| 			}
 | |
| 		}
 | |
| 		shutdownFuncs = nil
 | |
| 	})
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func newPropagator() propagation.TextMapPropagator {
 | |
| 	return propagation.NewCompositeTextMapPropagator(
 | |
| 		propagation.TraceContext{},
 | |
| 		propagation.Baggage{},
 | |
| 	)
 | |
| }
 | |
| 
 | |
| func withCertPool(path string, tlsConf *tls.Config) {
 | |
| 	if path == "" {
 | |
| 		return
 | |
| 	}
 | |
| 	b, err := os.ReadFile(path)
 | |
| 	if err != nil {
 | |
| 		log.Warn("Otel: reading ca cert failed path=%s, err=%s", path, err)
 | |
| 		return
 | |
| 	}
 | |
| 	cp := x509.NewCertPool()
 | |
| 	if ok := cp.AppendCertsFromPEM(b); !ok {
 | |
| 		log.Warn("Otel: no valid PEM certificate found path=%s", path)
 | |
| 		return
 | |
| 	}
 | |
| 	tlsConf.RootCAs = cp
 | |
| }
 | |
| 
 | |
| func withClientCert(nc, nk string, tlsConf *tls.Config) {
 | |
| 	if nc == "" || nk == "" {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	crt, err := tls.LoadX509KeyPair(nc, nk)
 | |
| 	if err != nil {
 | |
| 		log.Warn("Otel: create tls client key pair failed")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	tlsConf.Certificates = append(tlsConf.Certificates, crt)
 | |
| }
 |