-
-
Notifications
You must be signed in to change notification settings - Fork 6
Enrich JSON, extend sampling intervals, show refresh hint #23
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 0.1.4 | ||
| 0.1.5 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,6 +27,8 @@ type processesMsg []processes.Info | |||||||||||||||||
|
|
||||||||||||||||||
| type pingMsg time.Duration | ||||||||||||||||||
|
|
||||||||||||||||||
| type refreshHintClearMsg struct{} | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using an empty struct for
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| const ( | ||||||||||||||||||
| slopeWindow = 6 | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
@@ -87,6 +89,7 @@ type Model struct { | |||||||||||||||||
| downPulse float64 | ||||||||||||||||||
| upPulse float64 | ||||||||||||||||||
| pingLatency time.Duration | ||||||||||||||||||
| refreshHint string | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||
| err error | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -166,6 +169,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |||||||||||||||||
| m.upPulse = math.Max(0, m.upPulse-0.08) | ||||||||||||||||||
| return m, tick() | ||||||||||||||||||
|
|
||||||||||||||||||
| case refreshHintClearMsg: | ||||||||||||||||||
| m.refreshHint = "" | ||||||||||||||||||
| return m, nil | ||||||||||||||||||
|
Comment on lines
+172
to
+174
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only clear the refresh hint if the message's timestamp matches the most recently set hint's timestamp. This prevents older scheduled clear messages from clearing newer hints.
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| case processesMsg: | ||||||||||||||||||
| m.procs = msg | ||||||||||||||||||
| return m, nil | ||||||||||||||||||
|
|
@@ -312,12 +319,12 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { | |||||||||||||||||
| m.bitsMode = !m.bitsMode | ||||||||||||||||||
|
|
||||||||||||||||||
| case key.Matches(msg, m.keys.Faster): | ||||||||||||||||||
| m.adjustRefreshInterval(true) | ||||||||||||||||||
| return m, waitForSample(m.smp.Out) | ||||||||||||||||||
| cmd := m.adjustRefreshInterval(true) | ||||||||||||||||||
| return m, tea.Batch(waitForSample(m.smp.Out), cmd) | ||||||||||||||||||
|
|
||||||||||||||||||
| case key.Matches(msg, m.keys.Slower): | ||||||||||||||||||
| m.adjustRefreshInterval(false) | ||||||||||||||||||
| return m, waitForSample(m.smp.Out) | ||||||||||||||||||
| cmd := m.adjustRefreshInterval(false) | ||||||||||||||||||
| return m, tea.Batch(waitForSample(m.smp.Out), cmd) | ||||||||||||||||||
|
Comment on lines
321
to
+327
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Goroutine Leak on Refresh Interval AdjustmentEvery time the refresh interval is adjusted (via However, the previous
This results in a goroutine leak every time the user adjusts the refresh rate (or cycles the interface). Recommended Fix:
|
||||||||||||||||||
|
|
||||||||||||||||||
| case key.Matches(msg, m.keys.Themes): | ||||||||||||||||||
| m.showThemes = true | ||||||||||||||||||
|
|
@@ -339,14 +346,17 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { | |||||||||||||||||
| return m, nil | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| func (m *Model) adjustRefreshInterval(faster bool) { | ||||||||||||||||||
| func (m *Model) adjustRefreshInterval(faster bool) tea.Cmd { | ||||||||||||||||||
| intervals := []time.Duration{ | ||||||||||||||||||
| 50 * time.Millisecond, | ||||||||||||||||||
| 100 * time.Millisecond, | ||||||||||||||||||
| 250 * time.Millisecond, | ||||||||||||||||||
| 500 * time.Millisecond, | ||||||||||||||||||
| 1 * time.Second, | ||||||||||||||||||
| 2 * time.Second, | ||||||||||||||||||
| 3 * time.Second, | ||||||||||||||||||
| 5 * time.Second, | ||||||||||||||||||
| 10 * time.Second, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| idx := -1 | ||||||||||||||||||
|
|
@@ -379,7 +389,11 @@ func (m *Model) adjustRefreshInterval(faster bool) { | |||||||||||||||||
| col := collector.New(m.ifaceName) | ||||||||||||||||||
| m.smp = sampler.New(col, m.refreshInterval) | ||||||||||||||||||
| go m.smp.Run(ctx) | ||||||||||||||||||
|
|
||||||||||||||||||
| m.refreshHint = fmt.Sprintf("every %s", m.refreshInterval) | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Sampler restart on refresh interval changes may leak goroutines or duplicate sampling without cancelling the previous one. Adjusting the refresh interval currently creates a new sampler with a new background context but never cancels the old one. If the interval is changed multiple times, you can end up with several samplers running in parallel and leaked goroutines. Please ensure the previous sampler/context is cleanly stopped before starting a new one, or update the existing sampler’s configuration instead of recreating it. |
||||||||||||||||||
| return tea.Tick(2*time.Second, func(t time.Time) tea.Msg { return refreshHintClearMsg{} }) | ||||||||||||||||||
|
Comment on lines
+393
to
+394
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Capture the current timestamp when setting the refresh hint, and pass it to the scheduled now := time.Now()
m.refreshHint = fmt.Sprintf("every %s", m.refreshInterval)
m.refreshHintTime = now
return tea.Tick(2*time.Second, func(t time.Time) tea.Msg { return refreshHintClearMsg(now) }) |
||||||||||||||||||
| } | ||||||||||||||||||
| return nil | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| func (m Model) View() string { | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the sample's actual timestamp (
s.At) instead oftime.Now()to ensure the JSON output reflects the exact time the network metrics were captured.