summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/rr/cmd/root.go8
-rw-r--r--cmd/rr/debug/debugger.go28
-rw-r--r--cmd/rr/http/reset.go6
-rw-r--r--cmd/rr/http/workers.go61
-rw-r--r--cmd/rr/util/cprint.go (renamed from cmd/rr/utils/cprint.go)2
-rw-r--r--cmd/rr/util/list.go58
-rw-r--r--service/http/rpc.go33
-rw-r--r--util/state.go62
8 files changed, 149 insertions, 109 deletions
diff --git a/cmd/rr/cmd/root.go b/cmd/rr/cmd/root.go
index 4ab37967..aabfcdea 100644
--- a/cmd/rr/cmd/root.go
+++ b/cmd/rr/cmd/root.go
@@ -24,7 +24,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
- "github.com/spiral/roadrunner/cmd/rr/utils"
+ "github.com/spiral/roadrunner/cmd/rr/util"
"github.com/spiral/roadrunner/service"
"os"
"path/filepath"
@@ -51,7 +51,7 @@ var (
Use: "rr",
SilenceErrors: true,
SilenceUsage: true,
- Short: utils.Sprintf(
+ Short: util.Sprintf(
"<green>RoadRunner, PHP Application Server:</reset>\nVersion: <yellow+hb>%s</reset>, %s",
Version,
BuildTime,
@@ -83,7 +83,7 @@ func (w *ViperWrapper) Unmarshal(out interface{}) error {
// This is called by main.main(). It only needs to happen once to the CLI.
func Execute() {
if err := CLI.Execute(); err != nil {
- utils.Printf("<red+hb>Error:</reset> <red>%s</reset>\n", err)
+ util.Printf("<red+hb>Error:</reset> <red>%s</reset>\n", err)
os.Exit(1)
}
}
@@ -100,7 +100,7 @@ func init() {
if cfg := initConfig(cfgFile, []string{"."}, ".rr"); cfg != nil {
if err := Container.Init(cfg); err != nil {
- utils.Printf("<red+hb>Error:</reset> <red>%s</reset>\n", err)
+ util.Printf("<red+hb>Error:</reset> <red>%s</reset>\n", err)
os.Exit(1)
}
}
diff --git a/cmd/rr/debug/debugger.go b/cmd/rr/debug/debugger.go
index ed9a1a56..5b1d586b 100644
--- a/cmd/rr/debug/debugger.go
+++ b/cmd/rr/debug/debugger.go
@@ -4,7 +4,7 @@ import (
"fmt"
"github.com/sirupsen/logrus"
"github.com/spiral/roadrunner"
- "github.com/spiral/roadrunner/cmd/rr/utils"
+ "github.com/spiral/roadrunner/cmd/rr/util"
rrhttp "github.com/spiral/roadrunner/service/http"
"net/http"
"strings"
@@ -24,7 +24,7 @@ func (s *debugger) listener(event int, ctx interface{}) {
switch event {
case rrhttp.EventResponse:
e := ctx.(*rrhttp.ResponseEvent)
- s.logger.Info(utils.Sprintf(
+ s.logger.Info(util.Sprintf(
"<cyan+h>%s</reset> %s <white+hb>%s</reset> %s",
e.Request.RemoteAddr,
statusColor(e.Response.Status),
@@ -35,14 +35,14 @@ func (s *debugger) listener(event int, ctx interface{}) {
e := ctx.(*rrhttp.ErrorEvent)
if _, ok := e.Error.(roadrunner.JobError); ok {
- s.logger.Info(utils.Sprintf(
+ s.logger.Info(util.Sprintf(
"%s <white+hb>%s</reset> %s",
statusColor(500),
e.Request.Method,
uri(e.Request),
))
} else {
- s.logger.Info(utils.Sprintf(
+ s.logger.Info(util.Sprintf(
"%s <white+hb>%s</reset> %s <red>%s</reset>",
statusColor(500),
e.Request.Method,
@@ -55,13 +55,13 @@ func (s *debugger) listener(event int, ctx interface{}) {
switch event {
case roadrunner.EventWorkerKill:
w := ctx.(*roadrunner.Worker)
- s.logger.Warning(utils.Sprintf(
+ s.logger.Warning(util.Sprintf(
"<white+hb>worker.%v</reset> <yellow>killed</red>",
*w.Pid,
))
case roadrunner.EventWorkerError:
err := ctx.(roadrunner.WorkerError)
- s.logger.Error(utils.Sprintf(
+ s.logger.Error(util.Sprintf(
"<white+hb>worker.%v</reset> <red>%s</reset>",
*err.Worker.Pid,
err.Caused,
@@ -71,7 +71,7 @@ func (s *debugger) listener(event int, ctx interface{}) {
// outputs
switch event {
case roadrunner.EventStderrOutput:
- s.logger.Warning(utils.Sprintf(
+ s.logger.Warning(util.Sprintf(
"<yellow>%s</reset>",
strings.Trim(string(ctx.([]byte)), "\r\n"),
))
@@ -80,15 +80,15 @@ func (s *debugger) listener(event int, ctx interface{}) {
// rr server events
switch event {
case roadrunner.EventServerFailure:
- s.logger.Error(utils.Sprintf("<red>server is dead</reset>"))
+ s.logger.Error(util.Sprintf("<red>server is dead</reset>"))
}
// pool events
switch event {
case roadrunner.EventPoolConstruct:
- s.logger.Debug(utils.Sprintf("<cyan>new worker pool</reset>"))
+ s.logger.Debug(util.Sprintf("<cyan>new worker pool</reset>"))
case roadrunner.EventPoolError:
- s.logger.Error(utils.Sprintf("<red>%s</reset>", ctx))
+ s.logger.Error(util.Sprintf("<red>%s</reset>", ctx))
}
//s.logger.Warning(event, ctx)
@@ -96,18 +96,18 @@ func (s *debugger) listener(event int, ctx interface{}) {
func statusColor(status int) string {
if status < 300 {
- return utils.Sprintf("<green>%v</reset>", status)
+ return util.Sprintf("<green>%v</reset>", status)
}
if status < 400 {
- return utils.Sprintf("<cyan>%v</reset>", status)
+ return util.Sprintf("<cyan>%v</reset>", status)
}
if status < 500 {
- return utils.Sprintf("<yellow>%v</reset>", status)
+ return util.Sprintf("<yellow>%v</reset>", status)
}
- return utils.Sprintf("<red>%v</reset>", status)
+ return util.Sprintf("<red>%v</reset>", status)
}
// uri fetches full uri from request in a form of string (including https scheme if TLS connection is enabled).
diff --git a/cmd/rr/http/reset.go b/cmd/rr/http/reset.go
index 3bc089ec..f1129eef 100644
--- a/cmd/rr/http/reset.go
+++ b/cmd/rr/http/reset.go
@@ -24,7 +24,7 @@ import (
"errors"
"github.com/spf13/cobra"
rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/rr/utils"
+ "github.com/spiral/roadrunner/cmd/rr/util"
"github.com/spiral/roadrunner/service"
"github.com/spiral/roadrunner/service/rpc"
)
@@ -49,13 +49,13 @@ func reloadHandler(cmd *cobra.Command, args []string) error {
}
defer client.Close()
- utils.Printf("<green>restarting http worker pool</reset>: ")
+ util.Printf("<green>restarting http worker pool</reset>: ")
var r string
if err := client.Call("http.Reset", true, &r); err != nil {
return err
}
- utils.Printf("<green+hb>done</reset>\n")
+ util.Printf("<green+hb>done</reset>\n")
return nil
}
diff --git a/cmd/rr/http/workers.go b/cmd/rr/http/workers.go
index b03c273f..3c3e9987 100644
--- a/cmd/rr/http/workers.go
+++ b/cmd/rr/http/workers.go
@@ -23,19 +23,15 @@ package http
import (
"errors"
tm "github.com/buger/goterm"
- "github.com/dustin/go-humanize"
- "github.com/olekukonko/tablewriter"
- "github.com/shirou/gopsutil/process"
"github.com/spf13/cobra"
rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/rr/utils"
+ "github.com/spiral/roadrunner/cmd/rr/util"
"github.com/spiral/roadrunner/service"
"github.com/spiral/roadrunner/service/http"
rrpc "github.com/spiral/roadrunner/service/rpc"
"net/rpc"
"os"
"os/signal"
- "strconv"
"syscall"
"time"
)
@@ -108,58 +104,5 @@ func showWorkers(client *rpc.Client) {
panic(err)
}
- tw := tablewriter.NewWriter(os.Stdout)
- tw.SetHeader([]string{"PID", "Status", "Execs", "Memory", "Created"})
- tw.SetColMinWidth(0, 7)
- tw.SetColMinWidth(1, 9)
- tw.SetColMinWidth(2, 7)
- tw.SetColMinWidth(3, 7)
- tw.SetColMinWidth(4, 18)
-
- for _, w := range r.Workers {
- tw.Append([]string{
- strconv.Itoa(w.Pid),
- renderStatus(w.Status),
- renderJobs(w.NumJobs),
- renderMemory(w.Pid),
- renderAlive(time.Unix(0, w.Created)),
- })
- }
-
- tw.Render()
-}
-
-func renderStatus(status string) string {
- switch status {
- case "inactive":
- return utils.Sprintf("<yellow>inactive</reset>")
- case "ready":
- return utils.Sprintf("<cyan>ready</reset>")
- case "working":
- return utils.Sprintf("<green>working</reset>")
- case "stopped":
- return utils.Sprintf("<red>stopped</reset>")
- case "errored":
- return utils.Sprintf("<red>errored</reset>")
- }
-
- return status
-}
-
-func renderJobs(number int64) string {
- return humanize.Comma(int64(number))
-}
-
-func renderAlive(t time.Time) string {
- return humanize.RelTime(t, time.Now(), "ago", "")
-}
-
-func renderMemory(pid int) string {
- p, _ := process.NewProcess(int32(pid))
- i, err := p.MemoryInfo()
- if err != nil {
- return err.Error()
- }
-
- return humanize.Bytes(i.RSS)
+ util.WorkerTable(r.Workers).Render()
}
diff --git a/cmd/rr/utils/cprint.go b/cmd/rr/util/cprint.go
index 020975ec..0985de62 100644
--- a/cmd/rr/utils/cprint.go
+++ b/cmd/rr/util/cprint.go
@@ -1,4 +1,4 @@
-package utils
+package util
import (
"fmt"
diff --git a/cmd/rr/util/list.go b/cmd/rr/util/list.go
new file mode 100644
index 00000000..4094ce44
--- /dev/null
+++ b/cmd/rr/util/list.go
@@ -0,0 +1,58 @@
+package util
+
+import (
+ rrutil "github.com/spiral/roadrunner/util"
+ "github.com/olekukonko/tablewriter"
+ "os"
+ "strconv"
+ "github.com/dustin/go-humanize"
+ "time"
+)
+
+// WorkerTable renders table with information about rr server workers.
+func WorkerTable(workers []*rrutil.State) *tablewriter.Table {
+ tw := tablewriter.NewWriter(os.Stdout)
+ tw.SetHeader([]string{"PID", "Status", "Execs", "Memory", "Created"})
+ tw.SetColMinWidth(0, 7)
+ tw.SetColMinWidth(1, 9)
+ tw.SetColMinWidth(2, 7)
+ tw.SetColMinWidth(3, 7)
+ tw.SetColMinWidth(4, 18)
+
+ for _, w := range workers {
+ tw.Append([]string{
+ strconv.Itoa(w.Pid),
+ renderStatus(w.Status),
+ renderJobs(w.NumJobs),
+ humanize.Bytes(w.MemoryUsage),
+ renderAlive(time.Unix(0, w.Created)),
+ })
+ }
+
+ return tw
+}
+
+func renderStatus(status string) string {
+ switch status {
+ case "inactive":
+ return Sprintf("<yellow>inactive</reset>")
+ case "ready":
+ return Sprintf("<cyan>ready</reset>")
+ case "working":
+ return Sprintf("<green>working</reset>")
+ case "stopped":
+ return Sprintf("<red>stopped</reset>")
+ case "errored":
+ return Sprintf("<red>errored</reset>")
+ }
+
+ return status
+}
+
+func renderJobs(number int64) string {
+ return humanize.Comma(int64(number))
+}
+
+func renderAlive(t time.Time) string {
+ return humanize.RelTime(t, time.Now(), "ago", "")
+}
diff --git a/service/http/rpc.go b/service/http/rpc.go
index 9dfe718e..08b3f262 100644
--- a/service/http/rpc.go
+++ b/service/http/rpc.go
@@ -2,6 +2,7 @@ package http
import (
"github.com/pkg/errors"
+ "github.com/spiral/roadrunner/util"
)
type rpcServer struct{ svc *Service }
@@ -9,22 +10,7 @@ type rpcServer struct{ svc *Service }
// WorkerList contains list of workers.
type WorkerList struct {
// Workers is list of workers.
- Workers []Worker `json:"workers"`
-}
-
-// Worker provides information about specific worker.
-type Worker struct {
- // Pid contains process id.
- Pid int `json:"pid"`
-
- // Status of the worker.
- Status string `json:"status"`
-
- // Number of worker executions.
- NumJobs int64 `json:"numExecs"`
-
- // Created is unix nano timestamp of worker creation time.
- Created int64 `json:"created"`
+ Workers []*util.State `json:"workers"`
}
// Reset resets underlying RR worker pool and restarts all of it's workers.
@@ -38,20 +24,11 @@ func (rpc *rpcServer) Reset(reset bool, r *string) error {
}
// Workers returns list of active workers and their stats.
-func (rpc *rpcServer) Workers(list bool, r *WorkerList) error {
+func (rpc *rpcServer) Workers(list bool, r *WorkerList) (err error) {
if rpc.svc == nil || rpc.svc.srv == nil {
return errors.New("http server is not running")
}
- for _, w := range rpc.svc.rr.Workers() {
- state := w.State()
- r.Workers = append(r.Workers, Worker{
- Pid: *w.Pid,
- Status: state.String(),
- NumJobs: state.NumExecs(),
- Created: w.Created.UnixNano(),
- })
- }
-
- return nil
+ r.Workers, err = util.ServerState(rpc.svc.rr)
+ return err
}
diff --git a/util/state.go b/util/state.go
new file mode 100644
index 00000000..3984d72d
--- /dev/null
+++ b/util/state.go
@@ -0,0 +1,62 @@
+package util
+
+import (
+ "github.com/shirou/gopsutil/process"
+ "github.com/spiral/roadrunner"
+ "errors"
+)
+
+// State provides information about specific worker.
+type State struct {
+ // Pid contains process id.
+ Pid int `json:"pid"`
+
+ // Status of the worker.
+ Status string `json:"status"`
+
+ // Number of worker executions.
+ NumJobs int64 `json:"numExecs"`
+
+ // Created is unix nano timestamp of worker creation time.
+ Created int64 `json:"created"`
+
+ // MemoryUsage holds the information about worker memory usage in bytes.
+ // Values might vary for different operating systems and based on RSS.
+ MemoryUsage uint64 `json:"memoryUsage"`
+}
+
+// WorkerState creates new worker state definition.
+func WorkerState(w *roadrunner.Worker) (*State, error) {
+ p, _ := process.NewProcess(int32(*w.Pid))
+ i, err := p.MemoryInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{
+ Pid: *w.Pid,
+ Status: w.State().String(),
+ NumJobs: w.State().NumExecs(),
+ Created: w.Created.UnixNano(),
+ MemoryUsage: i.RSS,
+ }, nil
+}
+
+// ServerState returns list of all worker states of a given rr server.
+func ServerState(rr *roadrunner.Server) ([]*State, error) {
+ if rr == nil {
+ return nil, errors.New("rr server is not running")
+ }
+
+ result := make([]*State, 0)
+ for _, w := range rr.Workers() {
+ state, err := WorkerState(w)
+ if err != nil {
+ return nil, err
+ }
+
+ result = append(result, state)
+ }
+
+ return result, nil
+}