1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-30 06:39:01 +01:00

Add some prometheus stats

This commit is contained in:
Daniil Gentili 2024-05-01 18:21:21 +02:00
parent 13cea65a80
commit 3db5fb1b42
7 changed files with 205 additions and 15 deletions

View File

@ -63,9 +63,11 @@ final class GarbageCollector
} }
self::$started = true; self::$started = true;
EventLoop::unreference(EventLoop::repeat(1, static function (): void { $counter = Magic::getCounter("", "explicit_gc_count", "Number of times the GC was explicitly invoked", []);
EventLoop::unreference(EventLoop::repeat(1, static function () use ($counter): void {
$currentMemory = self::getMemoryConsumption(); $currentMemory = self::getMemoryConsumption();
if ($currentMemory > self::$memoryConsumption + self::$memoryDiffMb) { if ($currentMemory > self::$memoryConsumption + self::$memoryDiffMb) {
$counter();
gc_collect_cycles(); gc_collect_cycles();
self::$memoryConsumption = self::getMemoryConsumption(); self::$memoryConsumption = self::getMemoryConsumption();
/*self::$memoryConsumption = self::getMemoryConsumption(); /*self::$memoryConsumption = self::getMemoryConsumption();

View File

@ -994,6 +994,46 @@ abstract class InternalDoc
{ {
return $this->wrapper->getAPI()->getPlugin($class); return $this->wrapper->getAPI()->getPlugin($class);
} }
/**
* Returns a closure linked to the specified prometheus counter.
*
* @return Closure(): void Call to increment the counter
*/
final public function getPromCounter(string $namespace, string $name, string $help, array $labels = [
]): \Closure
{
return $this->wrapper->getAPI()->getPromCounter($namespace, $name, $help, $labels);
}
/**
* Returns a closure linked to the specified prometheus gauge.
*
* @return Closure(float): void
*/
final public function getPromGauge(string $namespace, string $name, string $help, array $labels = [
]): \Closure
{
return $this->wrapper->getAPI()->getPromGauge($namespace, $name, $help, $labels);
}
/**
* Returns a closure linked to the specified prometheus histogram.
*
* @return Closure(float): void
*/
final public function getPromHistogram(string $namespace, string $name, string $help, $labels = [
], ?array $buckets = null): \Closure
{
return $this->wrapper->getAPI()->getPromHistogram($namespace, $name, $help, $labels, $buckets);
}
/**
* Returns a closure linked to the specified prometheus summary.
*
* @return Closure(float): void
*/
final public function getPromSummary(string $namespace, string $name, string $help, $labels = [
], int $maxAgeSeconds = 600, ?array $quantiles = null): \Closure
{
return $this->wrapper->getAPI()->getPromSummary($namespace, $name, $help, $labels, $maxAgeSeconds, $quantiles);
}
/** /**
* Gets info of the propic of a user. * Gets info of the propic of a user.
*/ */

View File

@ -25,12 +25,14 @@ use Amp\DeferredFuture;
use Amp\Future; use Amp\Future;
use Amp\Ipc\IpcServer; use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket; use Amp\Ipc\Sync\ChannelledSocket;
use Closure;
use danog\Loop\Loop; use danog\Loop\Loop;
use danog\MadelineProto\Exception; use danog\MadelineProto\Exception;
use danog\MadelineProto\Ipc\Runner\ProcessRunner; use danog\MadelineProto\Ipc\Runner\ProcessRunner;
use danog\MadelineProto\Ipc\Runner\WebRunner; use danog\MadelineProto\Ipc\Runner\WebRunner;
use danog\MadelineProto\Logger; use danog\MadelineProto\Logger;
use danog\MadelineProto\Loop\InternalLoop; use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\SessionPaths; use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\Settings\Ipc; use danog\MadelineProto\Settings\Ipc;
use danog\MadelineProto\Shutdown; use danog\MadelineProto\Shutdown;
@ -48,7 +50,18 @@ use function Amp\delay;
*/ */
abstract class AbstractServer extends Loop abstract class AbstractServer extends Loop
{ {
use InternalLoop; use InternalLoop {
__construct as private internalInit;
}
/**
* @var Closure(int): void
*/
private Closure $connectionGauge;
public function __construct(MTProto $API)
{
$this->internalInit($API);
$this->connectionGauge = $API->getPromGauge("", "ipc_server_connections", "Number of IPC server connections");
}
/** /**
* Server version. * Server version.
*/ */
@ -204,6 +217,7 @@ abstract class AbstractServer extends Loop
{ {
$this->API->waitForInit(); $this->API->waitForInit();
$this->API->logger('Accepted IPC client connection!'); $this->API->logger('Accepted IPC client connection!');
($this->connectionGauge)(1);
$id = 0; $id = 0;
$payload = null; $payload = null;
@ -214,6 +228,7 @@ abstract class AbstractServer extends Loop
} catch (Throwable $e) { } catch (Throwable $e) {
Logger::log("Exception in IPC connection: $e"); Logger::log("Exception in IPC connection: $e");
} finally { } finally {
($this->connectionGauge)(-1);
EventLoop::queue(function () use ($socket, $payload): void { EventLoop::queue(function () use ($socket, $payload): void {
try { try {
$socket->disconnect(); $socket->disconnect();

View File

@ -20,13 +20,12 @@ declare(strict_types=1);
namespace danog\MadelineProto\Ipc; namespace danog\MadelineProto\Ipc;
use danog\MadelineProto\MTProto;
/** /**
* IPC server. * IPC server.
* *
* @internal * @internal
*/ */
final class Server extends AbstractServer { final class Server extends AbstractServer
{
} }

View File

@ -31,7 +31,7 @@ use Revolt\EventLoop;
* *
* @internal * @internal
*/ */
final class ServerCallback extends Server final class ServerCallback extends AbstractServer
{ {
/** /**
* Timeout watcher list, indexed by socket ID. * Timeout watcher list, indexed by socket ID.

View File

@ -32,6 +32,7 @@ use Amp\Http\Client\Request;
use Amp\SignalException; use Amp\SignalException;
use Amp\Sync\LocalKeyedMutex; use Amp\Sync\LocalKeyedMutex;
use Amp\Sync\LocalMutex; use Amp\Sync\LocalMutex;
use Closure;
use danog\AsyncOrm\Annotations\OrmMappedArray; use danog\AsyncOrm\Annotations\OrmMappedArray;
use danog\AsyncOrm\DbArray; use danog\AsyncOrm\DbArray;
use danog\AsyncOrm\DbArrayBuilder; use danog\AsyncOrm\DbArrayBuilder;
@ -73,6 +74,10 @@ use danog\MadelineProto\Wrappers\Events;
use danog\MadelineProto\Wrappers\Login; use danog\MadelineProto\Wrappers\Login;
use danog\MadelineProto\Wrappers\Loop; use danog\MadelineProto\Wrappers\Loop;
use danog\MadelineProto\Wrappers\Start; use danog\MadelineProto\Wrappers\Start;
use Prometheus\Counter;
use Prometheus\Gauge;
use Prometheus\Histogram;
use Prometheus\Summary;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Revolt\EventLoop; use Revolt\EventLoop;
use SplQueue; use SplQueue;
@ -506,6 +511,77 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
} }
} }
/**
* Returns a closure linked to the specified prometheus gauge.
*
* @internal
*
* @return Closure(int): void
*/
public function getPromGauge(string $namespace, string $name, string $help, array $labels = []): Closure
{
return Magic::getGauge(
$namespace,
$name,
$help,
$labels + ['session' => $this->getSessionName(), 'session_id' => (string) ($this->getSelf()['id'] ?? '')],
);
}
/**
* Returns a closure linked to the specified prometheus counter.
*
* @internal
*
* @return Closure(): void Call to increment the counter
*/
public function getPromCounter(string $namespace, string $name, string $help, array $labels = []): Closure
{
return Magic::getCounter(
$namespace,
$name,
$help,
$labels + ['session' => $this->getSessionName(), 'session_id' => (string) ($this->getSelf()['id'] ?? '')],
);
}
/**
* Returns a closure linked to the specified prometheus summary.
*
* @internal
*
* @return Closure(float): void
*/
public function getPromSummary(string $namespace, string $name, string $help, $labels = [], int $maxAgeSeconds = 600, ?array $quantiles = null): Closure
{
return Magic::getSummary(
$namespace,
$name,
$help,
$labels + ['session' => $this->getSessionName(), 'session_id' => (string) ($this->getSelf()['id'] ?? '')],
$maxAgeSeconds,
$quantiles
);
}
/**
* Returns a closure linked to the specified prometheus histogram.
*
* @internal
*
* @return Closure(float): void
*/
public function getPromHistogram(string $namespace, string $name, string $help, $labels = [], ?array $buckets = null): Closure
{
return Magic::getHistogram(
$namespace,
$name,
$help,
$labels + ['session' => $this->getSessionName(), 'session_id' => (string) ($this->getSelf()['id'] ?? '')],
$buckets
);
}
/** /**
* Initialization function. * Initialization function.
* *

View File

@ -22,6 +22,7 @@ namespace danog\MadelineProto;
use Amp\DeferredFuture; use Amp\DeferredFuture;
use Amp\SignalException; use Amp\SignalException;
use Closure;
use danog\MadelineProto\TL\Conversion\Extension; use danog\MadelineProto\TL\Conversion\Extension;
use phpseclib3\Math\BigInteger; use phpseclib3\Math\BigInteger;
use Prometheus\CollectorRegistry; use Prometheus\CollectorRegistry;
@ -206,7 +207,8 @@ final class Magic
* Whether there's a basedir limitation. * Whether there's a basedir limitation.
*/ */
public static bool $hasBasedirLimitation = false; public static bool $hasBasedirLimitation = false;
public static CollectorRegistry $prometheus; private static CollectorRegistry $prometheus;
private static array $promLabels;
/** /**
* Encoded emojis. * Encoded emojis.
* *
@ -341,16 +343,72 @@ final class Magic
} }
} }
self::$prometheus = new CollectorRegistry(new InMemory); self::$prometheus = new CollectorRegistry(new InMemory);
$alloc = self::$prometheus->registerGauge("", "php_memstats_alloc_bytes", "RAM allocated by the PHP memory pool", ["pid"]); self::$promLabels = ['release' => API::RELEASE];
$inuse = self::$prometheus->registerGauge("", "php_memstats_inuse_bytes", "RAM actually used by PHP", ["pid"]); if (self::$pid !== null) {
$labels = self::$pid ? [(string) self::$pid] : []; self::$promLabels['pid'] = (string) self::$pid;
EventLoop::repeat(1.0, function () use ($alloc, $inuse, $labels): void { }
$alloc->set((float) memory_get_usage(true), $labels);
$inuse->set((float) memory_get_usage(false), $labels); $alloc = self::getGauge("", "php_memstats_alloc_bytes", "RAM allocated by the PHP memory pool", []);
}); $inuse = self::getGauge("", "php_memstats_inuse_bytes", "RAM actually used by PHP", []);
EventLoop::unreference(EventLoop::repeat(1.0, static function () use ($alloc, $inuse): void {
$alloc((float) memory_get_usage(true));
$inuse((float) memory_get_usage(false));
}));
GarbageCollector::start(); GarbageCollector::start();
self::$inited = true; self::$inited = true;
} }
/**
* @param array<string, string> $labels
* @return Closure(int): void
*/
public static function getGauge(string $namespace, string $name, string $help, array $labels): Closure
{
$labels += self::$promLabels;
$gauge = self::$prometheus->getOrRegisterGauge($namespace, $name, $help, array_keys($labels));
$labels = array_values($labels);
return static function (int $by) use ($labels, $gauge): void {
$gauge->incBy($by);
};
}
/**
* @param array<string, string> $labels
* @return Closure(): void
*/
public static function getCounter(string $namespace, string $name, string $help, array $labels): Closure
{
$labels += self::$promLabels;
$gauge = self::$prometheus->getOrRegisterCounter($namespace, $name, $help, array_keys($labels));
$labels = array_values($labels);
return static function () use ($labels, $gauge): void {
$gauge->inc($labels);
};
}
/**
* @param array<string, string> $labels
* @return Closure(float): void
*/
public static function getHistogram(string $namespace, string $name, string $help, array $labels, ?array $buckets = null): Closure
{
$labels += self::$promLabels;
$gauge = self::$prometheus->getOrRegisterHistogram($namespace, $name, $help, array_keys($labels), $buckets);
$labels = array_values($labels);
return static function ($value) use ($labels, $gauge): void {
$gauge->observe($value, $labels);
};
}
/**
* @param array<string, string> $labels
* @return Closure(float): void
*/
public static function getSummary(string $namespace, string $name, string $help, array $labels, int $maxAgeSeconds = 600, ?array $quantiles = null): Closure
{
$labels += self::$promLabels;
$gauge = self::$prometheus->getOrRegisterSummary($namespace, $name, $help, array_keys($labels), $maxAgeSeconds, $quantiles);
$labels = array_values($labels);
return static function ($value) use ($labels, $gauge): void {
$gauge->observe($value, $labels);
};
}
/** /**
* Check if this is a POSIX fork of the main PHP process. * Check if this is a POSIX fork of the main PHP process.
*/ */