diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b0204f..804465b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: - go-version: [1.18.x] + go-version: [1.21.x] runs-on: ubuntu-latest diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 24e0e6c..203a9f8 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -7,7 +7,7 @@ jobs: name: lint strategy: matrix: - go-version: [1.18.x] + go-version: [1.21.x] runs-on: ubuntu-latest steps: - name: Install Go @@ -19,7 +19,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.50.1 + version: v1.54.2 # Optional: if set to true then the action will use pre-installed Go. skip-go-installation: true diff --git a/Makefile b/Makefile index 9457338..574c4d6 100644 --- a/Makefile +++ b/Makefile @@ -49,8 +49,8 @@ DOCKER_REGISTRY_REPO ?= mattermost/${APP_NAME}-daily DOCKER_USER ?= user DOCKER_PASSWORD ?= password ## Docker Images -DOCKER_IMAGE_GO += "golang:${GO_VERSION}@sha256:fa71e1447cb0241324162a6c51297206928d755b16142eceec7b809af55061e5" -DOCKER_IMAGE_GOLINT += "golangci/golangci-lint:v1.50.1@sha256:94388e00f07c64262b138a7508f857473e30fdf0f59d04b546a305fc12cb5961" +DOCKER_IMAGE_GO += "golang:${GO_VERSION}@sha256:b17c35044f4062d83c815434615997eed97697daae8745c6dd39dc3673b87efb" +DOCKER_IMAGE_GOLINT += "golangci/golangci-lint:v1.54.2@sha256:abe731fe6bb335a30eab303a41dd5c2b630bb174372a4da08e3d42eab5324127" DOCKER_IMAGE_DOCKERLINT += "hadolint/hadolint:v2.9.2@sha256:d355bd7df747a0f124f3b5e7b21e9dafd0cb19732a276f901f0fdee243ec1f3b" DOCKER_IMAGE_COSIGN += "bitnami/cosign:1.8.0@sha256:8c2c61c546258fffff18b47bb82a65af6142007306b737129a7bd5429d53629a" DOCKER_IMAGE_GH_CLI += "registry.internal.mattermost.com/images/build-ci:3.16.0@sha256:f6a229a9ababef3c483f237805ee4c3dbfb63f5de4fbbf58f4c4b6ed8fcd34b6" diff --git a/build/Dockerfile b/build/Dockerfile index 7808172..c688d60 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,7 +1,7 @@ # This dockerfile is used to build Mattermost calls-recorder # A multi stage build, with golang used as a builder # and ubuntu:22.04 as runner -ARG GO_IMAGE=golang:1.18@sha256:fa71e1447cb0241324162a6c51297206928d755b16142eceec7b809af55061e5 +ARG GO_IMAGE=golang:1.21@sha256:b17c35044f4062d83c815434615997eed97697daae8745c6dd39dc3673b87efb ARG ARCH ARG RUNNER_IMAGE diff --git a/build/pkgs_list b/build/pkgs_list index e3d5ada..ff542e5 100644 --- a/build/pkgs_list +++ b/build/pkgs_list @@ -1,7 +1,7 @@ ca-certificates=20230311 -chromium=117.0.5938.132-1 -chromium-driver=117.0.5938.132-1 -chromium-sandbox=117.0.5938.132-1 +chromium=117.0.5938.132-2 +chromium-driver=117.0.5938.132-2 +chromium-sandbox=117.0.5938.132-2 ffmpeg=7:6.0-7 fonts-recommended=1 pulseaudio=16.1+dfsg1-2+b1 diff --git a/cmd/recorder/cmd.go b/cmd/recorder/cmd.go index d26f3c2..d86c898 100644 --- a/cmd/recorder/cmd.go +++ b/cmd/recorder/cmd.go @@ -2,7 +2,7 @@ package main import ( "io" - "log" + "log/slog" "os/exec" "strings" ) @@ -12,7 +12,7 @@ const ( ) func runCmd(cmd string, args string) (*exec.Cmd, error) { - log.Printf("running %s: %q", cmd, args) + slog.Debug("running cmd", slog.String("cmd", cmd), slog.String("args", args)) c := exec.Command(cmd, strings.Split(args, " ")...) stdout, err := c.StdoutPipe() @@ -37,10 +37,17 @@ func runCmd(cmd string, args string) (*exec.Cmd, error) { return } if err != nil { - log.Printf("%s (%s): error reading: %s", cmd, name, err) + slog.Debug("error reading log buffer", + slog.String("cmd", cmd), + slog.String("name", name), + slog.String("err", err.Error()), + ) return } - log.Printf("%s (%s): %s", cmd, name, strings.TrimSuffix(string(buf[:n]), "\n")) + slog.Debug(strings.TrimSuffix(string(buf[:n]), "\n"), + slog.String("cmd", cmd), + slog.String("name", name), + ) } } diff --git a/cmd/recorder/job.go b/cmd/recorder/job.go new file mode 100644 index 0000000..9a70e2a --- /dev/null +++ b/cmd/recorder/job.go @@ -0,0 +1,46 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/mattermost/mattermost-plugin-calls/server/public" +) + +func (rec *Recorder) postJobStatus(status public.JobStatus) error { + apiURL := fmt.Sprintf("%s/plugins/%s/bot/calls/%s/jobs/%s/status", + rec.client.URL, pluginID, rec.cfg.CallID, rec.cfg.RecordingID) + + payload, err := json.Marshal(&status) + if err != nil { + return fmt.Errorf("failed to marshal: %w", err) + } + + ctx, cancelCtx := context.WithTimeout(context.Background(), httpRequestTimeout) + defer cancelCtx() + resp, err := rec.client.DoAPIRequestBytes(ctx, http.MethodPost, apiURL, payload, "") + if err != nil { + return fmt.Errorf("request failed%w", err) + } + defer resp.Body.Close() + cancelCtx() + + return nil +} + +func (rec *Recorder) ReportJobFailure(errMsg string) error { + return rec.postJobStatus(public.JobStatus{ + JobType: public.JobTypeRecording, + Status: public.JobStatusTypeFailed, + Error: errMsg, + }) +} + +func (rec *Recorder) ReportJobStarted() error { + return rec.postJobStatus(public.JobStatus{ + JobType: public.JobTypeRecording, + Status: public.JobStatusTypeStarted, + }) +} diff --git a/cmd/recorder/job_test.go b/cmd/recorder/job_test.go new file mode 100644 index 0000000..f56b488 --- /dev/null +++ b/cmd/recorder/job_test.go @@ -0,0 +1,94 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/mattermost/calls-recorder/cmd/recorder/config" + "github.com/mattermost/mattermost-plugin-calls/server/public" + + "github.com/stretchr/testify/require" +) + +func TestReportJobFailure(t *testing.T) { + middlewares := []middleware{} + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for _, mw := range middlewares { + if mw(w, r) { + return + } + } + http.NotFound(w, r) + })) + defer ts.Close() + + cfg := config.RecorderConfig{ + SiteURL: ts.URL, + CallID: "8w8jorhr7j83uqr6y1st894hqe", + ThreadID: "udzdsg7dwidbzcidx5khrf8nee", + RecordingID: "67t5u6cmtfbb7jug739d43xa9e", + AuthToken: "qj75unbsef83ik9p7ueypb6iyw", + } + cfg.SetDefaults() + rec, err := NewRecorder(cfg) + require.NoError(t, err) + require.NotNil(t, rec) + + t.Run("request failure", func(t *testing.T) { + middlewares = []middleware{ + func(w http.ResponseWriter, r *http.Request) bool { + if r.URL.Path != "/plugins/com.mattermost.calls/bot/calls/8w8jorhr7j83uqr6y1st894hqe/jobs/67t5u6cmtfbb7jug739d43xa9e/status" { + w.WriteHeader(404) + return true + } + + w.WriteHeader(400) + fmt.Fprintln(w, `{"message": "server error"}`) + return true + }, + } + err := rec.ReportJobFailure("") + require.EqualError(t, err, "request failed: server error") + }) + + t.Run("success", func(t *testing.T) { + var errMsg string + middlewares = []middleware{ + func(w http.ResponseWriter, r *http.Request) bool { + if r.URL.Path != "/plugins/com.mattermost.calls/bot/calls/8w8jorhr7j83uqr6y1st894hqe/jobs/67t5u6cmtfbb7jug739d43xa9e/status" { + w.WriteHeader(404) + return true + } + + var status public.JobStatus + if err := json.NewDecoder(r.Body).Decode(&status); err != nil { + w.WriteHeader(400) + fmt.Fprintf(w, `{"message": %q}`, err.Error()) + return true + } + + if status.JobType != public.JobTypeRecording { + w.WriteHeader(400) + return true + } + + if status.Status != public.JobStatusTypeFailed { + w.WriteHeader(400) + return true + } + + errMsg = status.Error + + w.WriteHeader(200) + return true + }, + } + err := rec.ReportJobFailure("some error") + require.Nil(t, err) + require.Equal(t, "some error", errMsg) + }) +} diff --git a/cmd/recorder/main.go b/cmd/recorder/main.go index 4e20ddf..0dc783b 100644 --- a/cmd/recorder/main.go +++ b/cmd/recorder/main.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "log" + "log/slog" "os" "os/signal" "syscall" @@ -11,41 +11,56 @@ import ( ) func main() { - log.SetFlags(log.LstdFlags | log.Lmicroseconds) + logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ + AddSource: true, + Level: slog.LevelDebug, + ReplaceAttr: slogReplaceAttr, + })) + slog.SetDefault(logger) pid := os.Getpid() if err := os.WriteFile("/tmp/recorder.pid", []byte(fmt.Sprintf("%d", pid)), 0666); err != nil { - log.Fatalf("failed to write pid file: %s", err) + slog.Error("failed to write pid file", slog.String("err", err.Error())) + os.Exit(1) } cfg, err := config.LoadFromEnv() if err != nil { - log.Fatalf("failed to load config: %s", err) + slog.Error("failed to load config", slog.String("err", err.Error())) + os.Exit(1) } cfg.SetDefaults() + slog.SetDefault(logger.With("jobID", cfg.RecordingID)) + recorder, err := NewRecorder(cfg) if err != nil { - log.Fatalf("failed to create recorder: %s", err) + slog.Error("failed to create recorder", slog.String("err", err.Error())) + os.Exit(1) } - log.Printf("starting recordinig") + slog.Info("starting recording") if err := recorder.Start(); err != nil { - log.Fatalf("failed to start recording: %s", err) + if err := recorder.ReportJobFailure(err.Error()); err != nil { + slog.Error("failed to report job failure", slog.String("err", err.Error())) + } + slog.Error("failed to start recording", slog.String("err", err.Error())) + os.Exit(1) } - log.Printf("recording has started") + slog.Info("recording has started") sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) <-sig - log.Printf("received SIGTERM, stopping recording") + slog.Info("received SIGTERM, stopping recording") if err := recorder.Stop(); err != nil { - log.Fatalf("failed to stop recording: %s", err) + slog.Error("failed to stop recording", slog.String("err", err.Error())) + os.Exit(1) } - log.Printf("recording has finished, exiting") + slog.Info("recording has finished, exiting") } diff --git a/cmd/recorder/recorder.go b/cmd/recorder/recorder.go index 2155e9d..fdda590 100644 --- a/cmd/recorder/recorder.go +++ b/cmd/recorder/recorder.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "log" + "log/slog" "os" "os/exec" "path/filepath" @@ -16,6 +16,8 @@ import ( "github.com/mattermost/calls-recorder/cmd/recorder/config" + "github.com/mattermost/mattermost/server/public/model" + cruntime "github.com/chromedp/cdproto/runtime" "github.com/chromedp/chromedp" ) @@ -27,7 +29,6 @@ const ( stopTimeout = 10 * time.Second maxUploadRetryAttempts = 5 uploadRetryAttemptWaitTime = 5 * time.Second - initPollInterval = 250 * time.Millisecond connCheckInterval = 1 * time.Second ) @@ -41,6 +42,8 @@ type Recorder struct { displayServer *exec.Cmd transcoder *exec.Cmd + client *model.Client4 + outPath string } @@ -87,14 +90,14 @@ func (rec *Recorder) runBrowser(recURL string) error { } contextOpts := []chromedp.ContextOption{ - chromedp.WithErrorf(log.Printf), + chromedp.WithErrorf(slogDebugF), } if devMode := os.Getenv("DEV_MODE"); devMode == "true" { opts = append(opts, chromedp.Flag("unsafely-treat-insecure-origin-as-secure", "http://172.17.0.1:8065,http://host.docker.internal:8065,http://mm-server:8065,http://host.minikube.internal:8065")) opts = append(opts, chromedp.NoSandbox) - contextOpts = append(contextOpts, chromedp.WithLogf(log.Printf)) - contextOpts = append(contextOpts, chromedp.WithDebugf(log.Printf)) + contextOpts = append(contextOpts, chromedp.WithLogf(slogDebugF)) + contextOpts = append(contextOpts, chromedp.WithDebugf(slogDebugF)) } allocCtx, _ := chromedp.NewExecAllocator(context.Background(), opts...) @@ -103,9 +106,9 @@ func (rec *Recorder) runBrowser(recURL string) error { chromedp.ListenTarget(ctx, func(ev interface{}) { switch ev := ev.(type) { case *cruntime.EventExceptionThrown: - log.Printf("chrome exception: %s", ev.ExceptionDetails.Text) + slog.Error("chrome exception", slog.String("err", ev.ExceptionDetails.Text)) if ev.ExceptionDetails.Exception != nil { - log.Printf("chrome exception: %s", ev.ExceptionDetails.Exception.Description) + slog.Error("chrome exception", slog.String("err", ev.ExceptionDetails.Exception.Description)) } case *cruntime.EventConsoleAPICalled: args := make([]string, 0, len(ev.Args)) @@ -115,7 +118,7 @@ func (rec *Recorder) runBrowser(recURL string) error { if len(arg.Value) > 0 { err := json.Unmarshal(arg.Value, &val) if err != nil { - log.Printf("failed to unmarshal: %s", err) + slog.Error("failed to unmarshal", slog.String("err", err.Error())) continue } str = fmt.Sprintf("%+v", val) @@ -127,24 +130,11 @@ func (rec *Recorder) runBrowser(recURL string) error { str := fmt.Sprintf("chrome console %s %s", ev.Type.String(), strings.Join(args, " ")) - log.Printf(sanitizeConsoleLog(str)) + slog.Debug(sanitizeConsoleLog(str)) } }) - var connected bool - connectCheckExpr := "window.callsClient && window.callsClient.connected && !window.callsClient.closed" - if err := chromedp.Run(ctx, - chromedp.Navigate(recURL), - chromedp.Poll(connectCheckExpr, &connected, chromedp.WithPollingInterval(initPollInterval)), - chromedp.ActionFunc(func(ctx context.Context) error { - if connected { - log.Printf("connected to call") - close(rec.readyCh) - return nil - } - return fmt.Errorf("connectivity check failed") - }), - ); err != nil { + if err := chromedp.Run(ctx, chromedp.Navigate(recURL)); err != nil { return fmt.Errorf("failed to run chromedp: %w", err) } @@ -152,31 +142,56 @@ func (rec *Recorder) runBrowser(recURL string) error { tctx, cancelCtx := context.WithTimeout(ctx, stopTimeout) // graceful cancel if err := chromedp.Cancel(tctx); err != nil { - log.Printf("failed to cancel context: %s", err) + slog.Error("failed to cancel context", slog.String("err", err.Error())) } cancelCtx() close(rec.stoppedCh) }() - var disconnected bool - disconnectCheckExpr := "!window.callsClient || window.callsClient.closed" - ticker := time.NewTicker(connCheckInterval) defer ticker.Stop() + + var connected bool + connectCheckExpr := "window.callsClient && window.callsClient.connected && !window.callsClient.closed" + for { + select { + case <-rec.stopCh: + slog.Info("stop signal received, shutting down browser") + return nil + case <-ticker.C: + if err := chromedp.Run(ctx, + chromedp.Evaluate(connectCheckExpr, &connected), + ); err != nil { + slog.Error("failed to run chromedp", slog.String("err", err.Error())) + continue + } + if !connected { + slog.Debug("not connected to call yet") + continue + } + + slog.Debug("connected to call") + close(rec.readyCh) + } + break + } + + var disconnected bool + disconnectCheckExpr := "!window.callsClient || window.callsClient.closed" for { select { case <-rec.stopCh: - log.Printf("stop signal received, shutting down browser") + slog.Info("stop signal received, shutting down browser") case <-ticker.C: if err := chromedp.Run(ctx, chromedp.Evaluate(disconnectCheckExpr, &disconnected), ); err != nil { - log.Printf("failed to run chromedp: %s", err) + slog.Error("failed to run chromedp", slog.String("err", err.Error())) } if disconnected { - log.Printf("disconnected from call, shutting down") + slog.Info("disconnected from call, shutting down") if err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM); err != nil { - log.Printf("failed to send SIGTERM signal: %s", err) + slog.Error("failed to send SIGTERM signal", slog.String("err", err.Error())) } return nil } @@ -189,12 +204,12 @@ func (rec *Recorder) runBrowser(recURL string) error { if err := chromedp.Run(ctx, chromedp.Evaluate(disconnectExpr+disconnectCheckExpr, &disconnected), ); err != nil { - log.Printf("failed to run chromedp: %s", err) + slog.Error("failed to run chromedp", slog.String("err", err.Error())) } if disconnected { - log.Printf("disconnected from call successfully") + slog.Info("disconnected from call successfully") } else { - log.Printf("failed to disconnect") + slog.Error("failed to disconnect") } return nil @@ -214,7 +229,7 @@ func (rec *Recorder) runTranscoder(dst string) error { cmd, err := runCmd("ffmpeg", args) if err != nil { - log.Fatal(err) + return fmt.Errorf("failed to run transcoder command: %w", err) } rec.transcoder = cmd @@ -232,11 +247,15 @@ func NewRecorder(cfg config.RecorderConfig) (*Recorder, error) { return nil, fmt.Errorf("invalid config: %w", err) } + client := model.NewAPIv4Client(cfg.SiteURL) + client.SetToken(cfg.AuthToken) + return &Recorder{ cfg: cfg, readyCh: make(chan struct{}), stopCh: make(chan struct{}), stoppedCh: make(chan struct{}), + client: client, }, nil } @@ -248,7 +267,7 @@ func (rec *Recorder) Start() error { } else if strings.TrimSpace(string(data)) != "1" { return fmt.Errorf("kernel.unprivileged_userns_clone should be enabled for the recording process to work") } - log.Printf("kernel.unprivileged_userns_clone is correctly set") + slog.Debug("kernel.unprivileged_userns_clone is correctly set") } var err error @@ -269,7 +288,7 @@ func (rec *Recorder) Start() error { go func() { if err := rec.runBrowser(recURL); err != nil { - log.Printf("failed to run browser: %s", err) + slog.Error("failed to run browser", slog.String("err", err.Error())) } }() @@ -279,7 +298,7 @@ func (rec *Recorder) Start() error { return fmt.Errorf("timed out waiting for ready event") } - log.Printf("browser connected, ready to record") + slog.Info("browser connected, ready to record") filename := fmt.Sprintf("%s-%s.mp4", rec.cfg.CallID, time.Now().UTC().Format("2006-01-02-15_04_05")) rec.outPath = filepath.Join("/recs", filename) @@ -288,15 +307,19 @@ func (rec *Recorder) Start() error { return fmt.Errorf("failed to run transcoder: %s", err) } + if err := rec.ReportJobStarted(); err != nil { + return fmt.Errorf("failed to report job started status: %w", err) + } + return nil } func (rec *Recorder) Stop() error { if err := rec.transcoder.Process.Signal(syscall.SIGTERM); err != nil { - log.Printf("failed to send signal: %s", err.Error()) + slog.Error("failed to send signal", slog.String("err", err.Error())) } if err := rec.transcoder.Wait(); err != nil { - log.Printf("failed waiting for transcoder to exit: %s", err) + slog.Error("failed waiting for transcoder to exit", slog.String("err", err.Error())) } close(rec.stopCh) @@ -308,7 +331,7 @@ func (rec *Recorder) Stop() error { } if err := rec.displayServer.Process.Kill(); err != nil { - log.Printf("failed to stop display process: %s", err) + slog.Error("failed to stop display process", slog.String("err", err.Error())) } // TODO (MM-48546): implement better retry logic. @@ -316,7 +339,7 @@ func (rec *Recorder) Stop() error { for { err := rec.uploadRecording() if err == nil { - log.Printf("recording uploaded successfully") + slog.Info("recording uploaded successfully") break } @@ -325,13 +348,13 @@ func (rec *Recorder) Stop() error { } attempt++ - log.Printf("failed to upload recording: %s", err) - log.Printf("retrying in %s", uploadRetryAttemptWaitTime) + slog.Info("failed to upload recording", slog.String("err", err.Error())) + slog.Info("retrying", slog.Duration("wait_time", uploadRetryAttemptWaitTime)) time.Sleep(uploadRetryAttemptWaitTime) } if err := os.Remove(rec.outPath); err != nil { - log.Printf("failed to remove recording: %s", err) + slog.Error("failed to remove recording", slog.String("err", err.Error())) } return nil diff --git a/cmd/recorder/upload.go b/cmd/recorder/upload.go index 3badcd3..ce7fe58 100644 --- a/cmd/recorder/upload.go +++ b/cmd/recorder/upload.go @@ -29,9 +29,7 @@ func (rec *Recorder) uploadRecording() error { return fmt.Errorf("failed to stat file: %w", err) } - client := model.NewAPIv4Client(rec.cfg.SiteURL) - client.SetToken(rec.cfg.AuthToken) - apiURL := fmt.Sprintf("%s/plugins/%s/bot", client.URL, pluginID) + apiURL := fmt.Sprintf("%s/plugins/%s/bot", rec.client.URL, pluginID) us := &model.UploadSession{ ChannelId: rec.cfg.CallID, @@ -46,7 +44,7 @@ func (rec *Recorder) uploadRecording() error { ctx, cancelCtx := context.WithTimeout(context.Background(), httpRequestTimeout) defer cancelCtx() - resp, err := client.DoAPIRequestBytes(ctx, http.MethodPost, apiURL+"/uploads", payload, "") + resp, err := rec.client.DoAPIRequestBytes(ctx, http.MethodPost, apiURL+"/uploads", payload, "") if err != nil { return fmt.Errorf("failed to create upload: %w", err) } @@ -59,7 +57,7 @@ func (rec *Recorder) uploadRecording() error { ctx, cancelCtx = context.WithTimeout(context.Background(), httpUploadTimeout) defer cancelCtx() - resp, err = client.DoAPIRequestReader(ctx, http.MethodPost, apiURL+"/uploads/"+us.Id, file, nil) + resp, err = rec.client.DoAPIRequestReader(ctx, http.MethodPost, apiURL+"/uploads/"+us.Id, file, nil) if err != nil { return fmt.Errorf("failed to upload data: %w", err) } @@ -84,7 +82,7 @@ func (rec *Recorder) uploadRecording() error { url := fmt.Sprintf("%s/calls/%s/recordings", apiURL, rec.cfg.CallID) ctx, cancelCtx = context.WithTimeout(context.Background(), httpRequestTimeout) defer cancelCtx() - resp, err = client.DoAPIRequestBytes(ctx, http.MethodPost, url, payload, "") + resp, err = rec.client.DoAPIRequestBytes(ctx, http.MethodPost, url, payload, "") if err != nil { return fmt.Errorf("failed to save recording: %w", err) } diff --git a/cmd/recorder/utils.go b/cmd/recorder/utils.go index bc7e242..e0e0064 100644 --- a/cmd/recorder/utils.go +++ b/cmd/recorder/utils.go @@ -1,6 +1,9 @@ package main import ( + "fmt" + "log/slog" + "path/filepath" "regexp" ) @@ -11,3 +14,16 @@ var ( func sanitizeConsoleLog(str string) string { return icePasswordRE.ReplaceAllString(str, "ice-pwd:XXX") } + +func slogDebugF(format string, args ...any) { + slog.Debug(fmt.Sprintf(format, args...)) +} + +func slogReplaceAttr(_ []string, a slog.Attr) slog.Attr { + if a.Key == slog.SourceKey { + source := a.Value.Any().(*slog.Source) + source.File = filepath.Base(source.File) + } + + return a +} diff --git a/go.mod b/go.mod index ce10144..cb9fd6c 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,11 @@ module github.com/mattermost/calls-recorder -go 1.18 +go 1.21.1 require ( github.com/chromedp/cdproto v0.0.0-20230828023241-f357fd93b5d6 github.com/chromedp/chromedp v0.9.2 + github.com/mattermost/mattermost-plugin-calls/server/public v0.0.1 github.com/mattermost/mattermost/server/public v0.0.0-20230613002302-62a3ee8adcb5 github.com/stretchr/testify v1.8.2 ) diff --git a/go.sum b/go.sum index d93c695..daaed52 100644 --- a/go.sum +++ b/go.sum @@ -96,6 +96,8 @@ github.com/mattermost/ldap v3.0.4+incompatible h1:SOeNnz+JNR+foQ3yHkYqijb9MLPhXN github.com/mattermost/ldap v3.0.4+incompatible/go.mod h1:b4reDCcGpBxJ4WX0f224KFY+OR0npin7or7EFpeIko4= github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE= github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY= +github.com/mattermost/mattermost-plugin-calls/server/public v0.0.1 h1:lgfrPdGPlGPzYk3soGKvFe50vj+UYsmjIRMILzo98iY= +github.com/mattermost/mattermost-plugin-calls/server/public v0.0.1/go.mod h1:uBazxv1nNZkg53pWH/lcuCtslgAfB9uTqNG+43MDNyQ= github.com/mattermost/mattermost/server/public v0.0.0-20230613002302-62a3ee8adcb5 h1:X8ue+QQn0VJe6qR0q2kHGFhQCn5T4rqb7XS0t6R1r3A= github.com/mattermost/mattermost/server/public v0.0.0-20230613002302-62a3ee8adcb5/go.mod h1:TtECPYX/ftU43bCGqN5W3Ic2gPDN2+zeKhXfE2YPRvw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=