zsh cleanup and stats (#247)

* better osrelease parsing (ignore garbage at end of string)

* add defaultshelltype to telemetry input

* track reinit errors by shelltype to see if zsh integration is working
This commit is contained in:
Mike Sawka 2024-01-23 17:19:03 -08:00 committed by GitHub
parent 6bcd37c28e
commit b762df179f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 69 additions and 53 deletions

View File

@ -873,10 +873,7 @@ func main() {
}
log.Printf("PCLOUD_ENDPOINT=%s\n", pcloud.GetEndpoint())
err = sstore.UpdateCurrentActivity(context.Background(), sstore.ActivityUpdate{NumConns: remote.NumRemotes()}) // set at least one record into activity
if err != nil {
log.Printf("[error] updating activity: %v\n", err)
}
sstore.UpdateActivityWrap(context.Background(), sstore.ActivityUpdate{NumConns: remote.NumRemotes()}, "numconns") // set at least one record into activity
installSignalHandlers()
go telemetryLoop()
go stdinReadWatch()

View File

@ -673,11 +673,7 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
}
evalDepth := getEvalDepth(ctx)
if pk.Interactive && evalDepth == 0 {
err := sstore.UpdateCurrentActivity(ctx, sstore.ActivityUpdate{NumCommands: 1})
if err != nil {
log.Printf("[error] incrementing activity numcommands: %v\n", err)
// fall through (non-fatal error)
}
sstore.UpdateActivityWrap(ctx, sstore.ActivityUpdate{NumCommands: 1}, "numcommands")
}
if evalDepth > MaxEvalDepth {
return nil, fmt.Errorf("alias/history expansion max-depth exceeded")
@ -2753,10 +2749,7 @@ func validateRemoteColor(color string, typeStr string) error {
func SessionOpenSharedCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
activity := sstore.ActivityUpdate{ClickShared: 1}
err := sstore.UpdateCurrentActivity(ctx, activity)
if err != nil {
log.Printf("error updating click-shared: %v\n", err)
}
sstore.UpdateActivityWrap(ctx, activity, "click-shared")
return nil, fmt.Errorf("shared sessions are not available in this version of prompt (stay tuned)")
}
@ -3213,10 +3206,7 @@ func HistoryCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
}
show := !resolveBool(pk.Kwargs["noshow"], false)
if show {
err = sstore.UpdateCurrentActivity(ctx, sstore.ActivityUpdate{HistoryView: 1})
if err != nil {
log.Printf("error updating current activity (history): %v\n", err)
}
sstore.UpdateActivityWrap(ctx, sstore.ActivityUpdate{HistoryView: 1}, "history")
}
update := &sstore.ModelUpdate{}
update.History = &sstore.HistoryInfoType{
@ -3453,10 +3443,7 @@ func BookmarksShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
if err != nil {
return nil, fmt.Errorf("cannot retrieve bookmarks: %v", err)
}
err = sstore.UpdateCurrentActivity(ctx, sstore.ActivityUpdate{BookmarksView: 1})
if err != nil {
log.Printf("error updating current activity (bookmarks): %v\n", err)
}
sstore.UpdateActivityWrap(ctx, sstore.ActivityUpdate{BookmarksView: 1}, "bookmarks")
update := &sstore.ModelUpdate{
MainView: sstore.MainViewBookmarks,
Bookmarks: bms,
@ -4504,7 +4491,7 @@ func ClientShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "db-version", dbVersion))
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "client-version", clientVersion))
buf.WriteString(fmt.Sprintf(" %-15s %s %s\n", "server-version", scbase.WaveVersion, scbase.BuildTime))
buf.WriteString(fmt.Sprintf(" %-15s %s (%s)\n", "arch", scbase.ClientArch(), scbase.MacOSRelease()))
buf.WriteString(fmt.Sprintf(" %-15s %s (%s)\n", "arch", scbase.ClientArch(), scbase.UnameKernelRelease()))
update := &sstore.ModelUpdate{
Info: &sstore.InfoMsgType{
InfoTitle: fmt.Sprintf("client info"),

View File

@ -18,6 +18,7 @@ import (
"sync"
"time"
"github.com/wavetermdev/waveterm/waveshell/pkg/shellapi"
"github.com/wavetermdev/waveterm/wavesrv/pkg/dbutil"
"github.com/wavetermdev/waveterm/wavesrv/pkg/rtnstate"
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbase"
@ -164,7 +165,8 @@ func SendTelemetry(ctx context.Context, force bool) error {
}
log.Printf("[pcloud] sending telemetry data\n")
dayStr := sstore.GetCurDayStr()
input := TelemetryInputType{UserId: clientData.UserId, ClientId: clientData.ClientId, CurDay: dayStr, Activity: activity}
defaultShellType := shellapi.DetectLocalShellType()
input := TelemetryInputType{UserId: clientData.UserId, ClientId: clientData.ClientId, CurDay: dayStr, DefaultShell: defaultShellType, Activity: activity}
req, err := makeAnonPostReq(ctx, TelemetryUrl, input)
if err != nil {
return err

View File

@ -22,6 +22,7 @@ type TelemetryInputType struct {
UserId string `json:"userid"`
ClientId string `json:"clientid"`
CurDay string `json:"curday"`
DefaultShell string `json:"defaultshell"`
Activity []*sstore.ActivityType `json:"activity"`
}

View File

@ -1103,6 +1103,16 @@ func getStateVarsFromInitPk(initPk *packet.InitPacketType) map[string]string {
return rtn
}
func makeReinitErrorUpdate(shellType string) sstore.ActivityUpdate {
rtn := sstore.ActivityUpdate{}
if shellType == packet.ShellType_bash {
rtn.ReinitBashErrors = 1
} else if shellType == packet.ShellType_zsh {
rtn.ReinitZshErrors = 1
}
return rtn
}
func (msh *MShellProc) ReInit(ctx context.Context, shellType string) (*packet.ShellStatePacketType, error) {
if !msh.IsConnected() {
return nil, fmt.Errorf("cannot reinit, remote is not connected")
@ -1122,12 +1132,14 @@ func (msh *MShellProc) ReInit(ctx context.Context, shellType string) (*packet.Sh
}
ssPk, ok := resp.(*packet.ShellStatePacketType)
if !ok {
sstore.UpdateActivityWrap(ctx, makeReinitErrorUpdate(shellType), "reiniterror")
if respPk, ok := resp.(*packet.ResponsePacketType); ok && respPk.Error != "" {
return nil, fmt.Errorf("error reinitializing remote: %s", respPk.Error)
}
return nil, fmt.Errorf("invalid reinit response (not an shellstate packet): %T", resp)
}
if ssPk.State == nil {
sstore.UpdateActivityWrap(ctx, makeReinitErrorUpdate(shellType), "reiniterror")
return nil, fmt.Errorf("invalid reinit response shellstate packet does not contain remote state")
}
// TODO: maybe we don't need to save statebase here. should be possible to save it on demand

View File

@ -351,11 +351,11 @@ func ClientArch() string {
return fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
}
var releaseRegex = regexp.MustCompile(`^\d+\.\d+\.\d+$`)
var releaseRegex = regexp.MustCompile(`^(\d+\.\d+\.\d+)`)
var osReleaseOnce = &sync.Once{}
var osRelease string
func macOSRelease() string {
func unameKernelRelease() string {
ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
defer cancelFn()
out, err := exec.CommandContext(ctx, "uname", "-r").CombinedOutput()
@ -364,16 +364,17 @@ func macOSRelease() string {
return "-"
}
releaseStr := strings.TrimSpace(string(out))
if !releaseRegex.MatchString(releaseStr) {
m := releaseRegex.FindStringSubmatch(releaseStr)
if m == nil || len(m) < 2 {
log.Printf("invalid uname -r output: [%s]\n", releaseStr)
return "-"
}
return releaseStr
return m[1]
}
func MacOSRelease() string {
func UnameKernelRelease() string {
osReleaseOnce.Do(func() {
osRelease = macOSRelease()
osRelease = unameKernelRelease()
})
return osRelease
}

View File

@ -2157,6 +2157,15 @@ func GetCurDayStr() string {
return dayStr
}
// Wraps UpdateCurrentActivity, but ignores errors
func UpdateActivityWrap(ctx context.Context, update ActivityUpdate, debugStr string) {
err := UpdateCurrentActivity(ctx, update)
if err != nil {
// ignore error, just log, since this is not critical
log.Printf("error updating current activity (%s): %v\n", debugStr, err)
}
}
func UpdateCurrentActivity(ctx context.Context, update ActivityUpdate) error {
now := time.Now()
dayStr := GetCurDayStr()
@ -2171,7 +2180,7 @@ func UpdateCurrentActivity(ctx context.Context, update ActivityUpdate) error {
if len(tzName) > MaxTzNameLen {
tzName = tzName[0:MaxTzNameLen]
}
tx.Exec(query, dayStr, tdata, tzName, tzOffset, scbase.WaveVersion, scbase.ClientArch(), scbase.BuildTime, scbase.MacOSRelease())
tx.Exec(query, dayStr, tdata, tzName, tzOffset, scbase.WaveVersion, scbase.ClientArch(), scbase.BuildTime, scbase.UnameKernelRelease())
}
tdata.NumCommands += update.NumCommands
tdata.FgMinutes += update.FgMinutes
@ -2180,6 +2189,8 @@ func UpdateCurrentActivity(ctx context.Context, update ActivityUpdate) error {
tdata.ClickShared += update.ClickShared
tdata.HistoryView += update.HistoryView
tdata.BookmarksView += update.BookmarksView
tdata.ReinitBashErrors += update.ReinitBashErrors
tdata.ReinitZshErrors += update.ReinitZshErrors
if update.NumConns > 0 {
tdata.NumConns = update.NumConns
}

View File

@ -235,6 +235,8 @@ type ActivityUpdate struct {
BookmarksView int
NumConns int
WebShareLimit int
ReinitBashErrors int
ReinitZshErrors int
BuildTime string
}
@ -247,6 +249,7 @@ type ActivityType struct {
ClientVersion string `json:"clientversion"`
ClientArch string `json:"clientarch"`
BuildTime string `json:"buildtime"`
DefaultShell string `json:"defaultshell"`
OSRelease string `json:"osrelease"`
}
@ -260,6 +263,8 @@ type TelemetryData struct {
BookmarksView int `json:"bookmarksview,omitempty"`
NumConns int `json:"numconns"`
WebShareLimit int `json:"websharelimit,omitempty"`
ReinitBashErrors int `json:"reinitbasherrors,omitempty"`
ReinitZshErrors int `json:"reinitzsherrors,omitempty"`
}
func (tdata TelemetryData) Value() (driver.Value, error) {