Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bpf log level getter (#560) #562

Merged
merged 3 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions daemon/manager/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (

"github.com/spf13/cobra"

"kmesh.net/kmesh/pkg/logger"
"kmesh.net/kmesh/pkg/status"
)

Expand All @@ -49,32 +48,17 @@ func NewCmd() *cobra.Command {
return cmd
}

func GetLoggerLevel(args []string) {
if len(args) != 1 {
names := logger.GetLoggerNames()
if len(names) > 0 {
fmt.Println("Existing loggers:")
for _, name := range names {
fmt.Println(name)
}
} else {
fmt.Println("No existing loggers.")
}
return
}
loggerName := args[0]
url := status.GetLoggerURL() + "?name=" + loggerName

func GetJson(url string, val any) {
resp, err := http.Get(url)
if err != nil {
fmt.Printf("Error making GET request: %v\n", err)
fmt.Printf("Error making GET request(%s): %v\n", url, err)
return
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body: %v\n", err)
fmt.Printf("Error reading response body(%s): %v\n", url, err)
return
}

Expand All @@ -84,12 +68,32 @@ func GetLoggerLevel(args []string) {
return
}

var loggerInfo status.LoggerInfo
err = json.Unmarshal(body, &loggerInfo)
err = json.Unmarshal(body, val)
if err != nil {
fmt.Printf("Error unmarshaling response body: %v\n", err)
return
}
}

func GetLoggerNames() {
url := status.GetLoggerURL()
var loggerNames []string
GetJson(url, &loggerNames)
fmt.Printf("Existing Loggers:\n")
for _, logger := range loggerNames {
fmt.Printf("\t%s\n", logger)
}
}

func GetLoggerLevel(args []string) {
if len(args) == 0 {
GetLoggerNames()
return
}
loggerName := args[0]
url := status.GetLoggerURL() + "?name=" + loggerName
var loggerInfo status.LoggerInfo
GetJson(url, &loggerInfo)

fmt.Printf("Logger Name: %s\n", loggerInfo.Name)
fmt.Printf("Logger Level: %s\n", loggerInfo.Level)
Expand Down
65 changes: 57 additions & 8 deletions pkg/status/status_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
patternConfigDumpWorkload = configDumpPrefix + "/workload"
patternReadyProbe = "/debug/ready"
patternLoggers = "/debug/loggers"
patternBpfLogLevel = "/debug/bpfLogLevel/"

bpfLoggerName = "bpf"

Expand Down Expand Up @@ -168,17 +167,42 @@
}
}

func (s *Server) getLoggerNames(w http.ResponseWriter, r *http.Request) {
loggerNames := append(logger.GetLoggerNames(), bpfLoggerName)
data, err := json.MarshalIndent(&loggerNames, "", " ")
if err != nil {
log.Errorf("Failed to marshal logger names: %v", err)
w.WriteHeader(http.StatusInternalServerError)

Check warning on line 175 in pkg/status/status_server.go

View check run for this annotation

Codecov / codecov/patch

pkg/status/status_server.go#L173-L175

Added lines #L173 - L175 were not covered by tests
return
}
_, _ = w.Write(data)
}

func (s *Server) getLoggerLevel(w http.ResponseWriter, r *http.Request) {
loggerName := r.URL.Query().Get("name")
loggerLevel, err := logger.GetLoggerLevel(loggerName)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "\t%v\n", err)
if loggerName == "" {
s.getLoggerNames(w, r)
return
}
loggerInfo := LoggerInfo{
Name: loggerName,
Level: loggerLevel.String(),
var loggerInfo *LoggerInfo
if loggerName != bpfLoggerName {
loggerLevel, err := logger.GetLoggerLevel(loggerName)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "\t%v\n", err)

Check warning on line 192 in pkg/status/status_server.go

View check run for this annotation

Codecov / codecov/patch

pkg/status/status_server.go#L190-L192

Added lines #L190 - L192 were not covered by tests
return
}
loggerInfo = &LoggerInfo{
Name: loggerName,
Level: loggerLevel.String(),
}
} else {
var err error
loggerInfo, err = s.getBpfLogLevel()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)

Check warning on line 203 in pkg/status/status_server.go

View check run for this annotation

Codecov / codecov/patch

pkg/status/status_server.go#L202-L203

Added lines #L202 - L203 were not covered by tests
return
}
}
data, err := json.MarshalIndent(&loggerInfo, "", " ")
if err != nil {
Expand Down Expand Up @@ -288,6 +312,31 @@
_, _ = w.Write([]byte("OK"))
}

func (s *Server) getBpfLogLevel() (*LoggerInfo, error) {
key := uint32(0)
value := uint32(0)
if err := s.bpfLogLevelMap.Lookup(&key, &value); err != nil {

Check warning on line 318 in pkg/status/status_server.go

View check run for this annotation

Codecov / codecov/patch

pkg/status/status_server.go#L318

Added line #L318 was not covered by tests
return nil, fmt.Errorf("get log level error: %v", err)
}

logLevelMap := map[int]string{
constants.BPF_LOG_ERR: "error",
constants.BPF_LOG_WARN: "warn",
constants.BPF_LOG_INFO: "info",
constants.BPF_LOG_DEBUG: "debug",
}

loggerLevel, exists := logLevelMap[int(value)]
if !exists {

Check warning on line 330 in pkg/status/status_server.go

View check run for this annotation

Codecov / codecov/patch

pkg/status/status_server.go#L330

Added line #L330 was not covered by tests
return nil, fmt.Errorf("unexpected invalid log level: %d", value)
}

return &LoggerInfo{
Name: bpfLoggerName,
Level: loggerLevel,
}, nil
}

func (s *Server) setBpfLogLevel(w http.ResponseWriter, levelStr string) {
level, err := strconv.Atoi(levelStr)
if err != nil {
Expand Down
82 changes: 46 additions & 36 deletions pkg/status/status_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ import (
"net/http"
"net/http/httptest"
"net/netip"
"sort"
"strconv"
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"istio.io/istio/pilot/test/util"

"kmesh.net/kmesh/api/v2/workloadapi"
Expand Down Expand Up @@ -53,32 +55,35 @@ func TestServer_getLoggerLevel(t *testing.T) {
w := httptest.NewRecorder()
server.getLoggerLevel(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}
assert.Equal(t, http.StatusOK, w.Code)

var loggerInfo LoggerInfo
err := json.Unmarshal(w.Body.Bytes(), &loggerInfo)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
assert.Nil(t, err)

expectedLoggerLevel, err := logger.GetLoggerLevel(loggerName)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
assert.Nil(t, err)

if expectedLoggerLevel.String() != loggerInfo.Level {
t.Errorf("Wrong logger level, expected %s, but got %s", expectedLoggerLevel.String(), loggerInfo.Level)
}

if loggerName != loggerInfo.Name {
t.Errorf("Wrong logger name, expected %s, but got %s", loggerName, loggerInfo.Name)
}
assert.Equal(t, loggerInfo.Level, expectedLoggerLevel.String())
assert.Equal(t, loggerInfo.Name, loggerName)
}

req := httptest.NewRequest(http.MethodGet, patternLoggers, nil)
w := httptest.NewRecorder()
server.getLoggerLevel(w, req)

assert.Equal(t, http.StatusOK, w.Code)
expectedLoggerNames := append(logger.GetLoggerNames(), bpfLoggerName)
var actualLoggerNames []string
err := json.Unmarshal(w.Body.Bytes(), &actualLoggerNames)
assert.Nil(t, err)

sort.Strings(expectedLoggerNames)
sort.Strings(actualLoggerNames)
assert.Equal(t, expectedLoggerNames, actualLoggerNames)
}

func TestServer_setBpfLevel(t *testing.T) {
func TestServer_getAndSetBpfLevel(t *testing.T) {
// Test in two modes
configs := []options.BpfConfig{{
Mode: "ads",
Expand Down Expand Up @@ -126,17 +131,30 @@ func TestServer_setBpfLevel(t *testing.T) {
w := httptest.NewRecorder()
server.setLoggerLevel(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}

assert.Equal(t, http.StatusOK, w.Code)
server.bpfLogLevelMap.Lookup(&key, &actualLoggerLevel)

if actualLoggerLevel != expectedLoggerLevel {
t.Errorf("Wrong logger level, expected %d, but got %d", expectedLoggerLevel, actualLoggerLevel)
}
assert.Equal(t, expectedLoggerLevel, actualLoggerLevel)
}
}

// test get bpf log level
getLoggerUrl := patternLoggers + "?name=" + bpfLoggerName
req := httptest.NewRequest(http.MethodGet, getLoggerUrl, nil)
w := httptest.NewRecorder()
server.getLoggerLevel(w, req)

var (
actualLoggerInfo LoggerInfo
expectedLoggerInfo *LoggerInfo
)
err := json.Unmarshal(w.Body.Bytes(), &actualLoggerInfo)
assert.Nil(t, err)

expectedLoggerInfo, err = server.getBpfLogLevel()
assert.Nil(t, err)
assert.NotNil(t, expectedLoggerInfo)
assert.Equal(t, expectedLoggerInfo.Level, actualLoggerInfo.Level)
assert.Equal(t, expectedLoggerInfo.Name, actualLoggerInfo.Name)
})
}
}
Expand Down Expand Up @@ -171,18 +189,10 @@ func TestServer_setLoggerLevel(t *testing.T) {
w := httptest.NewRecorder()
server.setLoggerLevel(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}

assert.Equal(t, http.StatusOK, w.Code)
actualLoggerLevel, err := logger.GetLoggerLevel(loggerName)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

if actualLoggerLevel.String() != loggerInfo.Level {
t.Errorf("Wrong logger level, expected %s, but got %s", loggerInfo.Level, actualLoggerLevel.String())
}
assert.Nil(t, err)
assert.Equal(t, loggerInfo.Level, actualLoggerLevel.String())
}
}
}
Expand Down
Loading