@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorConduitLogSearchEngine
4 extends PhabricatorApplicationSearchEngine {
5
6 public function getResultTypeDescription() {
7 return pht('Conduit Logs');
8 }
9
10 public function getApplicationClassName() {
11 return PhabricatorConduitApplication::class;
12 }
13
14 public function canUseInPanelContext() {
15 return false;
16 }
17
18 public function newQuery() {
19 return new PhabricatorConduitLogQuery();
20 }
21
22 protected function buildQueryFromParameters(array $map) {
23 $query = $this->newQuery();
24
25 if ($map['callerPHIDs']) {
26 $query->withCallerPHIDs($map['callerPHIDs']);
27 }
28
29 if ($map['isBot'] !== null) {
30 $query->withIsSystemAgent($map['isBot']);
31 }
32
33 if ($map['methods']) {
34 $query->withMethods($map['methods']);
35 }
36
37 if ($map['statuses']) {
38 $query->withMethodStatuses($map['statuses']);
39 }
40
41 if ($map['epochMin'] || $map['epochMax']) {
42 $query->withEpochBetween(
43 $map['epochMin'],
44 $map['epochMax']);
45 }
46
47 return $query;
48 }
49
50 protected function buildCustomSearchFields() {
51 return array(
52 id(new PhabricatorUsersSearchField())
53 ->setKey('callerPHIDs')
54 ->setLabel(pht('Callers'))
55 ->setAliases(array('caller', 'callers'))
56 ->setDescription(pht('Find calls by specific users.')),
57 id(new PhabricatorSearchThreeStateField())
58 ->setLabel(pht('Caller Type'))
59 ->setKey('isBot')
60 ->setAliases(array('isSystemAgent'))
61 ->setOptions(
62 pht('(Show All)'),
63 pht('Show Only Bots'),
64 pht('Hide Bots'))
65 ->setDescription(
66 pht(
67 'Pass true to find only bots, or false to omit bots.')),
68 id(new PhabricatorSearchStringListField())
69 ->setKey('methods')
70 ->setLabel(pht('Methods'))
71 ->setDescription(pht('Find calls to specific methods.')),
72 id(new PhabricatorSearchCheckboxesField())
73 ->setKey('statuses')
74 ->setLabel(pht('Method Status'))
75 ->setAliases(array('status'))
76 ->setDescription(
77 pht('Find calls to stable, unstable, or deprecated methods.'))
78 ->setOptions(ConduitAPIMethod::getMethodStatusMap()),
79 id(new PhabricatorSearchDateField())
80 ->setLabel(pht('Called After'))
81 ->setKey('epochMin'),
82 id(new PhabricatorSearchDateField())
83 ->setLabel(pht('Called Before'))
84 ->setKey('epochMax'),
85 );
86 }
87
88 protected function getURI($path) {
89 return '/conduit/log/'.$path;
90 }
91
92 protected function getBuiltinQueryNames() {
93 $names = array();
94
95 $viewer = $this->requireViewer();
96 if ($viewer->isLoggedIn()) {
97 $names['viewer'] = pht('My Calls');
98 $names['viewerdeprecated'] = pht('My Deprecated Calls');
99 }
100
101 $names['all'] = pht('All Call Logs');
102 $names['deprecated'] = pht('Deprecated Call Logs');
103
104 return $names;
105 }
106
107 public function buildSavedQueryFromBuiltin($query_key) {
108 $query = $this->newSavedQuery();
109 $query->setQueryKey($query_key);
110
111 $viewer = $this->requireViewer();
112 $viewer_phid = $viewer->getPHID();
113
114 $deprecated = array(
115 ConduitAPIMethod::METHOD_STATUS_DEPRECATED,
116 );
117
118 switch ($query_key) {
119 case 'viewer':
120 return $query
121 ->setParameter('callerPHIDs', array($viewer_phid));
122 case 'viewerdeprecated':
123 return $query
124 ->setParameter('callerPHIDs', array($viewer_phid))
125 ->setParameter('statuses', $deprecated);
126 case 'deprecated':
127 return $query
128 ->setParameter('statuses', $deprecated);
129 case 'all':
130 return $query;
131 }
132
133 return parent::buildSavedQueryFromBuiltin($query_key);
134 }
135
136 protected function newExportFields() {
137 $viewer = $this->requireViewer();
138
139 return array(
140 id(new PhabricatorPHIDExportField())
141 ->setKey('callerPHID')
142 ->setLabel(pht('Caller PHID')),
143 id(new PhabricatorStringExportField())
144 ->setKey('caller')
145 ->setLabel(pht('Caller')),
146 id(new PhabricatorStringExportField())
147 ->setKey('method')
148 ->setLabel(pht('Method')),
149 id(new PhabricatorIntExportField())
150 ->setKey('duration')
151 ->setLabel(pht('Call Duration (us)')),
152 id(new PhabricatorStringExportField())
153 ->setKey('error')
154 ->setLabel(pht('Error')),
155 );
156 }
157
158 protected function newExportData(array $logs) {
159 $viewer = $this->requireViewer();
160
161 $phids = array();
162 foreach ($logs as $log) {
163 if ($log->getCallerPHID()) {
164 $phids[] = $log->getCallerPHID();
165 }
166 }
167 $handles = $viewer->loadHandles($phids);
168
169 $export = array();
170 foreach ($logs as $log) {
171 $caller_phid = $log->getCallerPHID();
172 if ($caller_phid) {
173 $caller_name = $handles[$caller_phid]->getName();
174 } else {
175 $caller_name = null;
176 }
177
178 $map = array(
179 'callerPHID' => $caller_phid,
180 'caller' => $caller_name,
181 'method' => $log->getMethod(),
182 'duration' => (int)$log->getDuration(),
183 'error' => $log->getError(),
184 );
185
186 $export[] = $map;
187 }
188
189 return $export;
190 }
191
192 /**
193 * @param array<PhabricatorConduitMethodCallLog> $logs
194 * @param PhabricatorSavedQuery $query
195 * @param array<PhabricatorObjectHandle> $handles
196 */
197 protected function renderResultList(
198 array $logs,
199 PhabricatorSavedQuery $query,
200 array $handles) {
201 assert_instances_of($logs, PhabricatorConduitMethodCallLog::class);
202 $viewer = $this->requireViewer();
203
204 $methods = id(new PhabricatorConduitMethodQuery())
205 ->setViewer($viewer)
206 ->execute();
207 $methods = mpull($methods, null, 'getAPIMethodName');
208
209 Javelin::initBehavior('phabricator-tooltips');
210
211 $viewer = $this->requireViewer();
212 $rows = array();
213 foreach ($logs as $log) {
214 $caller_phid = $log->getCallerPHID();
215
216 if ($caller_phid) {
217 $caller = $viewer->renderHandle($caller_phid);
218 } else {
219 $caller = null;
220 }
221
222 $method = idx($methods, $log->getMethod());
223 if ($method) {
224 $method_status = $method->getMethodStatus();
225 } else {
226 $method_status = null;
227 }
228
229 switch ($method_status) {
230 case ConduitAPIMethod::METHOD_STATUS_STABLE:
231 $status = null;
232 break;
233 case ConduitAPIMethod::METHOD_STATUS_UNSTABLE:
234 $status = id(new PHUIIconView())
235 ->setIcon('fa-exclamation-triangle yellow')
236 ->addSigil('has-tooltip')
237 ->setMetadata(
238 array(
239 'tip' => pht('Unstable'),
240 ));
241 break;
242 case ConduitAPIMethod::METHOD_STATUS_DEPRECATED:
243 $status = id(new PHUIIconView())
244 ->setIcon('fa-exclamation-triangle red')
245 ->addSigil('has-tooltip')
246 ->setMetadata(
247 array(
248 'tip' => pht('Deprecated'),
249 ));
250 break;
251 case ConduitAPIMethod::METHOD_STATUS_FROZEN:
252 $status = id(new PHUIIconView())
253 ->setIcon('fa-exclamation-triangle grey')
254 ->addSigil('has-tooltip')
255 ->setMetadata(
256 array(
257 'tip' => pht('Frozen'),
258 ));
259 break;
260 default:
261 $status = id(new PHUIIconView())
262 ->setIcon('fa-question-circle')
263 ->addSigil('has-tooltip')
264 ->setMetadata(
265 array(
266 'tip' => pht('Unknown ("%s")', $method_status),
267 ));
268 break;
269 }
270
271 $rows[] = array(
272 $status,
273 $log->getMethod(),
274 $caller,
275 $log->getError(),
276 pht('%s us', new PhutilNumber($log->getDuration())),
277 phabricator_datetime($log->getDateCreated(), $viewer),
278 );
279 }
280
281 $table = id(new AphrontTableView($rows))
282 ->setHeaders(
283 array(
284 null,
285 pht('Method'),
286 pht('Caller'),
287 pht('Error'),
288 pht('Duration'),
289 pht('Date'),
290 ))
291 ->setColumnClasses(
292 array(
293 null,
294 'pri',
295 null,
296 'wide right',
297 null,
298 null,
299 ));
300
301 return id(new PhabricatorApplicationSearchResultView())
302 ->setTable($table)
303 ->setNoDataString(pht('No matching calls in log.'));
304 }
305}