xbnz / mtr
Framework agnostic package for MTR
0.1.2
2022-01-31 22:15 UTC
Requires
- php: 8.1.*
- illuminate/collections: ^9.0.0-beta.4
- psr/log: ^1.0 || ^2.0 || ^3.0
- s1lentium/iptools: ^1.1
- spatie/fork: ^1.1
- symfony/process: ^6.0
- webmozart/assert: ^1.10
Requires (Dev)
- mockery/mockery: ^1.5
- nunomaduro/collision: ^6.1
- phpunit/phpunit: ^9.5
- symfony/var-dumper: ^6.0
README
PHP MTR
Framework-agnostic asynchronous MTR library
⚠️ The MTR command requires root privileges for low interval, edit your /etc/sudoers file. |
---|
Get up and running
Require the package
composer require xbnz/mtr
Using MTR in your project (Laravel)
// Optionally configure DI (Laravel example) class AppServiceProvider extends Provider { public function register() { $this->app->bind(MTR::class, function (Application $app) { return MTR::build(Config::get('services.mtr_options'), $app->make(LoggerInterface::class)); }); } }
MTR options
// services.php return [ // ... 'mtr_options' => new \Xbnz\Mtr\MtrOptionsConfigDto(...) ]
⚠️ Important note on configuration options. |
---|
You should not disable the 'report wide' or 'json' options. The package will cease to work.
Bulk or single IP with async execution
use Xbnz\Mtr; public function __construct(private MTR $mtr) {} // Or without DI... public function __construct() { $this->mtr = Mtr::build(new MtrOptionsConfigDto(...), new Logger); } public function example() { // Consider a high timeout value for large scans. // Async threads above 50 might cause inaccuracies in RTT statistics. $results = $this->mtr->withIp('1.1.1.1', '8.8.8.8')->wrap($consoleTimeout, $concurrentProcesses); // OR $results = $this->mtr->withIp(...['1.1.1.1', '8.8.8.8'])->wrap($consoleTimeout, $concurrentProcesses); // OR $results = $this->mtr->withIp('1.1.1.1')->wrap($consoleTimeout, $concurrentProcesses); // OR $results = $this->mtr->withIp(995738574453)->wrap($consoleTimeout, $concurrentProcesses); // OR $results = $this->mtr->withIp('google.com')->wrap($consoleTimeout, $concurrentProcesses); // OR $results = $this->mtr->withIp(0x1294812)->wrap($consoleTimeout, $concurrentProcesses); Assert::containsOnlyInstancesOf( MtrResult::class, $results ); /** * If last hop of MTR !== supplied IP, the target is dead. * In most circumstances, you'd want to reject dead targets. * You might still want to see the hops for a dead target, so the default policy is not to reject. */ $aliveTargetHopPairs = $results ->reject(fn($result) => $result->targetDown()) ->map(fn($result) => [$result->targetHost => $result->hops]); ->each(fn($targetWithHops) => Assert::containsOnlyInstancesOf(MtrHopDto::class, $targetWithHops)); $aliveTargetHopPairs ->each(function ($hops, $ip) { if ($hops->last()->packetLoss > 5) { $this->logger->log("Target {$ip}, hop {$hops->last()->hopPositionCount} has {$hops->last()->packetLoss}% loss") } }); }
Hooking into the raw()
method
The raw()
method will return an unprocessed result set from MTR. This will also allow you to hook into each asynchronous
process, which is useful for long-running processes.
For example, you might want to keep track of each IP that is processed, like so.
public function handle(MTR $mtr) { // Thousands of IPs $mtr->withIp('1.1.1.1/20') ->raw(callable: function (ForkSerializableProcessDto $dto) { dump($dto->host . PHP_EOL); }) }