diff --git a/app/widget_maker.go b/app/widget_maker.go index ad0d343f..7e8d93b1 100644 --- a/app/widget_maker.go +++ b/app/widget_maker.go @@ -163,7 +163,7 @@ func MakeWidget( widget = nbascore.NewWidget(app, pages, settings) case "newrelic": settings := newrelic.NewSettingsFromYAML(moduleName, moduleConfig, config) - widget = newrelic.NewWidget(app, settings) + widget = newrelic.NewWidget(app, pages, settings) case "opsgenie": settings := opsgenie.NewSettingsFromYAML(moduleName, moduleConfig, config) widget = opsgenie.NewWidget(app, settings) diff --git a/modules/newrelic/display.go b/modules/newrelic/display.go new file mode 100644 index 00000000..db7113fc --- /dev/null +++ b/modules/newrelic/display.go @@ -0,0 +1,74 @@ +package newrelic + +import ( + "fmt" + + "github.com/wtfutil/wtf/wtf" + nr "github.com/yfronto/newrelic" +) + +func (widget *Widget) display() { + client := widget.currentData() + if client == nil { + widget.Redraw(widget.CommonSettings.Title, " NewRelic data unavailable ", false) + return + } + app, appErr := client.Application() + deploys, depErr := client.Deployments() + + appName := "error" + if appErr == nil { + appName = app.Name + } + + var content string + title := fmt.Sprintf("%s - [green]%s[white]", widget.CommonSettings.Title, appName) + wrap := false + if depErr != nil { + wrap = true + content = depErr.Error() + } else { + content = widget.contentFrom(deploys) + } + + widget.Redraw(title, content, wrap) +} + +func (widget *Widget) contentFrom(deploys []nr.ApplicationDeployment) string { + str := fmt.Sprintf( + " %s\n", + "[red]Latest Deploys[white]", + ) + + revisions := []string{} + + for _, deploy := range deploys { + if (deploy.Revision != "") && wtf.Exclude(revisions, deploy.Revision) { + lineColor := "white" + if wtf.IsToday(deploy.Timestamp) { + lineColor = "lightblue" + } + + revLen := 8 + if revLen > len(deploy.Revision) { + revLen = len(deploy.Revision) + } + + str += fmt.Sprintf( + " [green]%s[%s] %s %-.16s[white]\n", + deploy.Revision[0:revLen], + lineColor, + deploy.Timestamp.Format("Jan 02 15:04 MST"), + wtf.NameFromEmail(deploy.User), + ) + + revisions = append(revisions, deploy.Revision) + + if len(revisions) == widget.settings.deployCount { + break + } + } + } + + return str +} diff --git a/modules/newrelic/keyboard.go b/modules/newrelic/keyboard.go new file mode 100644 index 00000000..d572a4e1 --- /dev/null +++ b/modules/newrelic/keyboard.go @@ -0,0 +1,9 @@ +package newrelic + +import "github.com/gdamore/tcell" + +func (widget *Widget) initializeKeyboardControls() { + widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help window") + widget.SetKeyboardKey(tcell.KeyLeft, widget.PrevSource, "Select previous application") + widget.SetKeyboardKey(tcell.KeyRight, widget.NextSource, "Select next application") +} diff --git a/modules/newrelic/settings.go b/modules/newrelic/settings.go index 0b940667..3444a421 100644 --- a/modules/newrelic/settings.go +++ b/modules/newrelic/settings.go @@ -12,9 +12,9 @@ const defaultTitle = "NewRelic" type Settings struct { common *cfg.Common - apiKey string `help:"Your New Relic API token."` - applicationID int `help:"The integer ID of the New Relic application you wish to report on."` - deployCount int `help:"The number of past deploys to display on screen." optional:"true"` + apiKey string `help:"Your New Relic API token."` + deployCount int `help:"The number of past deploys to display on screen." optional:"true"` + applicationIDs []interface{} `help:"The integer ID of the New Relic application you wish to report on."` } func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { @@ -22,9 +22,9 @@ func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *co settings := Settings{ common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig), - apiKey: ymlConfig.UString("apiKey", ymlConfig.UString("apikey", os.Getenv("WTF_NEW_RELIC_API_KEY"))), - applicationID: ymlConfig.UInt("applicationID"), - deployCount: ymlConfig.UInt("deployCount", 5), + apiKey: ymlConfig.UString("apiKey", os.Getenv("WTF_NEW_RELIC_API_KEY")), + deployCount: ymlConfig.UInt("deployCount", 5), + applicationIDs: ymlConfig.UList("applicationIDs"), } return &settings diff --git a/modules/newrelic/widget.go b/modules/newrelic/widget.go index 4c757168..9688aef7 100644 --- a/modules/newrelic/widget.go +++ b/modules/newrelic/widget.go @@ -1,7 +1,7 @@ package newrelic import ( - "fmt" + "sort" "github.com/rivo/tview" "github.com/wtfutil/wtf/utils" @@ -10,20 +10,38 @@ import ( ) type Widget struct { - view.TextWidget + wtf.KeyboardWidget + wtf.MultiSourceWidget + wtf.TextWidget + + Clients []*Client - client *Client settings *Settings } -func NewWidget(app *tview.Application, settings *Settings) *Widget { +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { widget := Widget{ - TextWidget: view.NewTextWidget(app, settings.common, false), + KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common), + MultiSourceWidget: wtf.NewMultiSourceWidget(settings.common, "applicationID", "applicationIDs"), + TextWidget: wtf.NewTextWidget(app, settings.common, true), settings: settings, } - widget.client = NewClient(widget.settings.apiKey, widget.settings.applicationID) + widget.initializeKeyboardControls() + widget.View.SetInputCapture(widget.InputCapture) + + for _, id := range wtf.ToInts(widget.settings.applicationIDs) { + widget.Clients = append(widget.Clients, NewClient(widget.settings.apiKey, id)) + } + + sort.Slice(widget.Clients, func(i, j int) bool { + return widget.Clients[i].applicationId < widget.Clients[j].applicationId + }) + + widget.SetDisplayFunction(widget.display) + + widget.KeyboardWidget.SetView(widget.View) return &widget } @@ -90,3 +108,21 @@ func (widget *Widget) content() (string, string, bool) { return title, content, wrap } + +func (widget *Widget) HelpText() string { + return widget.KeyboardWidget.HelpText() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) currentData() *Client { + if len(widget.Clients) == 0 { + return nil + } + + if widget.Idx < 0 || widget.Idx >= len(widget.Clients) { + return nil + } + + return widget.Clients[widget.Idx] +}