Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v24.0.0beta1
@@ -75,8 +75,13 @@ class Application extends App implements IBootstrap { | |||
); | |||
}); | |||
$container->registerService(ILDAPWrapper::class, function () { | |||
return new LDAP(); | |||
$container->registerService(ILDAPWrapper::class, function (IAppContainer $appContainer) { | |||
/** @var IServerContainer $server */ | |||
$server = $appContainer->get(IServerContainer::class); | |||
return new LDAP( | |||
$server->getConfig()->getSystemValueString('ldap_log_file') | |||
); | |||
}); | |||
} | |||
@@ -317,7 +317,7 @@ class Sync extends TimedJob { | |||
if (isset($argument['ldapWrapper'])) { | |||
$this->ldap = $argument['ldapWrapper']; | |||
} else { | |||
$this->ldap = new LDAP(); | |||
$this->ldap = new LDAP($this->config->getSystemValueString('ldap_log_file')); | |||
} | |||
if (isset($argument['avatarManager'])) { |
@@ -38,14 +38,16 @@ use OCA\User_LDAP\PagedResults\IAdapter; | |||
use OCA\User_LDAP\PagedResults\Php73; | |||
class LDAP implements ILDAPWrapper { | |||
protected $logFile = ''; | |||
protected $curFunc = ''; | |||
protected $curArgs = []; | |||
/** @var IAdapter */ | |||
protected $pagedResultsAdapter; | |||
public function __construct() { | |||
public function __construct(string $logFile = '') { | |||
$this->pagedResultsAdapter = new Php73(); | |||
$this->logFile = $logFile; | |||
} | |||
/** | |||
@@ -349,6 +351,18 @@ class LDAP implements ILDAPWrapper { | |||
private function preFunctionCall($functionName, $args) { | |||
$this->curFunc = $functionName; | |||
$this->curArgs = $args; | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
$args = array_reduce($this->curArgs, static function (array $carry, $item): array { | |||
$carry[] = !is_resource($item) ? $item : '(resource)'; | |||
return $carry; | |||
}, []); | |||
file_put_contents( | |||
$this->logFile, | |||
$this->curFunc . '::' . json_encode($args) . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
} | |||
/** |
@@ -1982,4 +1982,31 @@ $CONFIG = [ | |||
* Defaults to ``true`` | |||
*/ | |||
'files_no_background_scan' => false, | |||
/** | |||
* Log all queries into a file | |||
* | |||
* Warning: This heavily decreases the performance of the server and is only | |||
* meant to debug/profile the query interaction manually. | |||
* Also, it might log sensitive data into a plain text file. | |||
*/ | |||
'query_log_file' => '', | |||
/** | |||
* Log all redis requests into a file | |||
* | |||
* Warning: This heavily decreases the performance of the server and is only | |||
* meant to debug/profile the redis interaction manually. | |||
* Also, it might log sensitive data into a plain text file. | |||
*/ | |||
'redis_log_file' => '', | |||
/** | |||
* Log all LDAP requests into a file | |||
* | |||
* Warning: This heavily decreases the performance of the server and is only | |||
* meant to debug/profile the LDAP interaction manually. | |||
* Also, it might log sensitive data into a plain text file. | |||
*/ | |||
'ldap_log_file' => '', | |||
]; |
@@ -233,6 +233,7 @@ class Connection extends \Doctrine\DBAL\Connection { | |||
$sql = $this->replaceTablePrefix($sql); | |||
$sql = $this->adapter->fixupStatement($sql); | |||
$this->queriesExecuted++; | |||
$this->logQueryToFile($sql); | |||
return parent::executeQuery($sql, $params, $types, $qcp); | |||
} | |||
@@ -243,6 +244,7 @@ class Connection extends \Doctrine\DBAL\Connection { | |||
$sql = $this->replaceTablePrefix($sql); | |||
$sql = $this->adapter->fixupStatement($sql); | |||
$this->queriesExecuted++; | |||
$this->logQueryToFile($sql); | |||
return parent::executeUpdate($sql, $params, $types); | |||
} | |||
@@ -264,9 +266,21 @@ class Connection extends \Doctrine\DBAL\Connection { | |||
$sql = $this->replaceTablePrefix($sql); | |||
$sql = $this->adapter->fixupStatement($sql); | |||
$this->queriesExecuted++; | |||
$this->logQueryToFile($sql); | |||
return parent::executeStatement($sql, $params, $types); | |||
} | |||
protected function logQueryToFile(string $sql): void { | |||
$logFile = $this->systemConfig->getValue('query_log_file', ''); | |||
if ($logFile !== '' && is_writable($logFile)) { | |||
file_put_contents( | |||
$this->systemConfig->getValue('query_log_file', ''), | |||
$sql . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
} | |||
/** | |||
* Returns the ID of the last inserted row, or the last value from a sequence object, | |||
* depending on the underlying driver. |
@@ -64,16 +64,21 @@ class Factory implements ICacheFactory { | |||
*/ | |||
private $lockingCacheClass; | |||
/** @var string */ | |||
private $logFile; | |||
/** | |||
* @param string $globalPrefix | |||
* @param ILogger $logger | |||
* @param string|null $localCacheClass | |||
* @param string|null $distributedCacheClass | |||
* @param string|null $lockingCacheClass | |||
* @param string $logFile | |||
*/ | |||
public function __construct(string $globalPrefix, ILogger $logger, | |||
$localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null) { | |||
$localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null, string $logFile = '') { | |||
$this->logger = $logger; | |||
$this->logFile = $logFile; | |||
$this->globalPrefix = $globalPrefix; | |||
if (!$localCacheClass) { | |||
@@ -112,7 +117,7 @@ class Factory implements ICacheFactory { | |||
* @return IMemcache | |||
*/ | |||
public function createLocking(string $prefix = ''): IMemcache { | |||
return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix); | |||
return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||
} | |||
/** | |||
@@ -122,7 +127,7 @@ class Factory implements ICacheFactory { | |||
* @return ICache | |||
*/ | |||
public function createDistributed(string $prefix = ''): ICache { | |||
return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix); | |||
return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||
} | |||
/** | |||
@@ -132,7 +137,7 @@ class Factory implements ICacheFactory { | |||
* @return ICache | |||
*/ | |||
public function createLocal(string $prefix = ''): ICache { | |||
return new $this->localCacheClass($this->globalPrefix . '/' . $prefix); | |||
return new $this->localCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||
} | |||
/** |
@@ -37,8 +37,11 @@ class Redis extends Cache implements IMemcacheTTL { | |||
*/ | |||
private static $cache = null; | |||
public function __construct($prefix = '') { | |||
private $logFile; | |||
public function __construct($prefix = '', string $logFile = '') { | |||
parent::__construct($prefix); | |||
$this->logFile = $logFile; | |||
if (is_null(self::$cache)) { | |||
self::$cache = \OC::$server->getGetRedisFactory()->getInstance(); | |||
} | |||
@@ -52,6 +55,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
} | |||
public function get($key) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::get::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
$result = self::$cache->get($this->getNameSpace() . $key); | |||
if ($result === false && !self::$cache->exists($this->getNameSpace() . $key)) { | |||
return null; | |||
@@ -61,6 +72,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
} | |||
public function set($key, $value, $ttl = 0) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::set::' . $key . '::' . $ttl . '::' . json_encode($value) . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
if ($ttl > 0) { | |||
return self::$cache->setex($this->getNameSpace() . $key, $ttl, json_encode($value)); | |||
} else { | |||
@@ -69,10 +88,26 @@ class Redis extends Cache implements IMemcacheTTL { | |||
} | |||
public function hasKey($key) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::hasKey::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
return (bool)self::$cache->exists($this->getNameSpace() . $key); | |||
} | |||
public function remove($key) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::remove::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
if (self::$cache->del($this->getNameSpace() . $key)) { | |||
return true; | |||
} else { | |||
@@ -81,6 +116,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
} | |||
public function clear($prefix = '') { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::clear::' . $prefix . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
$prefix = $this->getNameSpace() . $prefix . '*'; | |||
$keys = self::$cache->keys($prefix); | |||
$deleted = self::$cache->del($keys); | |||
@@ -106,6 +149,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
if ($ttl !== 0 && is_int($ttl)) { | |||
$args['ex'] = $ttl; | |||
} | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::add::' . $key . '::' . $value . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
return self::$cache->set($this->getPrefix() . $key, $value, $args); | |||
} | |||
@@ -118,6 +169,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
* @return int | bool | |||
*/ | |||
public function inc($key, $step = 1) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::inc::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
return self::$cache->incrBy($this->getNameSpace() . $key, $step); | |||
} | |||
@@ -129,6 +188,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
* @return int | bool | |||
*/ | |||
public function dec($key, $step = 1) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::dec::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
if (!$this->hasKey($key)) { | |||
return false; | |||
} | |||
@@ -144,6 +211,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
* @return bool | |||
*/ | |||
public function cas($key, $old, $new) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::cas::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
if (!is_int($new)) { | |||
$new = json_encode($new); | |||
} | |||
@@ -166,6 +241,14 @@ class Redis extends Cache implements IMemcacheTTL { | |||
* @return bool | |||
*/ | |||
public function cad($key, $old) { | |||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||
file_put_contents( | |||
$this->logFile, | |||
$this->getNameSpace() . '::cad::' . $key . "\n", | |||
FILE_APPEND | |||
); | |||
} | |||
self::$cache->watch($this->getNameSpace() . $key); | |||
if ($this->get($key) === $old) { | |||
$result = self::$cache->multi() |
@@ -697,7 +697,8 @@ class Server extends ServerContainer implements IServerContainer { | |||
return new \OC\Memcache\Factory($prefix, $c->get(ILogger::class), | |||
$config->getSystemValue('memcache.local', null), | |||
$config->getSystemValue('memcache.distributed', null), | |||
$config->getSystemValue('memcache.locking', null) | |||
$config->getSystemValue('memcache.locking', null), | |||
$config->getSystemValueString('redis_log_file') | |||
); | |||
} | |||
return $arrayCacheFactory; |