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

feat: agent logs #432

Merged
merged 1 commit into from
Apr 25, 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
4 changes: 2 additions & 2 deletions internal/util/log_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"time"
)

func ReadLog(ctx context.Context, logReader *io.Reader, follow bool, c chan []byte, errChan chan error) {
reader := bufio.NewReader(*logReader)
func ReadLog(ctx context.Context, logReader io.Reader, follow bool, c chan []byte, errChan chan error) {
reader := bufio.NewReader(logReader)

for {
select {
Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
)

func (a *Agent) Start() error {
a.initLogs()

log.Info("Starting Daytona Agent")

a.startTime = time.Now()
Expand Down
21 changes: 18 additions & 3 deletions pkg/agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package config
import (
"errors"
"os"
"strings"

"github.com/go-playground/validator/v10"
"github.com/kelseyhightower/envconfig"
Expand All @@ -20,9 +21,10 @@ type DaytonaServerConfig struct {
}

type Config struct {
ProjectDir string `envconfig:"DAYTONA_WS_DIR"`
ProjectName string `envconfig:"DAYTONA_WS_PROJECT_NAME"`
WorkspaceId string `envconfig:"DAYTONA_WS_ID" validate:"required"`
ProjectDir string `envconfig:"DAYTONA_WS_DIR"`
ProjectName string `envconfig:"DAYTONA_WS_PROJECT_NAME"`
WorkspaceId string `envconfig:"DAYTONA_WS_ID" validate:"required"`
LogFilePath *string `envconfig:"DAYTONA_AGENT_LOG_FILE_PATH"`
Server DaytonaServerConfig
Mode Mode
}
Expand Down Expand Up @@ -69,5 +71,18 @@ func GetConfig(mode Mode) (*Config, error) {
}
}

config.LogFilePath = GetLogFilePath()

return config, nil
}

func GetLogFilePath() *string {
logFilePath, ok := os.LookupEnv("DAYTONA_AGENT_LOG_FILE_PATH")
if !ok {
return nil
}

logFilePath = strings.Replace(logFilePath, "$HOME", os.Getenv("HOME"), 1)

return &logFilePath
}
7 changes: 6 additions & 1 deletion pkg/agent/git/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package git

import (
"bytes"
"io"
"os"

"github.com/daytonaio/daytona/pkg/serverapiclient"
Expand All @@ -17,16 +18,20 @@ import (
type Service struct {
ProjectDir string
GitConfigFileName string
LogWriter io.Writer
}

func (s *Service) CloneRepository(project *serverapiclient.Project, authToken *string) error {
cloneOptions := &git.CloneOptions{
URL: *project.Repository.Url,
Progress: os.Stdout,
SingleBranch: true,
InsecureSkipTLS: true,
}

if s.LogWriter != nil {
cloneOptions.Progress = s.LogWriter
}

if authToken != nil {
cloneOptions.Auth = &http.BasicAuth{
Username: "daytona",
Expand Down
44 changes: 44 additions & 0 deletions pkg/agent/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2024 Daytona Platforms Inc.
// SPDX-License-Identifier: Apache-2.0

package agent
Tpuljak marked this conversation as resolved.
Show resolved Hide resolved

import (
"io"

log "github.com/sirupsen/logrus"
)

type logFormatter struct {
textFormatter *log.TextFormatter
agentLogWriter io.Writer
}

func (f *logFormatter) Format(entry *log.Entry) ([]byte, error) {
formatted, err := f.textFormatter.Format(entry)
if err != nil {
return nil, err
}

if f.agentLogWriter != nil {
_, err = f.agentLogWriter.Write(formatted)
if err != nil {
return nil, err
}
}

// Return the original message without log decoration
// We don't want decoration to show up in the workspace creation logs
return []byte(entry.Message + "\n"), nil
}

func (s *Agent) initLogs() {
logFormatter := &logFormatter{
textFormatter: &log.TextFormatter{
ForceColors: true,
},
agentLogWriter: s.LogWriter,
}

log.SetFormatter(logFormatter)
}
2 changes: 1 addition & 1 deletion pkg/agent/ssh/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (s *Server) Start() error {
},
}

log.Println("starting ssh server on port 2222...")
log.Println("Starting ssh server on port 2222...")
return sshServer.ListenAndServe()
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package agent

import (
"io"
"time"

"github.com/daytonaio/daytona/pkg/agent/config"
Expand All @@ -29,5 +30,6 @@ type Agent struct {
Git GitService
Ssh SshServer
Tailscale TailscaleServer
LogWriter io.Writer
startTime time.Time
}
6 changes: 3 additions & 3 deletions pkg/api/controllers/log/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func writeToWs(ws *websocket.Conn, c chan []byte, errChan chan error) {
}
}

func readLog(ginCtx *gin.Context, logReader *io.Reader) {
func readLog(ginCtx *gin.Context, logReader io.Reader) {
followQuery := ginCtx.Query("follow")
follow := followQuery == "true"

Expand Down Expand Up @@ -92,7 +92,7 @@ func ReadServerLog(ginCtx *gin.Context) {
return
}

readLog(ginCtx, &reader)
readLog(ginCtx, reader)
}

func ReadWorkspaceLog(ginCtx *gin.Context) {
Expand All @@ -106,5 +106,5 @@ func ReadWorkspaceLog(ginCtx *gin.Context) {
return
}

readLog(ginCtx, &wsLogReader)
readLog(ginCtx, wsLogReader)
}
20 changes: 20 additions & 0 deletions pkg/cmd/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package agent

import (
"io"
"os"
"path"

Expand All @@ -26,6 +27,10 @@ var AgentCmd = &cobra.Command{
Short: "Start the agent process",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
if log.GetLevel() < log.InfoLevel {
log.SetLevel(log.InfoLevel)
}

agentMode := config.ModeProject

if hostModeFlag {
Expand All @@ -37,9 +42,22 @@ var AgentCmd = &cobra.Command{
log.Fatal(err)
}

gitLogWriter := io.MultiWriter(os.Stdout)
var agentLogWriter io.Writer
if config.LogFilePath != nil {
logFile, err := os.OpenFile(*config.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer logFile.Close()
gitLogWriter = io.MultiWriter(os.Stdout, logFile)
agentLogWriter = logFile
}

git := &git.Service{
ProjectDir: config.ProjectDir,
GitConfigFileName: path.Join(os.Getenv("HOME"), ".gitconfig"),
LogWriter: gitLogWriter,
}

sshServer := &ssh.Server{
Expand All @@ -62,6 +80,7 @@ var AgentCmd = &cobra.Command{
Git: git,
Ssh: sshServer,
Tailscale: tailscaleServer,
LogWriter: agentLogWriter,
}

err = agent.Start()
Expand All @@ -73,4 +92,5 @@ var AgentCmd = &cobra.Command{

func init() {
AgentCmd.Flags().BoolVar(&hostModeFlag, "host", false, "Run the agent in host mode")
AgentCmd.AddCommand(logsCmd)
}
61 changes: 61 additions & 0 deletions pkg/cmd/agent/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2024 Daytona Platforms Inc.
// SPDX-License-Identifier: Apache-2.0

package agent

import (
"context"
"fmt"
"io"
"os"

"github.com/daytonaio/daytona/internal/util"
"github.com/daytonaio/daytona/pkg/agent/config"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var followFlag bool

var logsCmd = &cobra.Command{
Use: "logs",
Short: "Output Daytona Agent logs",
Run: func(cmd *cobra.Command, args []string) {
logFilePath := config.GetLogFilePath()

if logFilePath == nil {
log.Fatal("Log file path not set")
}

file, err := os.Open(*logFilePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()

msgChan := make(chan []byte)
errChan := make(chan error)

go util.ReadLog(context.Background(), file, followFlag, msgChan, errChan)

for {
select {
case <-context.Background().Done():
return
case err := <-errChan:
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
return
}
case msg := <-msgChan:
fmt.Println(string(msg))
}
}
},
}

func init() {
logsCmd.Flags().BoolVarP(&followFlag, "follow", "f", false, "Follow logs")
}
2 changes: 2 additions & 0 deletions pkg/workspace/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func GetProjectEnvVars(project *Project, apiUrl, serverUrl string) map[string]st
"DAYTONA_SERVER_VERSION": internal.Version,
"DAYTONA_SERVER_URL": serverUrl,
"DAYTONA_SERVER_API_URL": apiUrl,
// $HOME will be replaced at runtime
"DAYTONA_AGENT_LOG_FILE_PATH": "$HOME/.daytona-agent.log",
}

return envVars
Expand Down
Loading