From b819116b7301fbbb907843715e70ac55757c6093 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Fri, 25 Mar 2022 19:25:13 +0000 Subject: [PATCH 1/4] Add auto logging of goroutine pid label This PR uses unsafe to export the hidden runtime_getProfLabel function from the runtime package and then casts the result to a map[string]string. We can then interrogate this map to get the pid label from the goroutine allowing us to log it with any logging request. Reference #19202 Signed-off-by: Andrew Thornton --- modules/log/groutinelabel.go | 20 ++++++++++++++++++++ modules/log/multichannel.go | 7 +++++++ 2 files changed, 27 insertions(+) create mode 100644 modules/log/groutinelabel.go diff --git a/modules/log/groutinelabel.go b/modules/log/groutinelabel.go new file mode 100644 index 0000000000000..8fb723bdf6529 --- /dev/null +++ b/modules/log/groutinelabel.go @@ -0,0 +1,20 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package log + +import "unsafe" + +//go:linkname runtime_getProfLabel runtime/pprof.runtime_getProfLabel +func runtime_getProfLabel() unsafe.Pointer + +type labelMap map[string]string + +func getGoroutineLabels() map[string]string { + l := (*labelMap)(runtime_getProfLabel()) + if l == nil { + return map[string]string{} + } + return *l +} diff --git a/modules/log/multichannel.go b/modules/log/multichannel.go index c725df4f3ed57..8d94eb2b22de3 100644 --- a/modules/log/multichannel.go +++ b/modules/log/multichannel.go @@ -72,6 +72,13 @@ func (l *MultiChannelledLogger) Log(skip int, level Level, format string, v ...i if len(v) > 0 { msg = ColorSprintf(format, v...) } + labels := getGoroutineLabels() + if labels != nil { + pid, ok := labels["pid"] + if ok { + msg = "[" + ColorString(FgHiYellow) + pid + ColorString(Reset) + "] " + msg + } + } stack := "" if l.GetStacktraceLevel() <= level { stack = Stack(skip + 1) From 224bb5b90c0e1672c129ce992d8fef1e97c0798f Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Fri, 25 Mar 2022 20:29:27 +0000 Subject: [PATCH 2/4] placate lint Signed-off-by: Andrew Thornton --- modules/log/groutinelabel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/log/groutinelabel.go b/modules/log/groutinelabel.go index 8fb723bdf6529..e63030223be10 100644 --- a/modules/log/groutinelabel.go +++ b/modules/log/groutinelabel.go @@ -7,7 +7,7 @@ package log import "unsafe" //go:linkname runtime_getProfLabel runtime/pprof.runtime_getProfLabel -func runtime_getProfLabel() unsafe.Pointer +func runtime_getProfLabel() unsafe.Pointer // nolint type labelMap map[string]string From 88528b74e23399e5b55ad5c6db0d6e178f0b9640 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 26 Mar 2022 10:06:37 +0000 Subject: [PATCH 3/4] as per review Signed-off-by: Andrew Thornton --- modules/log/groutinelabel.go | 2 +- modules/log/groutinelabel_test.go | 32 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 modules/log/groutinelabel_test.go diff --git a/modules/log/groutinelabel.go b/modules/log/groutinelabel.go index e63030223be10..2ffbba57c0d28 100644 --- a/modules/log/groutinelabel.go +++ b/modules/log/groutinelabel.go @@ -13,7 +13,7 @@ type labelMap map[string]string func getGoroutineLabels() map[string]string { l := (*labelMap)(runtime_getProfLabel()) - if l == nil { + if l == nil || *l == nil { return map[string]string{} } return *l diff --git a/modules/log/groutinelabel_test.go b/modules/log/groutinelabel_test.go new file mode 100644 index 0000000000000..c6d17d7aaf57c --- /dev/null +++ b/modules/log/groutinelabel_test.go @@ -0,0 +1,32 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package log + +import ( + "context" + "runtime/pprof" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_getGoroutineLabels(t *testing.T) { + pprof.Do(context.Background(), pprof.Labels(), func(ctx context.Context) { + currentLabels := getGoroutineLabels() + pprof.ForLabels(ctx, func(key, value string) bool { + assert.EqualValues(t, value, currentLabels[key]) + return true + }) + + pprof.Do(ctx, pprof.Labels("Test_getGoroutineLabels", "Test_getGoroutineLabels_child1"), func(ctx context.Context) { + currentLabels := getGoroutineLabels() + pprof.ForLabels(ctx, func(key, value string) bool { + assert.EqualValues(t, value, currentLabels[key]) + return true + }) + assert.EqualValues(t, "Test_getGoroutineLabels_child1", currentLabels["Test_getGoroutineLabels"]) + }) + }) +} From b9802234d90d3d2fcc4a11cb2650adb1b782b5ca Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 26 Mar 2022 10:10:20 +0000 Subject: [PATCH 4/4] adjust to allow nil map Signed-off-by: Andrew Thornton --- modules/log/groutinelabel.go | 4 ++-- modules/log/groutinelabel_test.go | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/log/groutinelabel.go b/modules/log/groutinelabel.go index 2ffbba57c0d28..0d3739fd98d7f 100644 --- a/modules/log/groutinelabel.go +++ b/modules/log/groutinelabel.go @@ -13,8 +13,8 @@ type labelMap map[string]string func getGoroutineLabels() map[string]string { l := (*labelMap)(runtime_getProfLabel()) - if l == nil || *l == nil { - return map[string]string{} + if l == nil { + return nil } return *l } diff --git a/modules/log/groutinelabel_test.go b/modules/log/groutinelabel_test.go index c6d17d7aaf57c..8e23721b867d2 100644 --- a/modules/log/groutinelabel_test.go +++ b/modules/log/groutinelabel_test.go @@ -26,7 +26,9 @@ func Test_getGoroutineLabels(t *testing.T) { assert.EqualValues(t, value, currentLabels[key]) return true }) - assert.EqualValues(t, "Test_getGoroutineLabels_child1", currentLabels["Test_getGoroutineLabels"]) + if assert.NotNil(t, currentLabels) { + assert.EqualValues(t, "Test_getGoroutineLabels_child1", currentLabels["Test_getGoroutineLabels"]) + } }) }) }