mirror of
https://github.com/ddworken/hishtory.git
synced 2025-06-24 05:51:38 +02:00
Fix memory leak caused by not closing resp.Body (#62) and also fix the server to work when the DD integration is disabled
This commit is contained in:
parent
226b39609f
commit
f502cbee1d
2
Makefile
2
Makefile
@ -25,7 +25,7 @@ build-static:
|
|||||||
docker build -t gcr.io/dworken-k8s/hishtory-static -f backend/web/caddy/Dockerfile .
|
docker build -t gcr.io/dworken-k8s/hishtory-static -f backend/web/caddy/Dockerfile .
|
||||||
|
|
||||||
build-api:
|
build-api:
|
||||||
rm hishtory
|
rm hishtory server || true
|
||||||
docker build -t gcr.io/dworken-k8s/hishtory-api -f backend/server/Dockerfile .
|
docker build -t gcr.io/dworken-k8s/hishtory-api -f backend/server/Dockerfile .
|
||||||
|
|
||||||
deploy-static: build-static
|
deploy-static: build-static
|
||||||
|
@ -16,6 +16,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
pprofhttp "net/http/pprof"
|
||||||
|
|
||||||
"github.com/DataDog/datadog-go/statsd"
|
"github.com/DataDog/datadog-go/statsd"
|
||||||
"github.com/ddworken/hishtory/shared"
|
"github.com/ddworken/hishtory/shared"
|
||||||
"github.com/jackc/pgx/v4/stdlib"
|
"github.com/jackc/pgx/v4/stdlib"
|
||||||
@ -27,11 +29,10 @@ import (
|
|||||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
||||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
||||||
"gopkg.in/DataDog/dd-trace-go.v1/profiler"
|
"gopkg.in/DataDog/dd-trace-go.v1/profiler"
|
||||||
"gorm.io/gorm/logger"
|
|
||||||
|
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -197,7 +198,9 @@ func apiSubmitHandler(ctx context.Context, w http.ResponseWriter, r *http.Reques
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to execute transaction to add entries to DB: %v", err))
|
panic(fmt.Errorf("failed to execute transaction to add entries to DB: %v", err))
|
||||||
}
|
}
|
||||||
GLOBAL_STATSD.Count("hishtory.submit", int64(len(devices)), []string{}, 1.0)
|
if GLOBAL_STATSD != nil {
|
||||||
|
GLOBAL_STATSD.Count("hishtory.submit", int64(len(devices)), []string{}, 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiBootstrapHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
func apiBootstrapHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
@ -256,7 +259,9 @@ func apiQueryHandler(ctx context.Context, w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLOBAL_STATSD.Incr("hishtory.query", []string{}, 1.0)
|
if GLOBAL_STATSD != nil {
|
||||||
|
GLOBAL_STATSD.Incr("hishtory.query", []string{}, 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func incrementReadCounts(ctx context.Context, deviceId string) error {
|
func incrementReadCounts(ctx context.Context, deviceId string) error {
|
||||||
@ -293,7 +298,10 @@ func apiRegisterHandler(ctx context.Context, w http.ResponseWriter, r *http.Requ
|
|||||||
checkGormResult(GLOBAL_DB.WithContext(ctx).Create(&shared.DumpRequest{UserId: userId, RequestingDeviceId: deviceId, RequestTime: time.Now()}))
|
checkGormResult(GLOBAL_DB.WithContext(ctx).Create(&shared.DumpRequest{UserId: userId, RequestingDeviceId: deviceId, RequestTime: time.Now()}))
|
||||||
}
|
}
|
||||||
updateUsageData(ctx, r, userId, deviceId, 0, false)
|
updateUsageData(ctx, r, userId, deviceId, 0, false)
|
||||||
GLOBAL_STATSD.Incr("hishtory.register", []string{}, 1.0)
|
|
||||||
|
if GLOBAL_STATSD != nil {
|
||||||
|
GLOBAL_STATSD.Incr("hishtory.register", []string{}, 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiGetPendingDumpRequestsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
func apiGetPendingDumpRequestsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
@ -555,6 +563,12 @@ func cron(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
if GLOBAL_STATSD != nil {
|
||||||
|
err = GLOBAL_STATSD.Flush()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,6 +599,7 @@ func updateReleaseVersion() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get latest release version: %v", err)
|
return fmt.Errorf("failed to get latest release version: %v", err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read github API response body: %v", err)
|
return fmt.Errorf("failed to read github API response body: %v", err)
|
||||||
@ -635,6 +650,7 @@ func assertValidUpdate(updateInfo shared.UpdateInfo) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to retrieve URL %#v: %v", url, err)
|
return fmt.Errorf("failed to retrieve URL %#v: %v", url, err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
if resp.StatusCode == 404 {
|
if resp.StatusCode == 404 {
|
||||||
return fmt.Errorf("URL %#v returned 404", url)
|
return fmt.Errorf("URL %#v returned 404", url)
|
||||||
}
|
}
|
||||||
@ -735,7 +751,10 @@ func feedbackHandler(ctx context.Context, w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
fmt.Printf("feedbackHandler: received request containg feedback %#v\n", feedback)
|
fmt.Printf("feedbackHandler: received request containg feedback %#v\n", feedback)
|
||||||
checkGormResult(GLOBAL_DB.WithContext(ctx).Create(feedback))
|
checkGormResult(GLOBAL_DB.WithContext(ctx).Create(feedback))
|
||||||
GLOBAL_STATSD.Incr("hishtory.uninstall", []string{}, 1.0)
|
|
||||||
|
if GLOBAL_STATSD != nil {
|
||||||
|
GLOBAL_STATSD.Incr("hishtory.uninstall", []string{}, 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type loggedResponseData struct {
|
type loggedResponseData struct {
|
||||||
@ -782,8 +801,10 @@ func withLogging(h func(context.Context, http.ResponseWriter, *http.Request)) ht
|
|||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
fmt.Printf("%s %s %#v %s %s %s\n", getRemoteAddr(r), r.Method, r.RequestURI, getHishtoryVersion(r), duration.String(), byteCountToString(responseData.size))
|
fmt.Printf("%s %s %#v %s %s %s\n", getRemoteAddr(r), r.Method, r.RequestURI, getHishtoryVersion(r), duration.String(), byteCountToString(responseData.size))
|
||||||
GLOBAL_STATSD.Distribution("hishtory.request_duration", float64(duration.Microseconds())/1_000, []string{"HANDLER=" + getFunctionName(h)}, 1.0)
|
if GLOBAL_STATSD != nil {
|
||||||
GLOBAL_STATSD.Incr("hishtory.request", []string{}, 1.0)
|
GLOBAL_STATSD.Distribution("hishtory.request_duration", float64(duration.Microseconds())/1_000, []string{"HANDLER=" + getFunctionName(h)}, 1.0)
|
||||||
|
GLOBAL_STATSD.Incr("hishtory.request", []string{}, 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return http.HandlerFunc(logFn)
|
return http.HandlerFunc(logFn)
|
||||||
}
|
}
|
||||||
@ -853,7 +874,8 @@ func deepCleanDatabase(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureObservability() func() {
|
func configureObservability(mux *httptrace.ServeMux) func() {
|
||||||
|
// Profiler
|
||||||
err := profiler.Start(
|
err := profiler.Start(
|
||||||
profiler.WithService("hishtory-api"),
|
profiler.WithService("hishtory-api"),
|
||||||
profiler.WithVersion(ReleaseVersion),
|
profiler.WithVersion(ReleaseVersion),
|
||||||
@ -867,17 +889,27 @@ func configureObservability() func() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to start DataDog profiler: %v\n", err)
|
fmt.Printf("Failed to start DataDog profiler: %v\n", err)
|
||||||
}
|
}
|
||||||
|
// Tracer
|
||||||
tracer.Start(
|
tracer.Start(
|
||||||
tracer.WithRuntimeMetrics(),
|
tracer.WithRuntimeMetrics(),
|
||||||
tracer.WithService("hishtory-api"),
|
tracer.WithService("hishtory-api"),
|
||||||
tracer.WithUDS("/var/run/datadog/apm.socket"),
|
tracer.WithUDS("/var/run/datadog/apm.socket"),
|
||||||
)
|
)
|
||||||
defer tracer.Stop()
|
defer tracer.Stop()
|
||||||
|
// Stats
|
||||||
ddStats, err := statsd.New("unix:///var/run/datadog/dsd.socket")
|
ddStats, err := statsd.New("unix:///var/run/datadog/dsd.socket")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to start DataDog statsd: %v\n", err)
|
fmt.Printf("Failed to start DataDog statsd: %v\n", err)
|
||||||
}
|
}
|
||||||
GLOBAL_STATSD = ddStats
|
GLOBAL_STATSD = ddStats
|
||||||
|
// Pprof
|
||||||
|
mux.HandleFunc("/debug/pprof/", pprofhttp.Index)
|
||||||
|
mux.HandleFunc("/debug/pprof/cmdline", pprofhttp.Cmdline)
|
||||||
|
mux.HandleFunc("/debug/pprof/profile", pprofhttp.Profile)
|
||||||
|
mux.HandleFunc("/debug/pprof/symbol", pprofhttp.Symbol)
|
||||||
|
mux.HandleFunc("/debug/pprof/trace", pprofhttp.Trace)
|
||||||
|
|
||||||
|
// Func to stop all of the above
|
||||||
return func() {
|
return func() {
|
||||||
profiler.Stop()
|
profiler.Stop()
|
||||||
tracer.Stop()
|
tracer.Stop()
|
||||||
@ -885,12 +917,13 @@ func configureObservability() func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
mux := httptrace.NewServeMux()
|
||||||
|
|
||||||
if isProductionEnvironment() {
|
if isProductionEnvironment() {
|
||||||
go configureObservability()()
|
defer configureObservability(mux)()
|
||||||
go deepCleanDatabase(context.Background())
|
go deepCleanDatabase(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := httptrace.NewServeMux()
|
|
||||||
mux.Handle("/api/v1/submit", withLogging(apiSubmitHandler))
|
mux.Handle("/api/v1/submit", withLogging(apiSubmitHandler))
|
||||||
mux.Handle("/api/v1/get-dump-requests", withLogging(apiGetPendingDumpRequestsHandler))
|
mux.Handle("/api/v1/get-dump-requests", withLogging(apiGetPendingDumpRequestsHandler))
|
||||||
mux.Handle("/api/v1/submit-dump", withLogging(apiSubmitDumpHandler))
|
mux.Handle("/api/v1/submit-dump", withLogging(apiSubmitDumpHandler))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user