From f853c2f940f674aaf84935d6419c41c35559f4f2 Mon Sep 17 00:00:00 2001 From: "Harrison (Harry) Cramer" <32515581+harrisoncramer@users.noreply.github.com> Date: Mon, 30 Oct 2023 21:57:23 -0400 Subject: [PATCH] Feat: Improve Logging for Go Server (#68) This MR adds an optional `debug` object to the configuration table to help users debug any connectivity issues with Gitlab. The table lets you log the requests and responses from the Go server. --- README.md | 1 + cmd/client.go | 63 ++++++++++++++++++++++++++++++++++++++----- lua/gitlab/server.lua | 24 +++++++++-------- lua/gitlab/state.lua | 3 ++- 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2e47043..76d67d0 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Here is the default setup function. All of these values are optional, and if you require("gitlab").setup({ port = nil, -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically log_path = vim.fn.stdpath("cache") .. "/gitlab.nvim.log", -- Log path for the Go server + debug = { go_request = false, go_response = false }, -- Which values to log reviewer = "delta", -- The reviewer type ("delta" or "diffview") attachment_dir = nil, -- The local directory for files (see the "summary" section) popup = { -- The popup for comment creation, editing, and replying diff --git a/cmd/client.go b/cmd/client.go index e8369fa..343aa9d 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -5,9 +5,11 @@ import ( "errors" "fmt" "net/http" + "net/http/httputil" "os" "strconv" + "github.com/hashicorp/go-retryablehttp" "github.com/xanzy/go-gitlab" ) @@ -17,15 +19,17 @@ type Client struct { mergeId int gitlabInstance string authToken string + logPath string + debug bool git *gitlab.Client } -type Logger struct { - Active bool +type DebugSettings struct { + GoRequest bool `json:"go_request"` + GoResponse bool `json:"go_response"` } -func (l Logger) Printf(s string, args ...interface{}) { - logString := fmt.Sprintf(s+"\n", args...) +var requestLogger retryablehttp.RequestLogHook = func(l retryablehttp.Logger, r *http.Request, i int) { logPath := os.Args[len(os.Args)-1] file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) @@ -33,7 +37,31 @@ func (l Logger) Printf(s string, args ...interface{}) { panic(err) } defer file.Close() - _, err = file.Write([]byte(logString)) + + token := r.Header.Get("Private-Token") + r.Header.Set("Private-Token", "REDACTED") + res, err := httputil.DumpRequest(r, true) + r.Header.Set("Private-Token", token) + + _, err = file.Write([]byte("\n-- REQUEST --\n")) + _, err = file.Write(res) + _, err = file.Write([]byte("\n")) +} + +var responseLogger retryablehttp.ResponseLogHook = func(l retryablehttp.Logger, response *http.Response) { + logPath := os.Args[len(os.Args)-1] + + file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + panic(err) + } + defer file.Close() + + res, err := httputil.DumpResponse(response, true) + + _, err = file.Write([]byte("\n-- RESPONSE --\n")) + _, err = file.Write(res) + _, err = file.Write([]byte("\n")) } /* This will initialize the client with the token and check for the basic project ID and command arguments */ @@ -46,6 +74,15 @@ func (c *Client) init(branchName string) error { projectId := os.Args[1] gitlabInstance := os.Args[2] authToken := os.Args[4] + debugSettings := os.Args[5] + + var debugObject DebugSettings + err := json.Unmarshal([]byte(debugSettings), &debugObject) + if err != nil { + return fmt.Errorf("Could not parse debug settings: %w, %s", err, debugSettings) + } + + logPath := os.Args[len(os.Args)-1] if projectId == "" { return errors.New("Project ID cannot be empty") @@ -62,11 +99,23 @@ func (c *Client) init(branchName string) error { c.gitlabInstance = gitlabInstance c.projectId = projectId c.authToken = authToken + c.logPath = logPath - var l Logger var apiCustUrl = fmt.Sprintf(c.gitlabInstance + "/api/v4") - git, err := gitlab.NewClient(authToken, gitlab.WithBaseURL(apiCustUrl), gitlab.WithCustomLogger(l)) + gitlabOptions := []gitlab.ClientOptionFunc{ + gitlab.WithBaseURL(apiCustUrl), + } + + if debugObject.GoRequest { + gitlabOptions = append(gitlabOptions, gitlab.WithRequestLogHook(requestLogger)) + } + + if debugObject.GoResponse { + gitlabOptions = append(gitlabOptions, gitlab.WithResponseLogHook(responseLogger)) + } + + git, err := gitlab.NewClient(authToken, gitlabOptions...) if err != nil { return fmt.Errorf("Failed to create client: %v", err) diff --git a/lua/gitlab/server.lua b/lua/gitlab/server.lua index 836d90d..3136836 100644 --- a/lua/gitlab/server.lua +++ b/lua/gitlab/server.lua @@ -12,16 +12,18 @@ M.start = function(callback) local parsed_port = nil local callback_called = false local command = state.settings.bin - .. " " - .. state.settings.project_id - .. " " - .. state.settings.gitlab_url - .. " " - .. port - .. " " - .. state.settings.auth_token - .. " " - .. state.settings.log_path + .. " " + .. state.settings.project_id + .. " " + .. state.settings.gitlab_url + .. " " + .. port + .. " " + .. state.settings.auth_token + .. " " + .. "'" .. vim.json.encode(state.settings.debug) .. "'" + .. " " + .. state.settings.log_path local job_id = vim.fn.jobstart(command, { on_stdout = function(_, data) @@ -86,7 +88,7 @@ M.build = function(override) end local cmd = u.is_windows() and "cd %s\\cmd && go build -o bin.exe && move bin.exe ..\\" - or "cd %s/cmd && go build -o bin && mv bin ../bin" + or "cd %s/cmd && go build -o bin && mv bin ../bin" local command = string.format(cmd, state.settings.bin_path) local null = u.is_windows() and " >NUL" or " > /dev/null" diff --git a/lua/gitlab/state.lua b/lua/gitlab/state.lua index 2811ebc..512e881 100644 --- a/lua/gitlab/state.lua +++ b/lua/gitlab/state.lua @@ -7,8 +7,9 @@ local u = require("gitlab.utils") local M = {} -- These are the default settings for the plugin -M.settings = { +M.settings = { port = nil, -- choose random port + debug = { go_request = false, go_response = false }, log_path = (vim.fn.stdpath("cache") .. "/gitlab.nvim.log"), reviewer = "delta", attachment_dir = "",