test(daemon): cover pane move observability
- commit
- d6fec558e8d96b4d346b084c134ce3135147bb60
- author
- brice · · 2026-08-20 14:16 UTC
- parent
- 80df2be
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +145 -36
M internal/usecase/daemon/move_observability_test.go +136 -34
| @@ -11,10 +11,26 @@ import ( | |||
| 11 | 11 | "github.com/bnema/vev/internal/domain" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| 14 | - | func TestMoveTabLogsCommitAndSourceAttachmentTermination(t *testing.T) { | |
| 15 | - | var logs bytes.Buffer | |
| 14 | + | type moveObservabilityFixture struct { | |
| 15 | + | daemon *Daemon | |
| 16 | + | source *session | |
| 17 | + | sourceTab *tab | |
| 18 | + | sourcePane *pane | |
| 19 | + | destination *session | |
| 20 | + | destinationTab *tab | |
| 21 | + | logs *bytes.Buffer | |
| 22 | + | } | |
| 23 | + | ||
| 24 | + | func newMoveObservabilityFixture(t *testing.T) moveObservabilityFixture { | |
| 25 | + | t.Helper() | |
| 26 | + | logs := &bytes.Buffer{} | |
| 16 | 27 | d, source, _, _ := newManualSessionWithPTYs(t, newQuietPTY()) | |
| 17 | - | d.log = slog.New(slog.NewJSONHandler(&logs, nil)) | |
| 28 | + | d.log = slog.New(slog.NewJSONHandler(logs, nil)) | |
| 29 | + | ||
| 30 | + | sourceTab := source.tabs[0] | |
| 31 | + | sourceTab.stableID = "source-tab" | |
| 32 | + | sourcePane := sourceTab.focusedPane() | |
| 33 | + | sourcePane.stableID = "source-pane" | |
| 18 | 34 | ||
| 19 | 35 | destinationCtx, destinationCancel := context.WithCancel(d.serveCtx) | |
| 20 | 36 | t.Cleanup(destinationCancel) | |
| @@ -31,40 +47,126 @@ func TestMoveTabLogsCommitAndSourceAttachmentTermination(t *testing.T) { | |||
| 31 | 47 | d.sessions[destination.id] = destination | |
| 32 | 48 | d.mu.Unlock() | |
| 33 | 49 | ||
| 34 | - | sourceTab := source.tabs[0] | |
| 35 | - | sourceTab.stableID = "source-tab" | |
| 36 | - | require.NoError(t, d.moveTab(moveTabRequest{ | |
| 37 | - | Source: moveSessionLocator{ID: source.id, Incarnation: source.incarnation}, | |
| 38 | - | SourceTabID: domain.TabStableID(sourceTab.stableID), | |
| 39 | - | Destination: moveSessionLocator{ID: destination.id, Incarnation: destination.incarnation}, | |
| 40 | - | })) | |
| 41 | - | d.waitNotifies() | |
| 50 | + | return moveObservabilityFixture{ | |
| 51 | + | daemon: d, source: source, sourceTab: sourceTab, sourcePane: sourcePane, | |
| 52 | + | destination: destination, destinationTab: destinationTab, logs: logs, | |
| 53 | + | } | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | func TestMoveLogsCommitAndSourceAttachmentTermination(t *testing.T) { | |
| 57 | + | tests := []struct { | |
| 58 | + | name string | |
| 59 | + | operation string | |
| 60 | + | move func(moveObservabilityFixture) error | |
| 61 | + | assertLog func(*testing.T, string) | |
| 62 | + | }{ | |
| 63 | + | { | |
| 64 | + | name: "tab", | |
| 65 | + | operation: "tab", | |
| 66 | + | move: func(f moveObservabilityFixture) error { | |
| 67 | + | return f.daemon.moveTab(moveTabRequest{ | |
| 68 | + | Source: moveSessionLocator{ID: f.source.id, Incarnation: f.source.incarnation}, | |
| 69 | + | SourceTabID: domain.TabStableID(f.sourceTab.stableID), | |
| 70 | + | Destination: moveSessionLocator{ID: f.destination.id, Incarnation: f.destination.incarnation}, | |
| 71 | + | }) | |
| 72 | + | }, | |
| 73 | + | assertLog: func(t *testing.T, output string) { | |
| 74 | + | t.Helper() | |
| 75 | + | require.Contains(t, output, `"msg":"tab move requested"`) | |
| 76 | + | }, | |
| 77 | + | }, | |
| 78 | + | { | |
| 79 | + | name: "pane", | |
| 80 | + | operation: "pane", | |
| 81 | + | move: func(f moveObservabilityFixture) error { | |
| 82 | + | return f.daemon.movePane(movePaneRequest{ | |
| 83 | + | Source: moveSessionLocator{ID: f.source.id, Incarnation: f.source.incarnation}, | |
| 84 | + | SourceTabID: domain.TabStableID(f.sourceTab.stableID), | |
| 85 | + | SourcePaneID: domain.PaneStableID(f.sourcePane.stableID), | |
| 86 | + | Destination: moveSessionLocator{ID: f.destination.id, Incarnation: f.destination.incarnation}, | |
| 87 | + | DestinationTabID: domain.TabStableID(f.destinationTab.stableID), | |
| 88 | + | }) | |
| 89 | + | }, | |
| 90 | + | assertLog: func(t *testing.T, output string) { | |
| 91 | + | t.Helper() | |
| 92 | + | require.Contains(t, output, `"msg":"pane move requested"`) | |
| 93 | + | require.Contains(t, output, `"source_pane_id":"source-pane","destination_tab_id":"destination-tab"`) | |
| 94 | + | }, | |
| 95 | + | }, | |
| 96 | + | } | |
| 97 | + | ||
| 98 | + | for _, tt := range tests { | |
| 99 | + | t.Run(tt.name, func(t *testing.T) { | |
| 100 | + | fixture := newMoveObservabilityFixture(t) | |
| 101 | + | require.NoError(t, tt.move(fixture)) | |
| 102 | + | fixture.daemon.waitNotifies() | |
| 42 | 103 | ||
| 43 | - | output := logs.String() | |
| 44 | - | require.Contains(t, output, `"msg":"tab move requested"`) | |
| 45 | - | require.Contains(t, output, `"msg":"move committed"`) | |
| 46 | - | require.Contains(t, output, `"operation":"tab"`) | |
| 47 | - | require.Contains(t, output, `"source_retired":true`) | |
| 48 | - | require.Contains(t, output, `"msg":"move detaching source attachments"`) | |
| 49 | - | require.Contains(t, output, `"reason":"session-killed"`) | |
| 50 | - | require.Contains(t, output, `"msg":"client detached"`) | |
| 51 | - | require.Contains(t, output, `"reason":1`) | |
| 104 | + | output := fixture.logs.String() | |
| 105 | + | tt.assertLog(t, output) | |
| 106 | + | require.Contains(t, output, `"msg":"move committed"`) | |
| 107 | + | require.Contains(t, output, `"operation":"`+tt.operation+`"`) | |
| 108 | + | require.Contains(t, output, `"source_retired":true`) | |
| 109 | + | require.Contains(t, output, `"msg":"move detaching source attachments"`) | |
| 110 | + | require.Contains(t, output, `"reason":"session-killed"`) | |
| 111 | + | require.Contains(t, output, `"msg":"client detached"`) | |
| 112 | + | require.Contains(t, output, `"reason":1`) | |
| 113 | + | }) | |
| 114 | + | } | |
| 52 | 115 | } | |
| 53 | 116 | ||
| 54 | - | func TestMoveTabLogsNormalizedRejection(t *testing.T) { | |
| 55 | - | var logs bytes.Buffer | |
| 56 | - | d := New(nil, stubClock{}, slog.New(slog.NewJSONHandler(&logs, nil))) | |
| 117 | + | func TestMoveLogsNormalizedRejection(t *testing.T) { | |
| 118 | + | tests := []struct { | |
| 119 | + | name string | |
| 120 | + | operation string | |
| 121 | + | move func(*Daemon) error | |
| 122 | + | fields []string | |
| 123 | + | }{ | |
| 124 | + | { | |
| 125 | + | name: "tab", | |
| 126 | + | operation: "tab", | |
| 127 | + | move: func(d *Daemon) error { | |
| 128 | + | return d.moveTab(moveTabRequest{ | |
| 129 | + | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | |
| 130 | + | SourceTabID: "tab", | |
| 131 | + | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | |
| 132 | + | }) | |
| 133 | + | }, | |
| 134 | + | fields: []string{ | |
| 135 | + | `"source_session_id":"missing"`, | |
| 136 | + | `"destination_session_id":"also-missing"`, | |
| 137 | + | }, | |
| 138 | + | }, | |
| 139 | + | { | |
| 140 | + | name: "pane", | |
| 141 | + | operation: "pane", | |
| 142 | + | move: func(d *Daemon) error { | |
| 143 | + | return d.movePane(movePaneRequest{ | |
| 144 | + | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | |
| 145 | + | SourceTabID: "source-tab", | |
| 146 | + | SourcePaneID: "source-pane", | |
| 147 | + | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | |
| 148 | + | DestinationTabID: "destination-tab", | |
| 149 | + | }) | |
| 150 | + | }, | |
| 151 | + | fields: []string{ | |
| 152 | + | `"source_pane_id":"source-pane"`, | |
| 153 | + | `"destination_tab_id":"destination-tab"`, | |
| 154 | + | }, | |
| 155 | + | }, | |
| 156 | + | } | |
| 57 | 157 | ||
| 58 | - | err := d.moveTab(moveTabRequest{ | |
| 59 | - | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | |
| 60 | - | SourceTabID: "tab", | |
| 61 | - | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | |
| 62 | - | }) | |
| 158 | + | for _, tt := range tests { | |
| 159 | + | t.Run(tt.name, func(t *testing.T) { | |
| 160 | + | var logs bytes.Buffer | |
| 161 | + | d := New(nil, stubClock{}, slog.New(slog.NewJSONHandler(&logs, nil))) | |
| 63 | 162 | ||
| 64 | - | require.ErrorIs(t, err, errMovePaneInvalid) | |
| 65 | - | output := logs.String() | |
| 66 | - | require.Contains(t, output, `"msg":"tab move requested"`) | |
| 67 | - | require.Contains(t, output, `"msg":"tab move rejected"`) | |
| 68 | - | require.Contains(t, output, `"source_session_id":"missing"`) | |
| 69 | - | require.Contains(t, output, `"destination_session_id":"also-missing"`) | |
| 163 | + | require.ErrorIs(t, tt.move(d), errMovePaneInvalid) | |
| 164 | + | output := logs.String() | |
| 165 | + | require.Contains(t, output, `"msg":"`+tt.operation+` move requested"`) | |
| 166 | + | require.Contains(t, output, `"msg":"`+tt.operation+` move rejected"`) | |
| 167 | + | for _, field := range tt.fields { | |
| 168 | + | require.Contains(t, output, field) | |
| 169 | + | } | |
| 170 | + | }) | |
| 171 | + | } | |
| 70 | 172 | } | |
| @@ -11,10 +11,26 @@ import ( | |||||
| 11 | "github.com/bnema/vev/internal/domain" | 11 | "github.com/bnema/vev/internal/domain" | ||
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
| 14 | - | func TestMoveTabLogsCommitAndSourceAttachmentTermination(t *testing.T) { | 14 | + | type moveObservabilityFixture struct { |
| 15 | - | var logs bytes.Buffer | 15 | + | daemon *Daemon |
| 16 | + | source *session | |||
| 17 | + | sourceTab *tab | |||
| 18 | + | sourcePane *pane | |||
| 19 | + | destination *session | |||
| 20 | + | destinationTab *tab | |||
| 21 | + | logs *bytes.Buffer | |||
| 22 | + | } | |||
| 23 | + | ||||
| 24 | + | func newMoveObservabilityFixture(t *testing.T) moveObservabilityFixture { | |||
| 25 | + | t.Helper() | |||
| 26 | + | logs := &bytes.Buffer{} | |||
| 16 | d, source, _, _ := newManualSessionWithPTYs(t, newQuietPTY()) | 27 | d, source, _, _ := newManualSessionWithPTYs(t, newQuietPTY()) | ||
| 17 | - | d.log = slog.New(slog.NewJSONHandler(&logs, nil)) | 28 | + | d.log = slog.New(slog.NewJSONHandler(logs, nil)) |
| 29 | + | ||||
| 30 | + | sourceTab := source.tabs[0] | |||
| 31 | + | sourceTab.stableID = "source-tab" | |||
| 32 | + | sourcePane := sourceTab.focusedPane() | |||
| 33 | + | sourcePane.stableID = "source-pane" | |||
| 18 | 34 | ||||
| 19 | destinationCtx, destinationCancel := context.WithCancel(d.serveCtx) | 35 | destinationCtx, destinationCancel := context.WithCancel(d.serveCtx) | ||
| 20 | t.Cleanup(destinationCancel) | 36 | t.Cleanup(destinationCancel) | ||
| @@ -31,40 +47,126 @@ func TestMoveTabLogsCommitAndSourceAttachmentTermination(t *testing.T) { | |||||
| 31 | d.sessions[destination.id] = destination | 47 | d.sessions[destination.id] = destination | ||
| 32 | d.mu.Unlock() | 48 | d.mu.Unlock() | ||
| 33 | 49 | ||||
| 34 | - | sourceTab := source.tabs[0] | 50 | + | return moveObservabilityFixture{ |
| 35 | - | sourceTab.stableID = "source-tab" | 51 | + | daemon: d, source: source, sourceTab: sourceTab, sourcePane: sourcePane, |
| 36 | - | require.NoError(t, d.moveTab(moveTabRequest{ | 52 | + | destination: destination, destinationTab: destinationTab, logs: logs, |
| 37 | - | Source: moveSessionLocator{ID: source.id, Incarnation: source.incarnation}, | 53 | + | } |
| 38 | - | SourceTabID: domain.TabStableID(sourceTab.stableID), | 54 | + | } |
| 39 | - | Destination: moveSessionLocator{ID: destination.id, Incarnation: destination.incarnation}, | 55 | + | |
| 40 | - | })) | 56 | + | func TestMoveLogsCommitAndSourceAttachmentTermination(t *testing.T) { |
| 41 | - | d.waitNotifies() | 57 | + | tests := []struct { |
| 58 | + | name string | |||
| 59 | + | operation string | |||
| 60 | + | move func(moveObservabilityFixture) error | |||
| 61 | + | assertLog func(*testing.T, string) | |||
| 62 | + | }{ | |||
| 63 | + | { | |||
| 64 | + | name: "tab", | |||
| 65 | + | operation: "tab", | |||
| 66 | + | move: func(f moveObservabilityFixture) error { | |||
| 67 | + | return f.daemon.moveTab(moveTabRequest{ | |||
| 68 | + | Source: moveSessionLocator{ID: f.source.id, Incarnation: f.source.incarnation}, | |||
| 69 | + | SourceTabID: domain.TabStableID(f.sourceTab.stableID), | |||
| 70 | + | Destination: moveSessionLocator{ID: f.destination.id, Incarnation: f.destination.incarnation}, | |||
| 71 | + | }) | |||
| 72 | + | }, | |||
| 73 | + | assertLog: func(t *testing.T, output string) { | |||
| 74 | + | t.Helper() | |||
| 75 | + | require.Contains(t, output, `"msg":"tab move requested"`) | |||
| 76 | + | }, | |||
| 77 | + | }, | |||
| 78 | + | { | |||
| 79 | + | name: "pane", | |||
| 80 | + | operation: "pane", | |||
| 81 | + | move: func(f moveObservabilityFixture) error { | |||
| 82 | + | return f.daemon.movePane(movePaneRequest{ | |||
| 83 | + | Source: moveSessionLocator{ID: f.source.id, Incarnation: f.source.incarnation}, | |||
| 84 | + | SourceTabID: domain.TabStableID(f.sourceTab.stableID), | |||
| 85 | + | SourcePaneID: domain.PaneStableID(f.sourcePane.stableID), | |||
| 86 | + | Destination: moveSessionLocator{ID: f.destination.id, Incarnation: f.destination.incarnation}, | |||
| 87 | + | DestinationTabID: domain.TabStableID(f.destinationTab.stableID), | |||
| 88 | + | }) | |||
| 89 | + | }, | |||
| 90 | + | assertLog: func(t *testing.T, output string) { | |||
| 91 | + | t.Helper() | |||
| 92 | + | require.Contains(t, output, `"msg":"pane move requested"`) | |||
| 93 | + | require.Contains(t, output, `"source_pane_id":"source-pane","destination_tab_id":"destination-tab"`) | |||
| 94 | + | }, | |||
| 95 | + | }, | |||
| 96 | + | } | |||
| 97 | + | ||||
| 98 | + | for _, tt := range tests { | |||
| 99 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 100 | + | fixture := newMoveObservabilityFixture(t) | |||
| 101 | + | require.NoError(t, tt.move(fixture)) | |||
| 102 | + | fixture.daemon.waitNotifies() | |||
| 42 | 103 | ||||
| 43 | - | output := logs.String() | 104 | + | output := fixture.logs.String() |
| 44 | - | require.Contains(t, output, `"msg":"tab move requested"`) | 105 | + | tt.assertLog(t, output) |
| 45 | - | require.Contains(t, output, `"msg":"move committed"`) | 106 | + | require.Contains(t, output, `"msg":"move committed"`) |
| 46 | - | require.Contains(t, output, `"operation":"tab"`) | 107 | + | require.Contains(t, output, `"operation":"`+tt.operation+`"`) |
| 47 | - | require.Contains(t, output, `"source_retired":true`) | 108 | + | require.Contains(t, output, `"source_retired":true`) |
| 48 | - | require.Contains(t, output, `"msg":"move detaching source attachments"`) | 109 | + | require.Contains(t, output, `"msg":"move detaching source attachments"`) |
| 49 | - | require.Contains(t, output, `"reason":"session-killed"`) | 110 | + | require.Contains(t, output, `"reason":"session-killed"`) |
| 50 | - | require.Contains(t, output, `"msg":"client detached"`) | 111 | + | require.Contains(t, output, `"msg":"client detached"`) |
| 51 | - | require.Contains(t, output, `"reason":1`) | 112 | + | require.Contains(t, output, `"reason":1`) |
| 113 | + | }) | |||
| 114 | + | } | |||
| 52 | } | 115 | } | ||
| 53 | 116 | ||||
| 54 | - | func TestMoveTabLogsNormalizedRejection(t *testing.T) { | 117 | + | func TestMoveLogsNormalizedRejection(t *testing.T) { |
| 55 | - | var logs bytes.Buffer | 118 | + | tests := []struct { |
| 56 | - | d := New(nil, stubClock{}, slog.New(slog.NewJSONHandler(&logs, nil))) | 119 | + | name string |
| 120 | + | operation string | |||
| 121 | + | move func(*Daemon) error | |||
| 122 | + | fields []string | |||
| 123 | + | }{ | |||
| 124 | + | { | |||
| 125 | + | name: "tab", | |||
| 126 | + | operation: "tab", | |||
| 127 | + | move: func(d *Daemon) error { | |||
| 128 | + | return d.moveTab(moveTabRequest{ | |||
| 129 | + | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | |||
| 130 | + | SourceTabID: "tab", | |||
| 131 | + | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | |||
| 132 | + | }) | |||
| 133 | + | }, | |||
| 134 | + | fields: []string{ | |||
| 135 | + | `"source_session_id":"missing"`, | |||
| 136 | + | `"destination_session_id":"also-missing"`, | |||
| 137 | + | }, | |||
| 138 | + | }, | |||
| 139 | + | { | |||
| 140 | + | name: "pane", | |||
| 141 | + | operation: "pane", | |||
| 142 | + | move: func(d *Daemon) error { | |||
| 143 | + | return d.movePane(movePaneRequest{ | |||
| 144 | + | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | |||
| 145 | + | SourceTabID: "source-tab", | |||
| 146 | + | SourcePaneID: "source-pane", | |||
| 147 | + | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | |||
| 148 | + | DestinationTabID: "destination-tab", | |||
| 149 | + | }) | |||
| 150 | + | }, | |||
| 151 | + | fields: []string{ | |||
| 152 | + | `"source_pane_id":"source-pane"`, | |||
| 153 | + | `"destination_tab_id":"destination-tab"`, | |||
| 154 | + | }, | |||
| 155 | + | }, | |||
| 156 | + | } | |||
| 57 | 157 | ||||
| 58 | - | err := d.moveTab(moveTabRequest{ | 158 | + | for _, tt := range tests { |
| 59 | - | Source: moveSessionLocator{ID: "missing", Incarnation: domain.IncarnationID{1}}, | 159 | + | t.Run(tt.name, func(t *testing.T) { |
| 60 | - | SourceTabID: "tab", | 160 | + | var logs bytes.Buffer |
| 61 | - | Destination: moveSessionLocator{ID: "also-missing", Incarnation: domain.IncarnationID{2}}, | 161 | + | d := New(nil, stubClock{}, slog.New(slog.NewJSONHandler(&logs, nil))) |
| 62 | - | }) | |||
| 63 | 162 | ||||
| 64 | - | require.ErrorIs(t, err, errMovePaneInvalid) | 163 | + | require.ErrorIs(t, tt.move(d), errMovePaneInvalid) |
| 65 | - | output := logs.String() | 164 | + | output := logs.String() |
| 66 | - | require.Contains(t, output, `"msg":"tab move requested"`) | 165 | + | require.Contains(t, output, `"msg":"`+tt.operation+` move requested"`) |
| 67 | - | require.Contains(t, output, `"msg":"tab move rejected"`) | 166 | + | require.Contains(t, output, `"msg":"`+tt.operation+` move rejected"`) |
| 68 | - | require.Contains(t, output, `"source_session_id":"missing"`) | 167 | + | for _, field := range tt.fields { |
| 69 | - | require.Contains(t, output, `"destination_session_id":"also-missing"`) | 168 | + | require.Contains(t, output, field) |
| 169 | + | } | |||
| 170 | + | }) | |||
| 171 | + | } | |||
| 70 | } | 172 | } | ||
M internal/usecase/daemon/move_pane_postcommit.go +9 -2
| @@ -80,7 +80,7 @@ func (p movePanePostcommitPlan) execute(d *Daemon) { | |||
| 80 | 80 | } | |
| 81 | 81 | p.unlockDispatch() | |
| 82 | 82 | p.reservation.Release() | |
| 83 | - | d.log.Info("move committed", | |
| 83 | + | attrs := []any{ | |
| 84 | 84 | "operation", p.operation, | |
| 85 | 85 | "source_session", p.source.name, | |
| 86 | 86 | "source_session_id", p.source.id, | |
| @@ -88,7 +88,14 @@ func (p movePanePostcommitPlan) execute(d *Daemon) { | |||
| 88 | 88 | "destination_session", p.destination.name, | |
| 89 | 89 | "destination_session_id", p.destination.id, | |
| 90 | 90 | "source_retired", p.sourceEmpty, | |
| 91 | - | ) | |
| 91 | + | } | |
| 92 | + | if p.operation == "pane" { | |
| 93 | + | attrs = append(attrs, | |
| 94 | + | "source_pane_id", p.movedPane.stableID, | |
| 95 | + | "destination_tab_id", p.destinationTab.stableID, | |
| 96 | + | ) | |
| 97 | + | } | |
| 98 | + | d.log.Info("move committed", attrs...) | |
| 92 | 99 | ||
| 93 | 100 | // Repair attachment-local stable targets after shared topology publication | |
| 94 | 101 | // and after the move dispatch locks have been released. | |
| @@ -80,7 +80,7 @@ func (p movePanePostcommitPlan) execute(d *Daemon) { | |||||
| 80 | } | 80 | } | ||
| 81 | p.unlockDispatch() | 81 | p.unlockDispatch() | ||
| 82 | p.reservation.Release() | 82 | p.reservation.Release() | ||
| 83 | - | d.log.Info("move committed", | 83 | + | attrs := []any{ |
| 84 | "operation", p.operation, | 84 | "operation", p.operation, | ||
| 85 | "source_session", p.source.name, | 85 | "source_session", p.source.name, | ||
| 86 | "source_session_id", p.source.id, | 86 | "source_session_id", p.source.id, | ||
| @@ -88,7 +88,14 @@ func (p movePanePostcommitPlan) execute(d *Daemon) { | |||||
| 88 | "destination_session", p.destination.name, | 88 | "destination_session", p.destination.name, | ||
| 89 | "destination_session_id", p.destination.id, | 89 | "destination_session_id", p.destination.id, | ||
| 90 | "source_retired", p.sourceEmpty, | 90 | "source_retired", p.sourceEmpty, | ||
| 91 | - | ) | 91 | + | } |
| 92 | + | if p.operation == "pane" { | |||
| 93 | + | attrs = append(attrs, | |||
| 94 | + | "source_pane_id", p.movedPane.stableID, | |||
| 95 | + | "destination_tab_id", p.destinationTab.stableID, | |||
| 96 | + | ) | |||
| 97 | + | } | |||
| 98 | + | d.log.Info("move committed", attrs...) | |||
| 92 | 99 | ||||
| 93 | // Repair attachment-local stable targets after shared topology publication | 100 | // Repair attachment-local stable targets after shared topology publication | ||
| 94 | // and after the move dispatch locks have been released. | 101 | // and after the move dispatch locks have been released. | ||