@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
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow Phabricator to write an access log using PhutilDeferredLog

Summary: Provide a configurable access log.

Test Plan:
Got a sensible-looking log including logged-in, logged-out, conduit, 404, etc:

[Mon, 23 Apr 2012 20:08:12 -0700] 32599 orbital - epriestley DifferentialCommentPreviewController - /differential/comment/preview/42/ http://local.aphront.com:8080/D42 200 65406
[Mon, 23 Apr 2012 20:08:12 -0700] 32881 orbital - epriestley DifferentialChangesetViewController - /differential/changeset/ http://local.aphront.com:8080/D42 200 72669
[Mon, 23 Apr 2012 20:08:39 -0700] 32882 orbital 127.0.0.1 epriestley DifferentialRevisionListController - /differential/ http://local.aphront.com:8080/D42 200 106444
[Mon, 23 Apr 2012 20:08:54 -0700] 32867 orbital 127.0.0.1 epriestley DifferentialRevisionListController - /differential/ http://local.aphront.com:8080/differential/ 200 112229
[Mon, 23 Apr 2012 20:09:05 -0700] 32530 orbital 127.0.0.1 epriestley PhabricatorDirectoryMainController - / http://local.aphront.com:8080/differential/ 200 141350
[Mon, 23 Apr 2012 20:09:10 -0700] 32598 orbital 127.0.0.1 epriestley PhabricatorDirectoryCategoryViewController - /directory/6/ http://local.aphront.com:8080/ 200 43474
[Mon, 23 Apr 2012 20:09:12 -0700] 32880 orbital 127.0.0.1 epriestley PhabricatorConduitConsoleController - /conduit/ http://local.aphront.com:8080/directory/6/ 200 139340
[Mon, 23 Apr 2012 20:09:15 -0700] 32868 orbital 127.0.0.1 epriestley PhabricatorConduitAPIController arcanist.projectinfo /api/arcanist.projectinfo http://local.aphront.com:8080/conduit/ 200 128774
[Mon, 23 Apr 2012 20:10:04 -0700] 32599 orbital 127.0.0.1 epriestley Phabricator404Controller - /asdbmabdmbsm - 404 38782
[Mon, 23 Apr 2012 20:10:04 -0700] 32881 orbital 127.0.0.1 - CelerityResourceController - /res/c9a43002/rsrc/css/aphront/request-failure-view.css http://local.aphront.com:8080/asdbmabdmbsm 200 25160
[Mon, 23 Apr 2012 20:10:57 -0700] 32882 orbital 127.0.0.1 epriestley PhabricatorLogoutController - /logout/ http://local.aphront.com:8080/asdbmabdmbsm 200 40810
[Mon, 23 Apr 2012 20:10:57 -0700] 32867 orbital 127.0.0.1 - PhabricatorLoginController - /login/ http://local.aphront.com:8080/asdbmabdmbsm 200 42526
[Mon, 23 Apr 2012 20:10:59 -0700] 32919 orbital 127.0.0.1 - PhabricatorLoginController - /login/ http://local.aphront.com:8080/asdbmabdmbsm 200 49052
[Mon, 23 Apr 2012 20:10:59 -0700] 32880 orbital 127.0.0.1 - CelerityResourceController - /res/c80156c4/rsrc/js/application/core/behavior-dark-console.js http://local.aphront.com:8080/login/ 200 33166
[Mon, 23 Apr 2012 20:10:59 -0700] 32868 orbital 127.0.0.1 - CelerityResourceController - /res/4965d970/rsrc/css/aphront/dark-console.css http://local.aphront.com:8080/login/ 200 38078
[Mon, 23 Apr 2012 20:10:59 -0700] 32599 orbital 127.0.0.1 - CelerityResourceController - /res/pkg/8a5de8a3/javelin.pkg.js http://local.aphront.com:8080/login/ 200 40534
[Mon, 23 Apr 2012 20:10:59 -0700] 32882 orbital 127.0.0.1 - CelerityResourceController - /res/pkg/9c4e265b/core.pkg.css http://local.aphront.com:8080/login/ 200 41262
[Mon, 23 Apr 2012 20:10:59 -0700] 32881 orbital 127.0.0.1 - CelerityResourceController - /res/pkg/0c96375e/core.pkg.js http://local.aphront.com:8080/login/ 200 43720
[Mon, 23 Apr 2012 20:10:59 -0700] 32921 orbital 127.0.0.1 - CelerityResourceController - /res/caa86a45/rsrc/js/javelin/core/init.js http://local.aphront.com:8080/login/ 200 47566
[Mon, 23 Apr 2012 20:10:59 -0700] 32867 orbital 127.0.0.1 - CelerityResourceController - /res/f46289e9/rsrc/js/application/core/behavior-error-log.js http://local.aphront.com:8080/login/ 200 29328
[Mon, 23 Apr 2012 20:10:59 -0700] 32919 orbital 127.0.0.1 - CelerityResourceController - /res/7e62ff40/rsrc/image/phabricator_logo.png http://local.aphront.com:8080/login/ 200 25583
[Mon, 23 Apr 2012 20:10:59 -0700] 32880 orbital 127.0.0.1 - CelerityResourceController - /res/8c6200d3/rsrc/image/sprite.png http://local.aphront.com:8080/login/ 200 29829
[Mon, 23 Apr 2012 20:11:01 -0700] 32868 orbital 127.0.0.1 - PhabricatorOAuthLoginController - /oauth/facebook/login/ http://local.aphront.com:8080/login/ 200 855931
[Mon, 23 Apr 2012 20:11:02 -0700] 32882 orbital 127.0.0.1 epriestley789 PhabricatorLoginValidateController - /login/validate/ http://local.aphront.com:8080/login/ 200 29793
[Mon, 23 Apr 2012 20:11:02 -0700] 32881 orbital 127.0.0.1 epriestley789 PhabricatorDirectoryMainController - / http://local.aphront.com:8080/login/ 200 91638

Reviewers: jungejason, btrahan, vrana

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D2310

+180
+39
conf/default.conf.php
··· 81 81 'policy.allow-public' => false, 82 82 83 83 84 + // -- Logging --------------------------------------------------------------- // 85 + 86 + // To enable the Phabricator access log, specify a path here. The Phabricator 87 + // access log can provide more detailed information about Phabricator access 88 + // than normal HTTP access logs (for instance, it can show logged-in users, 89 + // controllers, and other application data). If not set, no log will be 90 + // written. 91 + // 92 + // Make sure the PHP process can write to the log! 93 + 'log.access.path' => null, 94 + 95 + // Format for the access log. If not set, the default format will be used: 96 + // 97 + // "[%D]\t%h\t%u\t%M\t%C\t%m\t%U\t%c\t%T" 98 + // 99 + // Available variables are: 100 + // 101 + // - %c The HTTP response code. 102 + // - %C The controller which handled the request. 103 + // - %D The request date. 104 + // - %e Epoch timestamp. 105 + // - %h The webserver's host name. 106 + // - %p The PID of the server process. 107 + // - %R The HTTP referrer. 108 + // - %r The remote IP. 109 + // - %T The request duration, in microseconds. 110 + // - %U The request path. 111 + // - %u The logged-in user, if one is logged in. 112 + // - %M The HTTP method. 113 + // - %m For conduit, the Conduit method which was invoked. 114 + // 115 + // If a variable isn't available (for example, %m appears in the file format 116 + // but the request is not a Conduit request), it will be rendered as "-". 117 + // 118 + // Note that the default format is subject to change in the future, so if you 119 + // rely on the log's format, specify it explicitly. 120 + 'log.access.format' => null, 121 + 122 + 84 123 // -- DarkConsole ----------------------------------------------------------- // 85 124 86 125 // DarkConsole is a administrative debugging/profiling tool built into
+1
src/__phutil_library_map__.php
··· 501 501 'MetaMTAConstants' => 'applications/metamta/constants/base', 502 502 'MetaMTANotificationType' => 'applications/metamta/constants/notificationtype', 503 503 'Phabricator404Controller' => 'applications/base/controller/404', 504 + 'PhabricatorAccessLog' => 'infrastructure/accesslog', 504 505 'PhabricatorAphlictTestPageController' => 'applications/notifications/controller/test', 505 506 'PhabricatorAuditActionConstants' => 'applications/audit/constants/action', 506 507 'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment',
+14
src/applications/conduit/controller/api/PhabricatorConduitAPIController.php
··· 125 125 } 126 126 } 127 127 128 + $access_log = PhabricatorAccessLog::getLog(); 129 + if ($access_log) { 130 + $conduit_username = '-'; 131 + $conduit_user = $api_request->getUser(); 132 + if ($conduit_user && $conduit_user->getPHID()) { 133 + $conduit_username = $conduit_user->getUsername(); 134 + } 135 + $access_log->setData( 136 + array( 137 + 'u' => $conduit_username, 138 + 'm' => $method, 139 + )); 140 + } 141 + 128 142 if ($method_handler->shouldAllowUnguardedWrites()) { 129 143 $allow_unguarded_writes = true; 130 144 }
+1
src/applications/conduit/controller/api/__init__.php
··· 17 17 phutil_require_module('phabricator', 'applications/oauthserver/server'); 18 18 phutil_require_module('phabricator', 'applications/oauthserver/storage/accesstoken'); 19 19 phutil_require_module('phabricator', 'applications/people/storage/user'); 20 + phutil_require_module('phabricator', 'infrastructure/accesslog'); 20 21 phutil_require_module('phabricator', 'storage/queryfx'); 21 22 phutil_require_module('phabricator', 'view/control/table'); 22 23 phutil_require_module('phabricator', 'view/layout/panel');
+57
src/infrastructure/accesslog/PhabricatorAccessLog.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2012 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + final class PhabricatorAccessLog { 20 + 21 + static $log; 22 + 23 + public static function init() { 24 + // NOTE: This currently has no effect, but some day we may reuse PHP 25 + // interpreters to run multiple requests. If we do, it has the effect of 26 + // throwing away the old log. 27 + self::$log = null; 28 + } 29 + 30 + public static function getLog() { 31 + if (!self::$log) { 32 + $path = PhabricatorEnv::getEnvConfig('log.access.path'); 33 + $format = PhabricatorEnv::getEnvConfig('log.access.format'); 34 + $format = nonempty( 35 + $format, 36 + "[%D]\t%p\t%h\t%r\t%u\t%C\t%m\t%U\t%R\t%c\t%T"); 37 + 38 + if (!$path) { 39 + return null; 40 + } 41 + 42 + $log = new PhutilDeferredLog($path, $format); 43 + $log->setData( 44 + array( 45 + 'D' => date('r'), 46 + 'h' => php_uname('n'), 47 + 'p' => getmypid(), 48 + 'e' => time(), 49 + )); 50 + 51 + self::$log = $log; 52 + } 53 + 54 + return self::$log; 55 + } 56 + 57 + }
+15
src/infrastructure/accesslog/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'infrastructure/env'); 10 + 11 + phutil_require_module('phutil', 'filesystem/deferredlog'); 12 + phutil_require_module('phutil', 'utils'); 13 + 14 + 15 + phutil_require_source('PhabricatorAccessLog.php');
+53
webroot/index.php
··· 71 71 phutil_require_module('phabricator', 'infrastructure/env'); 72 72 PhabricatorEnv::setEnvConfig($conf); 73 73 74 + // This is the earliest we can get away with this, we need env config first. 75 + PhabricatorAccessLog::init(); 76 + $access_log = PhabricatorAccessLog::getLog(); 77 + if ($access_log) { 78 + $access_log->setData( 79 + array( 80 + 'R' => idx($_SERVER, 'HTTP_REFERER', '-'), 81 + 'r' => idx($_SERVER, 'REMOTE_ADDR', '-'), 82 + 'M' => idx($_SERVER, 'REQUEST_METHOD', '-'), 83 + )); 84 + } 85 + 74 86 phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); 75 87 DarkConsoleXHProfPluginAPI::hookProfiler(); 76 88 ··· 129 141 130 142 $application->setRequest($request); 131 143 list($controller, $uri_data) = $application->buildController(); 144 + 145 + if ($access_log) { 146 + $access_log->setData( 147 + array( 148 + 'U' => (string)$request->getRequestURI()->getPath(), 149 + 'C' => get_class($controller), 150 + )); 151 + } 152 + 132 153 try { 133 154 $response = $controller->willBeginExecution(); 155 + 156 + if ($access_log) { 157 + if ($request->getUser() && $request->getUser()->getPHID()) { 158 + $access_log->setData( 159 + array( 160 + 'u' => $request->getUser()->getUserName(), 161 + )); 162 + } 163 + } 164 + 134 165 if (!$response) { 135 166 $controller->willProcessRequest($uri_data); 136 167 $response = $controller->processRequest(); ··· 148 179 $response_string = $response->buildResponseString(); 149 180 } catch (Exception $ex) { 150 181 $write_guard->dispose(); 182 + if ($access_log) { 183 + $access_log->write(); 184 + } 151 185 phabricator_fatal('[Rendering Exception] '.$ex->getMessage()); 152 186 } 153 187 ··· 185 219 } 186 220 187 221 $sink->writeData($response_string); 222 + 223 + if ($access_log) { 224 + $access_log->setData( 225 + array( 226 + 'c' => $response->getHTTPResponseCode(), 227 + 'T' => (int)(1000000 * (microtime(true) - $__start__)), 228 + )); 229 + $access_log->write(); 230 + } 188 231 189 232 /** 190 233 * @group aphront ··· 304 347 } 305 348 306 349 function phabricator_fatal($msg) { 350 + $log = PhabricatorAccessLog::getLog(); 351 + if ($log) { 352 + $log->setData( 353 + array( 354 + 'c' => 500, 355 + )); 356 + $log->write(); 357 + } 358 + 307 359 header( 308 360 'Content-Type: text/plain; charset=utf-8', 309 361 $replace = true, ··· 314 366 315 367 exit(1); 316 368 } 369 +