1use crate::editor::git_memory::GitJob;
8use crate::editor::{ClipboardResult, ShellResult};
9use serde_json::json;
10use strop_trace::{record_with, EventKind};
11
12#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
15pub struct NativePath(#[serde(with = "strop_core::path_serde")] pub std::path::PathBuf);
16
17pub fn rejected(service: &'static str, reason: &str) {
18 record_with(
19 EventKind::JobRejected,
20 || json!({"service":service,"reason":reason}),
21 );
22}
23fn outcome<T>(value: &strop_core::worker::Outcome<T>) -> serde_json::Value {
24 use strop_core::worker::Outcome;
25 match value {
26 Outcome::Success(_) => json!({"kind":"success"}),
27 Outcome::Failed { failure, partial } => {
28 json!({"kind":"failed","failure":failure,"partial":partial.is_some()})
29 }
30 Outcome::Cancelled(reason) => json!({"kind":"cancelled","reason":reason}),
31 }
32}
33
34fn completion<K: serde::Serialize, T>(
35 service: &str,
36 result: &str,
37 value: &strop_core::worker::Completion<K, T>,
38) -> serde_json::Value {
39 json!({"service":service,"result":result,"ticket":value.ticket,"outcome":outcome(&value.outcome)})
40}
41
42pub fn git(job: &GitJob) {
43 record_with(EventKind::JobFinished, || match job {
44 GitJob::Context(value) => completion("git", "context", value),
45 GitJob::Hunks(value) => completion("git", "hunks", value),
46 GitJob::Mutation(value) => completion("git", "mutation", value),
47 GitJob::Log(value) => completion("git", "log", value),
48 GitJob::Gutter(value) => completion("git", "gutter", value),
49 GitJob::Card(value) => completion("git", "blame_card", value),
50 GitJob::Dive(value) => completion("git", "dive", value),
51 });
52}
53
54pub fn io(event: &crate::editor::io::IoEvent) {
55 use crate::editor::io::IoEvent;
56 record_with(EventKind::JobFinished, || match event {
57 IoEvent::Open(value) => completion("io", "open", value),
58 IoEvent::Save(value) => completion("io", "save", value),
59 IoEvent::Native(value) => completion("io", "native", value),
60 IoEvent::Review(value) => completion("search", "review", value),
61 IoEvent::Remote(event) => {
62 use crate::editor::remote::RemoteEvent;
63 match event {
64 RemoteEvent::Tick(ticket) => {
65 json!({"service":"remote","result":"follow_tick","ticket":ticket})
66 }
67 RemoteEvent::Timer(value) => completion("remote", "follow_clock", value),
68 RemoteEvent::Read(value) => completion("remote", "follow_read", value),
69 RemoteEvent::Control(value) => completion("remote", "control", value),
70 RemoteEvent::Filter(value) => completion("remote", "directory_filter", value),
71 RemoteEvent::Choices(value) => completion("remote", "destinations", value),
72 RemoteEvent::Write(value) => {
73 let mut record = completion("remote", "write", value);
74 if let strop_core::worker::Outcome::Success(
75 crate::editor::remote::save::RemoteWriteResult::Refused(error),
76 ) = &value.outcome
77 {
78 record["outcome"] = outcome(&strop_core::worker::Outcome::<()>::failed(
79 strop_core::worker::FailureKind::Io,
80 error.to_string(),
81 ));
82 }
83 record
84 }
85 RemoteEvent::DestinationWritten(value) => {
86 completion("remote", "destination_write", value)
87 }
88 }
89 }
90 IoEvent::Session {
91 request,
92 outcome: value,
93 } => json!({"service":"io","result":"session","request":request,"outcome":outcome(value)}),
94 });
95}
96
97pub fn shell(result: &ShellResult) {
98 record_with(EventKind::JobFinished, || {
99 let key = match &result.ticket.key {
100 crate::editor::ShellKey::Display {
101 origin, revision, ..
102 } => json!({
103 "kind":"display","document":super::snapshot::document_id(*origin),
104 "revision":revision,
105 }),
106 crate::editor::ShellKey::Pipe {
107 document,
108 revision,
109 start,
110 end,
111 } => json!({
112 "kind":"pipe","document":super::snapshot::document_id(*document),
113 "revision":revision,"start_byte":start,"end_byte":end,
114 }),
115 };
116 let outcome = match &result.outcome {
117 strop_core::worker::Outcome::Success(output) => json!({
118 "stdout_bytes":output.stdout.len(),"stderr_bytes":output.stderr.len(),
119 }),
120 strop_core::worker::Outcome::Failed { failure, .. } => {
121 json!({"error": failure.message})
122 }
123 _ => json!({"cancelled": true}),
124 };
125 json!({"service":"shell","request":result.ticket.request.get(),
126 "key":key,"outcome":outcome})
127 });
128}
129
130pub fn clipboard(result: &ClipboardResult) {
131 record_with(EventKind::JobFinished, || {
132 let outcome = match &result.outcome {
133 strop_core::worker::Outcome::Success(text) => json!({"bytes": text.len()}),
134 strop_core::worker::Outcome::Failed { failure, .. } => {
135 json!({"error": failure.message})
136 }
137 _ => json!({"cancelled": true}),
138 };
139 json!({"service":"clipboard","request":result.ticket.request.get(),
140 "document":super::snapshot::document_id(result.ticket.key.document),
141 "outcome":outcome})
142 });
143}
144
145pub fn lsp(event: &strop_lsp::LspEvent) {
146 use strop_lsp::LspEvent;
147 record_with(EventKind::JobFinished, || {
148 if strop_trace::capture_content() {
149 return json!({"service":"lsp", "event":event});
150 }
151 match event {
152 LspEvent::Ready { server, name } => {
153 json!({"service":"lsp","result":"ready","server":server,"name":name})
154 }
155 LspEvent::Failed { server, name, hint } => {
156 json!({"service":"lsp","result":"failed","server":server,"name":name,"hint":hint})
158 }
159 LspEvent::ServerMessage { server, name, text } => {
160 json!({"service":"lsp","result":"message","server":server,"name":name,"bytes":text.len()})
161 }
162 LspEvent::Diagnostics { context, diags, .. } => json!({
163 "service":"lsp","result":"diagnostics","context":context,"count":diags.len(),
164 }),
165 LspEvent::Edits { context, edits } => json!({
166 "service":"lsp","result":"edits","context":context,"count":edits.len(),
167 }),
168 LspEvent::WorkspaceEdits { context, edits } => json!({
169 "service":"lsp","result":"workspace_edits","context":context,"targets":edits.len(),
170 }),
171 LspEvent::Symbols { context, symbols } => json!({
172 "service":"lsp","result":"symbols","context":context,"count":symbols.len(),
173 }),
174 LspEvent::ActionList { context, actions } => json!({
175 "service":"lsp","result":"code_actions","context":context,"count":actions.len(),
176 }),
177 LspEvent::HoverText { context, text } => json!({
178 "service":"lsp","result":"hover","context":context,"bytes":text.len(),
179 }),
180 LspEvent::Note { context, text } => json!({
181 "service":"lsp","result":"note","context":context,"bytes":text.len(),
182 }),
183 LspEvent::GotoLocation { context, .. } => json!({
184 "service":"lsp","result":"goto","context":context,
185 }),
186 LspEvent::Locations {
187 context,
188 kind,
189 items,
190 } => json!({
191 "service":"lsp","result":kind.label(),"context":context,"count":items.len(),
192 }),
193 }
194 });
195}
196
197pub fn picker(event: &crate::editor::picker::PickerEvent) {
198 use strop_picker::PickerMsg;
199 record_with(EventKind::JobFinished, || {
200 let outcome = match &event.msg {
201 PickerMsg::Items(items) => json!({"result":"items","count":items.len()}),
202 PickerMsg::Warning(warning) => json!({"result":"warning","bytes":warning.len()}),
203 PickerMsg::QueryError(diagnostic) => {
204 json!({"result":"query-error","range":diagnostic.range})
205 }
206 PickerMsg::Finished(outcome) => match outcome {
207 strop_core::worker::Outcome::Success(()) => json!({"result":"finished"}),
208 strop_core::worker::Outcome::Failed { failure, .. } => {
209 json!({"result":"error","error":failure.message})
210 }
211 _ => json!({"result":"cancelled"}),
212 },
213 };
214 json!({"service":"picker","request":event.ticket.request.get(),
215 "outcome":outcome})
216 });
217}