protected function collectGarbage() { $table = new MultimeterEvent(); $conn_w = $table->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE epoch < %d LIMIT 100', $table->getTableName(), $this->getGarbageEpoch()); return $conn_w->getAffectedRows() == 100; }
public function collectGarbage() { $ttl = phutil_units('90 days in seconds'); $table = new MultimeterEvent(); $conn_w = $table->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE epoch < %d LIMIT 100', $table->getTableName(), PhabricatorTime::getNow() - $ttl); return $conn_w->getAffectedRows() == 100; }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $group_map = $this->getColumnMap(); $group = explode('.', $request->getStr('group')); $group = array_intersect($group, array_keys($group_map)); $group = array_fuse($group); if (empty($group['type'])) { $group['type'] = 'type'; } $now = PhabricatorTime::getNow(); $ago = $now - phutil_units('24 hours in seconds'); $table = new MultimeterEvent(); $conn = $table->establishConnection('r'); $where = array(); $where[] = qsprintf($conn, 'epoch >= %d AND epoch <= %d', $ago, $now); $with = array(); foreach ($group_map as $key => $column) { // Don't let non-admins filter by viewers, this feels a little too // invasive of privacy. if ($key == 'viewer') { if (!$viewer->getIsAdmin()) { continue; } } $with[$key] = $request->getStrList($key); if ($with[$key]) { $where[] = qsprintf($conn, '%T IN (%Ls)', $column, $with[$key]); } } $where = '(' . implode(') AND (', $where) . ')'; $data = queryfx_all($conn, 'SELECT *, count(*) AS N, SUM(sampleRate * resourceCost) AS totalCost, SUM(sampleRate * resourceCost) / SUM(sampleRate) AS averageCost FROM %T WHERE %Q GROUP BY %Q ORDER BY totalCost DESC, MAX(id) DESC LIMIT 100', $table->getTableName(), $where, implode(', ', array_select_keys($group_map, $group))); $this->loadDimensions($data); $phids = array(); foreach ($data as $row) { $viewer_name = $this->getViewerDimension($row['eventViewerID'])->getName(); $viewer_phid = $this->getEventViewerPHID($viewer_name); if ($viewer_phid) { $phids[] = $viewer_phid; } } $handles = $viewer->loadHandles($phids); $rows = array(); foreach ($data as $row) { if ($row['N'] == 1) { $events_col = $row['id']; } else { $events_col = $this->renderGroupingLink($group, 'id', pht('%s Event(s)', new PhutilNumber($row['N']))); } if (isset($group['request'])) { $request_col = $row['requestKey']; if (!$with['request']) { $request_col = $this->renderSelectionLink('request', $row['requestKey'], $request_col); } } else { $request_col = $this->renderGroupingLink($group, 'request'); } if (isset($group['viewer'])) { if ($viewer->getIsAdmin()) { $viewer_col = $this->getViewerDimension($row['eventViewerID'])->getName(); $viewer_phid = $this->getEventViewerPHID($viewer_col); if ($viewer_phid) { $viewer_col = $handles[$viewer_phid]->getName(); } if (!$with['viewer']) { $viewer_col = $this->renderSelectionLink('viewer', $row['eventViewerID'], $viewer_col); } } else { $viewer_col = phutil_tag('em', array(), pht('(Masked)')); } } else { $viewer_col = $this->renderGroupingLink($group, 'viewer'); } if (isset($group['context'])) { $context_col = $this->getContextDimension($row['eventContextID'])->getName(); if (!$with['context']) { $context_col = $this->renderSelectionLink('context', $row['eventContextID'], $context_col); } } else { $context_col = $this->renderGroupingLink($group, 'context'); } if (isset($group['host'])) { $host_col = $this->getHostDimension($row['eventHostID'])->getName(); if (!$with['host']) { $host_col = $this->renderSelectionLink('host', $row['eventHostID'], $host_col); } } else { $host_col = $this->renderGroupingLink($group, 'host'); } if (isset($group['label'])) { $label_col = $this->getLabelDimension($row['eventLabelID'])->getName(); if (!$with['label']) { $label_col = $this->renderSelectionLink('label', $row['eventLabelID'], $label_col); } } else { $label_col = $this->renderGroupingLink($group, 'label'); } if ($with['type']) { $type_col = MultimeterEvent::getEventTypeName($row['eventType']); } else { $type_col = $this->renderSelectionLink('type', $row['eventType'], MultimeterEvent::getEventTypeName($row['eventType'])); } $rows[] = array($events_col, $request_col, $viewer_col, $context_col, $host_col, $type_col, $label_col, MultimeterEvent::formatResourceCost($viewer, $row['eventType'], $row['averageCost']), MultimeterEvent::formatResourceCost($viewer, $row['eventType'], $row['totalCost']), $row['N'] == 1 ? $row['sampleRate'] : '-', phabricator_datetime($row['epoch'], $viewer)); } $table = id(new AphrontTableView($rows))->setHeaders(array(pht('ID'), pht('Request'), pht('Viewer'), pht('Context'), pht('Host'), pht('Type'), pht('Label'), pht('Avg'), pht('Cost'), pht('Rate'), pht('Epoch')))->setColumnClasses(array(null, null, null, null, null, null, 'wide', 'n', 'n', 'n', null)); $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Samples'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setTable($table); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Samples'), $this->getGroupURI(array(), true)); $crumbs->setBorder(true); $crumb_map = array('host' => pht('By Host'), 'context' => pht('By Context'), 'viewer' => pht('By Viewer'), 'request' => pht('By Request'), 'label' => pht('By Label'), 'id' => pht('By ID')); $parts = array(); foreach ($group as $item) { if ($item == 'type') { continue; } $parts[$item] = $item; $crumbs->addTextCrumb(idx($crumb_map, $item, $item), $this->getGroupURI($parts, true)); } $header = id(new PHUIHeaderView())->setHeader(pht('Samples (%s - %s)', phabricator_datetime($ago, $viewer), phabricator_datetime($now, $viewer)))->setHeaderIcon('fa-motorcycle'); $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($box); return $this->newPage()->setTitle(pht('Samples'))->setCrumbs($crumbs)->appendChild($view); }