[
  {
    "path": ".editorconfig",
    "content": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_size = 4\nindent_style = space\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test and documentation with \"export-ignore\".\n/.gitattributes     export-ignore\n/.gitignore         export-ignore\n/.travis.yml        export-ignore\n/phpunit.xml.dist   export-ignore\n/.scrutinizer.yml   export-ignore\n/tests              export-ignore\n/.editorconfig      export-ignore\n"
  },
  {
    "path": ".gitignore",
    "content": "build\ncomposer.lock\ndocs\nvendor\ncoverage\ntodo.txt\npush.sh\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) Sarfraz Ahmed\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)\n[![Latest Version on Packagist][ico-version]][link-packagist]\n[![Total Downloads][ico-downloads]][link-downloads]\n\n# Laravel Meter\n\nLaravel Meter monitors application performance for different things such as requests, commands, queries, events, etc and presents results in tables/charts. Think of it like Laravel Telescope but for performance monitoring. \n\n## Requirements ##\n\n - PHP >= 7.3\n - Laravel 5.5+ | 6\n\n## Configuration\n\nAvailable options are:\n- METER_DB_CONNECTION \n  ` Database connection to use for meter entries. Default: mysql (uses default connection) `\n- METER_PATH \n ` Path to access meter UI. Default: meter `\n- METER_USERNAME \n ` Username to access meter UI. Default: null `\n- METER_PASSWORD \n ` Password to access meter UI. Default: null `\n- ignore_matched_string \n ` It helps to ignore the matched string in the query. Ex:`\n \n ```php\n \"ignore_matched_string\" => [\n        \"query\" => [\n            \"information_schema\",\n        ]\n\n    ],\n```\n\nThere are more options available, please check `config/meter.php` file for more details.\n \n## Monitors ## \n\n- Requests\n- Queries\n- Commands\n- Events\n- Schedule\n- CPU Load\n- Disk Space\n- Server Memory\n- HTTP Connections\n\n## Screenshot ##\n\n![Main Window](https://github.com/sarfraznawaz2005/meter/blob/master/screenshot.png?raw=true)\n\n\n## Installation ##\n\nInstall via composer\n\n```\ncomposer require sarfraznawaz2005/meter\n```\n\n\nPublish package's config file by running below command:\n\n```bash\nphp artisan vendor:publish --provider=\"Sarfraznawaz2005\\Meter\\MeterServiceProvider\"\n```\nIt should publish `config/meter.php` config file and migration file.\n\nNow run `php artisan migrate` command to create `meter_entries` database table.\n\n## Usage ##\n\nEnable Meter in `config/meter.php` and setup any other options as needed. Meter UI will be visible at `path` config you set.\n\nBy default Meter monitors:\n\n- Requests\n- Queries\n- Commands\n- Events\n- Schedule\n\nTo monitor server stuff:\n\n- CPU Load\n- Disk Space\n- Server Memory\n- HTTP Connections\n\nYou should use `meter:servermonitor` command. Schedule it in Laravel's console kernel file accordingly:\n                           \n```php\n// app/Console/Kernel.php\nprotected function schedule(Schedule $schedule)\n{\n    $schedule->command('meter:servermonitor')->hourly(); // or daily\n}\n```\n## Authentication ##\n\nYou can use `username` and `password` config options to setup basic HTTP authentication for Meter interface to be accessed. Once setup, user should provide correct username and password to access Meter page(s).\n\nAlternatively, you can use `middleware` config option to apply your own auth middleware, etc \n\n## Ignoring Things ##\n\nYou can use `ignore_paths` and `ignore_commands` config options to ignore desired pages or commands from being monitored by Meter.\n\n## Data Pruning ##\n\nYou need to periodically remove meter data otherwise your database will turn big quickly. To prune meter data, you can setup prune command in Kernel file:\n\n```php\n$schedule->command('meter:prune')->daily();\n// or\n$schedule->command('meter:prune --days=7')->daily();\n```\n\n## Contributing\n\nPRs are welcome. Thanks\n\n## Security\n\nIf you discover any security related issues, please email sarfraznawaz2005@gmail.com instead of using the issue tracker.\n\n## Credits\n\n- [Sarfraz Ahmed][link-author]\n- [All Contributors][link-contributors]\n\n## License\n\nPlease see the [license file](LICENSE.md) for more information.\n\n[ico-version]: https://img.shields.io/packagist/v/sarfraznawaz2005/meter.svg?style=flat-square\n[ico-downloads]: https://img.shields.io/packagist/dt/sarfraznawaz2005/meter.svg?style=flat-square\n\n[link-packagist]: https://packagist.org/packages/sarfraznawaz2005/meter\n[link-downloads]: https://packagist.org/packages/sarfraznawaz2005/meter\n[link-author]: https://github.com/sarfraznawaz2005\n[link-contributors]: https://github.com/sarfraznawaz2005/meter/graphs/contributors\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"sarfraznawaz2005/meter\",\n    \"description\": \"laravel package to find performance bottlenecks in your laravel application.\",\n    \"keywords\": [\n        \"laravel\",\n        \"performance\",\n        \"meter\",\n        \"log\",\n        \"request\",\n        \"queries\",\n        \"database\",\n        \"monitor\",\n        \"health\"\n    ],\n    \"homepage\": \"https://github.com/sarfraznawaz2005/meter\",\n    \"license\": \"MIT\",\n    \"type\": \"library\",\n    \"authors\": [\n        {\n            \"name\": \"Sarfraz Ahmed\",\n            \"email\": \"sarfraznawaz2005@gmail.com\",\n            \"role\": \"Developer\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.3|>=8.0\",\n        \"illuminate/support\": \"~5|~6|~7|~8|~9\",\n        \"consoletvs/charts\": \"6.*\",\n        \"balping/json-raw-encoder\": \"^1.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Sarfraznawaz2005\\\\Meter\\\\\": \"src\"\n        },\n        \"files\": [\n            \"src/Helpers.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Sarfraznawaz2005\\\\Meter\\\\Tests\\\\\": \"tests\"\n        }\n    },\n    \"scripts\": {\n        \"test\": \"vendor/bin/phpunit\",\n        \"test-coverage\": \"vendor/bin/phpunit --coverage-html coverage\"\n    },\n    \"config\": {\n        \"sort-packages\": true\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \"Sarfraznawaz2005\\\\Meter\\\\MeterServiceProvider\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"vendor/autoload.php\"\n         backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         colors=\"true\"\n         verbose=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         processIsolation=\"false\"\n         stopOnFailure=\"false\">\n    <testsuites>\n        <testsuite name=\"Test Suite\">\n            <directory>tests</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist>\n            <directory suffix=\".php\">src/</directory>\n        </whitelist>\n    </filter>\n    <logging>\n        <log type=\"tap\" target=\"build/report.tap\"/>\n        <log type=\"junit\" target=\"build/report.junit.xml\"/>\n        <log type=\"coverage-html\" target=\"build/coverage\" charset=\"UTF-8\" yui=\"true\" highlight=\"true\"/>\n        <log type=\"coverage-text\" target=\"build/coverage.txt\"/>\n        <log type=\"coverage-clover\" target=\"build/logs/clover.xml\"/>\n    </logging>\n</phpunit>\n"
  },
  {
    "path": "src/Charts/Chart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse ConsoleTVs\\Charts\\Classes\\Chartjs\\Chart as BaseChart;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\n\nabstract class Chart extends BaseChart\n{\n    const COLOR_RED = '255, 99, 132';\n    const COLOR_BLUE = '0, 123, 255';\n    const COLOR_GREEN = '40, 167, 69';\n    const COLOR_YELLOW = '255, 193, 7';\n\n    protected $data = [];\n\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    abstract protected function setOptions();\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    abstract protected function setData(MeterModel $model);\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    abstract protected function getLabels(): array;\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    abstract protected function getValues(): array;\n\n    /**\n     * Sets DataSet for chart.\n     *\n     * @return void\n     */\n    abstract protected function setDataSet();\n\n    /**\n     * Chart constructor.\n     * @param MeterModel $model\n     */\n    public function __construct(MeterModel $model)\n    {\n        parent::__construct();\n\n        $this->setData($model);\n\n        $this->setOptions();\n\n        $this->labels($this->getLabels());\n\n        $this->setDataSet();\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/CommandsTimeChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass CommandsTimeChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true,\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Command Time (ms)'\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Time: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Command: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::COMMAND)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['time'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => $item->content['command'],\n                    'y' => (int)$item->content['time'],\n                ];\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . CommandMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Command Time', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/ConnectionsChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass ConnectionsChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::CONNECTIONS)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            $this->data[(string)$item->created_at] = (int)$item->content['count'];\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . HttpConnectionsMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Count', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/CpuChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass CpuChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::CPU)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            $this->data[(string)$item->created_at] = (int)$item->content['percent'];\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . CpuMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Percent', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/DiskSpaceChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass DiskSpaceChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::DISK)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            $this->data[(string)$item->created_at] = (int)$item->content['percent'];\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . DiskSpaceMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Percent', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/EventsTimeChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass EventsTimeChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true,\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Event Time (ms)'\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Time: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Event: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::EVENT)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['time'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => $item->content['name'],\n                    'y' => (int)$item->content['time'],\n                ];\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . EventMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Event Time', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/OverAllTimesChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor;\nuse function foo\\func;\n\nclass OverAllTimesChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                ]]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->filtered()->orderBy('id', 'asc')->get() as $item) {\n            $time = 0;\n\n            if (isset($item->content['duration'])) {\n                $time = $item->content['duration'];\n            } elseif (isset($item->content['time'])) {\n                $time = $item->content['time'];\n            }\n\n            $this->data[(string)$item->created_at] = [\n                'type' => $item->type,\n                'time' => $time\n            ];\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        if (config('meter.monitors.' . RequestMonitor::class . '.enabled', true)) {\n            $this->dataset('Response Time', 'line', collect($this->getValues())->where('type', 'request')->pluck('time'))\n                ->color('rgb(0, 123, 255)')\n                ->options([\n                    'pointRadius' => 2,\n                    'fill' => true,\n                    'lineTension' => 0,\n                    'borderWidth' => 1,\n                    'barPercentage' => 0.9\n                ])\n                ->backgroundcolor('rgba(0, 123, 255, 0.6)');\n        }\n\n        if (config('meter.monitors.' . QueryMonitor::class . '.enabled', true)) {\n            $this->dataset('Query Time', 'line', collect($this->getValues())->where('type', 'query')->pluck('time'))\n                ->color('rgb(40, 167, 69)')\n                ->options([\n                    'pointRadius' => 2,\n                    'fill' => true,\n                    'lineTension' => 0,\n                    'borderWidth' => 1,\n                    'barPercentage' => 0.9\n                ])\n                ->backgroundcolor('rgba(40, 167, 69, 0.6)');\n        }\n\n        if (config('meter.monitors.' . CommandMonitor::class . '.enabled', true)) {\n            $this->dataset('Command Time', 'line', collect($this->getValues())->where('type', 'command')->pluck('time'))\n                ->color('rgb(23, 162, 184)')\n                ->options([\n                    'pointRadius' => 2,\n                    'fill' => true,\n                    'lineTension' => 0,\n                    'borderWidth' => 1,\n                    'barPercentage' => 0.9\n                ])\n                ->backgroundcolor('rgba(23, 162, 184, 0.6)');\n        }\n\n        if (config('meter.monitors.' . EventMonitor::class . '.enabled', true)) {\n            $this->dataset('Event Time', 'line', collect($this->getValues())->where('type', 'event')->pluck('time'))\n                ->color('rgb(255, 193, 7)')\n                ->options([\n                    'pointRadius' => 2,\n                    'fill' => true,\n                    'lineTension' => 0,\n                    'borderWidth' => 1,\n                    'barPercentage' => 0.9\n                ])\n                ->backgroundcolor('rgba(255, 193, 7, 0.6)');\n        }\n\n        if (config('meter.monitors.' . ScheduleMonitor::class . '.enabled', true)) {\n            $this->dataset('Schedule Time', 'line', collect($this->getValues())->where('type', 'schedule')->pluck('time'))\n                ->color('rgb(220, 53, 69)')\n                ->options([\n                    'pointRadius' => 2,\n                    'fill' => true,\n                    'lineTension' => 0,\n                    'borderWidth' => 1,\n                    'barPercentage' => 0.9\n                ])\n                ->backgroundcolor('rgba(220, 53, 69, 0.6)');\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/QueriesTimeChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Illuminate\\Support\\Str;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass QueriesTimeChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Time (ms)'\n                    ]\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Time: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Query: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::QUERY)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['time'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => Str::limit($item->content['sql'], 120),\n                    'y' => (int)$item->content['time'],\n                ];\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . QueryMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Query Time', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/RequestMemoryChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass RequestMemoryChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Memory (MB)'\n                    ]\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Memory: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Path: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::REQUEST)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['memory'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => $item->content['uri'],\n                    'y' => (int)$item->content['memory'],\n                ];\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . RequestMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Memory', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/RequestTimeChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass RequestTimeChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Response Time (ms)'\n                    ]\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Time: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Path: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::REQUEST)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['duration'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => $item->content['uri'],\n                    'y' => (int)$item->content['duration'],\n                ];\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . RequestMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Response Time', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/SchedulesTimeChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Balping\\JsonRaw\\Raw;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass SchedulesTimeChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->pluck('y')->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->pluck('y')->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->pluck('y')->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true,\n                    ],\n                    'scaleLabel' => [\n                        'display' => true,\n                        'labelString' => 'Command Time (ms)'\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    //'type' => 'time',\n                    'time' => [\n                        'displayFormats' => ['hour' => 'MMM D hA'],\n                    ],\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n            'tooltips' => [\n                'callbacks' => [\n                    'label' => new Raw('function(item, data) { return \"Time: \" + data.datasets[item.datasetIndex].data[item.index].y + \" (Command: \" + data.datasets[item.datasetIndex].data[item.index].x + \")\"}')\n                ]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        /*\n        $this->data = $model->type(Type::SCHEDULE)\n            ->filtered()\n            ->groupBy('date')\n            ->orderBy('date', 'ASC')\n            ->get([\n                DB::raw('DATE(created_at) as date'),\n                DB::raw('COUNT(*) as \"total\"')\n            ])\n            ->pluck('total', 'date')\n            ->toArray();\n        */\n\n        foreach ($model->type(Type::SCHEDULE)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            if (isset($item->content['time'])) {\n                $this->data[(string)$item->created_at] = [\n                    'x' => $item->content['command'],\n                    'y' => (int)$item->content['time'],\n                ];;\n            }\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . ScheduleMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Command Time', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Charts/ServerMemoryChart.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Charts;\n\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass ServerMemoryChart extends Chart\n{\n    /**\n     * Sets options for chart.\n     *\n     * @return void\n     */\n    protected function setOptions()\n    {\n        $this->options([\n            'responsive' => true,\n            'maintainAspectRatio' => false,\n            'title' => [\n                'display' => true,\n                'text' => [\n                    'Min ' . round(collect($this->getValues())->min()) . ' | ' .\n                    'Avg ' . round(collect($this->getValues())->average()) . ' | ' .\n                    'Max ' . round(collect($this->getValues())->max())\n                ],\n            ],\n            'legend' => false,\n            'scales' => [\n                'yAxes' => [[\n                    'ticks' => [\n                        'beginAtZero' => true\n                    ],\n                ]],\n                'xAxes' => [[\n                    'display' => false,\n                    'ticks' => [\n                        'beginAtZero' => true,\n                        'autoSkip' => true,\n                        'autoSkipPadding' => 30,\n                        'maxRotation' => 0,\n                    ],\n                    'gridLines' => ['offsetGridLines' => true],\n                    'offset' => true,\n                ]]\n            ],\n        ], true);\n    }\n\n    /**\n     * Sets data for chart.\n     *\n     * @param MeterModel $model\n     * @return void\n     */\n    protected function setData(MeterModel $model)\n    {\n        foreach ($model->type(Type::MEMORY)->filtered()->orderBy('id', 'asc')->get() as $item) {\n            $this->data[(string)$item->created_at] = (int)$item->content['percent'];\n        }\n    }\n\n    /**\n     * Gets labels for chart.\n     *\n     * @return mixed\n     */\n    protected function getLabels(): array\n    {\n        return array_keys($this->data);\n    }\n\n    /**\n     * Gets values for chart.\n     *\n     * @return mixed\n     */\n    protected function getValues(): array\n    {\n        return array_values($this->data);\n    }\n\n    /**\n     * Generates and returns chart\n     *\n     * @return void\n     */\n    protected function setDataSet()\n    {\n        $type = config('meter.monitors.' . MemoryMonitor::class . '.graph_type', 'bar');\n\n        $this->dataset('Percent', $type, $this->getValues())\n            ->color('rgb(' . static::COLOR_RED . ')')\n            ->options([\n                'pointRadius' => 2,\n                'fill' => true,\n                'lineTension' => 0,\n                'borderWidth' => 1,\n                //'minBarLength' => 50,\n                'barPercentage' => 0.9\n            ])\n            ->backgroundcolor('rgba(' . static::COLOR_RED . ', 0.6)');\n    }\n\n}\n"
  },
  {
    "path": "src/Config/config.php",
    "content": "<?php\n\nreturn [\n\n    // Enable/Disable Meter\n    'enabled' => env('METER_ENABLED', false),\n\n    #---------------------------------------------------------------------\n\n    /*\n    * This is the subdomain where Meter will be accessible from. If the\n    * setting is null, Meter will reside under the same domain as the\n    * application.\n    */\n\n    'domain' => env('METER_DOMAIN', null),\n\n    #---------------------------------------------------------------------\n\n    /*\n     * URI path Meter will be accessible from.\n     *\n     * Username and password for basic http authentication to access\n     * meter interface.\n     */\n\n    'path' => env('METER_PATH', 'meter'),\n    'username' => env('METER_USERNAME', 'meter'),\n    'password' => env('METER_PASSWORD', 'meter'),\n\n    #---------------------------------------------------------------------\n\n    /*\n    * These middleware will be assigned to every Meter route, giving you\n    * the chance to add your own middleware to this list or change any of\n    * the existing middleware.\n    */\n\n    'middleware' => [\n        //\n    ],\n\n    #---------------------------------------------------------------------\n\n    /*\n    | The following array lists the URI paths and Artisan commands that will\n    | not be watched by Meter. In addition to this list, some Laravel\n    | commands like migrations and queue commands are always ignored.\n    */\n\n    'ignore_paths' => [\n        //\n    ],\n\n    'ignore_commands' => [\n        //\n    ],\n\n    'ignore_matched_string' => [\n\n        \"query\" => [\n            \"information_schema\",\n        ]\n\n    ],\n\n    #---------------------------------------------------------------------\n\n    /*\n    * The database connection Meter will use to store data. By default, it\n    * will use the default database connection.\n    */\n    'storage' => [\n        'database' => [\n            'connection' => env('METER_DB_CONNECTION', 'mysql'),\n        ],\n    ],\n\n    #---------------------------------------------------------------------\n\n    // Customize the monitors meter will use to show statiscs of.\n    'monitors' => [\n        Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor::class => [\n            'enabled' => env('METER_REQUEST_MONITOR', true),\n            'slow' => 3000, // considered slow if equal or over given time in ms\n            'graph_type' => env('METER_REQUEST_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_REQUEST_ON_DASHBOARD', true)\n        ],\n\n        Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor::class => [\n            'enabled' => env('METER_QUERY_MONITOR', true),\n            'ignore_packages' => true,\n            'slow' => 500, // considered slow if equal or over given time in ms\n            'graph_type' => env('METER_QUERY_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_QUERY_ON_DASHBOARD', true)\n        ],\n\n        Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor::class => [\n            'enabled' => env('METER_COMMAND_MONITOR', true),\n            'ignore' => [],\n            'graph_type' => env('METER_COMMAND_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_COMMAND_ON_DASHBOARD', true)\n        ],\n\n        Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor::class => [\n            'enabled' => env('METER_EVENT_MONITOR', true),\n            'ignore' => [],\n            'graph_type' => env('METER_EVENT_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_EVENT_ON_DASHBOARD', true)\n        ],\n\n        Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor::class => [\n            'enabled' => env('METER_SCHEDULE_MONITOR', true),\n            'graph_type' => env('METER_SCHEDULE_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_SCHEDULE_ON_DASHBOARD', true)\n        ],\n\n        #####################################################################\n        # below monitors are run via \"meter:servermonitor\" command if enabled\n        #####################################################################\n\n        // monitors average CPU usage\n        Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor::class => [\n            'enabled' => env('METER_CPU_MONITOR', false),\n            'graph_type' => env('METER_CPU_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_CPU_ON_DASHBOARD', true)\n        ],\n\n        // monitors disk space usage\n        Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor::class => [\n            'enabled' => env('METER_DISK_MONITOR', false),\n            'graph_type' => env('METER_DISK_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_DISK_ON_DASHBOARD', true)\n        ],\n\n        // monitors server memory usage\n        Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor::class => [\n            'enabled' => env('METER_MEMORY_MONITOR', false),\n            'graph_type' => env('METER_MEMORY_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_MEMOR_ON_DASHBOARD', true)\n        ],\n\n        // monitors active http connections count on port 80\n        Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor::class => [\n            'enabled' => env('METER_HTTP_CONNECTIONS_MONITOR', false),\n            'port' => env('METER_HTTP_CONNECTIONS_PORT', 80),\n            'graph_type' => env('METER_HTTP_CONNECTIONS_GRAPH_TYPE', 'bar'), // bar, line\n            'show_on_dashboard' => env('METER_HTTP_CONNECTIONS_ON_DASHBOARD', true)\n        ],\n    ],\n\n    // Graph/Table filters. Will be added between \"Today\" and \"All\".\n    'filters' => [\n        'Yesterday' => 1,\n        'Week' => 7,\n        'Month' => 30,\n        '3 Month' => 90,\n        '6 Month' => 180,\n        'Year' => 365,\n    ],\n];\n"
  },
  {
    "path": "src/Console/PruneCommand.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\n\nclass PruneCommand extends Command\n{\n    protected $signature = 'meter:prune {--days=1 : The number of days to retain Meter data}';\n    protected $description = 'Prune stale entries from the Meter database';\n\n    public function handle(MeterModel $model)\n    {\n        /* @var $model Builder */\n        $deleteCount = $model->whereDate('created_at', '<', now()->subDays($this->option('days')))->delete();\n\n        $this->info($deleteCount.' entries pruned.');\n    }\n}\n"
  },
  {
    "path": "src/Console/PublishCommand.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass PublishCommand extends Command\n{\n    protected $signature = 'meter:publish {--force : Overwrite any existing files}';\n    protected $description = 'Publish all of the Meter resources.';\n\n    public function handle()\n    {\n        $this->call('vendor:publish', [\n            '--tag' => 'meter-config',\n            '--force' => $this->option('force'),\n        ]);\n\n        $this->call('vendor:publish', [\n            '--tag' => 'meter-views',\n            '--force' => true,\n        ]);\n\n        $this->call('vendor:publish', [\n            '--tag' => 'meter-assets',\n            '--force' => true,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Console/ServerMonitorCommand.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor;\nuse Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor;\n\nclass ServerMonitorCommand extends Command\n{\n    protected $signature = 'meter:servermonitor';\n    protected $description = 'Checks server stuff such as disk space, cpu usage, memory, etc';\n\n    public static $serverMonitors = [\n        CpuMonitor::class,\n        DiskSpaceMonitor::class,\n        MemoryMonitor::class,\n        HttpConnectionsMonitor::class,\n    ];\n\n    public function handle()\n    {\n        if (!config('meter.enabled')) {\n            return;\n        }\n\n        if (Meter::isMonitoring()) {\n            $app = app();\n\n            foreach (static::$serverMonitors as $monitor) {\n                if (config('meter.monitors.' . $monitor . '.enabled', true)) {\n                    $monitor = $app->make($monitor);\n\n                    $monitor->register($app);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Helpers.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\n\nif (!function_exists('meterActiveLink')) {\n    function meterActiveLink($path, $class = 'active')\n    {\n        if (request()->is((array)$path) || request()->routeIs((array)$path)) {\n            return $class;\n        }\n\n        return '';\n    }\n}\n\nif (!function_exists('meterWithHtmlTitle')) {\n    function meterWithHtmlTitle($text, $title)\n    {\n        return \"<span data-toggle='tooltip' title='$title'>$text</span>\";\n    }\n}\n\nif (!function_exists('meterBadge')) {\n    function meterBadge($text)\n    {\n        return \"<span class='badge font-weight-light badge-secondary'>$text</span>\";\n    }\n}\n\nif (!function_exists('meterAutoBadge')) {\n    function meterAutoBadge($text, $colorMap)\n    {\n        $color = array_keys(array_filter($colorMap))[0] ?? 'badge-secondary';\n\n        return \"<span class='badge font-weight-light badge-$color'>$text</span>\";\n    }\n}\n\nif (!function_exists('meterCenter')) {\n    function meterCenter($text)\n    {\n        return \"<div class='text-center'>$text</div>\";\n    }\n}\n\nif (!function_exists('meterDetailsButton')) {\n    function meterDetailsButton($details)\n    {\n        $details = htmlspecialchars(json_encode($details), ENT_QUOTES, 'UTF-8');\n\n        return <<< HTML\n        <a class=\"btnDetails\" data-details=\"$details\" href=\"#\">\n            <i class=\"icon fa fa-bullseye\"></i>\n        </a>\nHTML;\n    }\n}\n\nif (!function_exists('meterGetSql')) {\n    function meterGetSql(Builder $builder)\n    {\n        $addSlashes = str_replace('?', \"'?'\", $builder->toSql());\n\n        return vsprintf(str_replace('?', '%s', $addSlashes), $builder->getBindings());\n    }\n}\n\nif (!function_exists('meterFormatModel')) {\n    function meterFormatModel(Model $model)\n    {\n        return get_class($model) . ':' . implode('_', Arr::wrap($model->getKey()));\n    }\n}\n\nif (!function_exists('meterIgnoreEntry')) {\n    function meterIgnoreEntry($key, $content)\n    {\n        return str_contains($content, $key);\n    }\n}\n"
  },
  {
    "path": "src/Http/Controllers/PagesController.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Http\\Controllers;\n\nuse Illuminate\\Routing\\Controller;\nuse Illuminate\\Support\\Facades\\DB;\nuse Sarfraznawaz2005\\Meter\\Charts\\CommandsTimeChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\ConnectionsChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\CpuChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\DiskSpaceChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\EventsTimeChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\QueriesTimeChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\RequestMemoryChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\RequestTimeChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\SchedulesTimeChart;\nuse Sarfraznawaz2005\\Meter\\Charts\\ServerMemoryChart;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\n\nclass PagesController extends Controller\n{\n    public function home(\n        RequestTimeChart $requestTimeChart,\n        RequestMemoryChart $requestMemoryChart,\n        QueriesTimeChart $queriesTimeChart,\n        CommandsTimeChart $commandsTimeChart,\n        EventsTimeChart $eventsTimeChart,\n        SchedulesTimeChart $schedulesTimeChart,\n        CpuChart $cpuChart,\n        DiskSpaceChart $diskSpaceChart,\n        ServerMemoryChart $serverMemoryChart,\n        ConnectionsChart $connectionsChart\n    )\n    {\n        $totals = MeterModel::select(\n            DB::raw('count(*) as total'),\n            DB::raw(\"count(case when type = 'command' then 1 end) as commands\"),\n            DB::raw(\"count(case when type = 'event' then 1 end) as events\"),\n            DB::raw(\"count(case when type = 'query' then 1 end) as queries\"),\n            DB::raw(\"count(case when type = 'request' then 1 end) as requests\"),\n            DB::raw(\"count(case when type = 'schedule' then 1 end) as schedules\")\n        )->filtered()->first();\n\n        return view(\n            'meter::dashboard', compact(\n                'totals',\n                'requestTimeChart',\n                'requestMemoryChart',\n                'queriesTimeChart',\n                'commandsTimeChart',\n                'eventsTimeChart',\n                'schedulesTimeChart',\n                'cpuChart',\n                'diskSpaceChart',\n                'serverMemoryChart',\n                'connectionsChart'\n            )\n        );\n    }\n\n    public function queries(QueriesTimeChart $queriesTimeChart)\n    {\n        return view('meter::queries', compact('queriesTimeChart'));\n    }\n\n    public function requests(\n        RequestTimeChart $timeChart,\n        RequestMemoryChart $memoryChart\n    )\n    {\n        return view('meter::requests', compact('timeChart', 'memoryChart'));\n    }\n\n    public function commands(CommandsTimeChart $chart)\n    {\n        return view('meter::commands', compact('chart'));\n    }\n\n    public function events(EventsTimeChart $chart)\n    {\n        return view('meter::events', compact('chart'));\n    }\n\n    public function schedules(SchedulesTimeChart $chart)\n    {\n        return view('meter::schedules', compact('chart'));\n    }\n\n    public function serverStats(\n        CpuChart $cpuChart,\n        DiskSpaceChart $diskSpaceChart,\n        ServerMemoryChart $serverMemoryChart,\n        ConnectionsChart $connectionsChart\n    )\n    {\n        return view('meter::server', compact('cpuChart', 'diskSpaceChart', 'serverMemoryChart', 'connectionsChart'));\n    }\n}\n"
  },
  {
    "path": "src/Http/Controllers/TablesController.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Http\\Controllers;\n\nuse Illuminate\\Routing\\Controller;\nuse Sarfraznawaz2005\\Meter\\Tables\\CommandsTable;\nuse Sarfraznawaz2005\\Meter\\Tables\\EventsTable;\nuse Sarfraznawaz2005\\Meter\\Tables\\QueriesTable;\nuse Sarfraznawaz2005\\Meter\\Tables\\RequestsTable;\nuse Sarfraznawaz2005\\Meter\\Tables\\SchedulesTable;\n\nclass TablesController extends Controller\n{\n    public function requestsTable(RequestsTable $table): array\n    {\n        return $table->getData();\n    }\n\n    public function queriesTable(QueriesTable $table): array\n    {\n        return $table->getData();\n    }\n\n    public function commandsTable(CommandsTable $table): array\n    {\n        return $table->getData();\n    }\n\n    public function eventsTable(EventsTable $table): array\n    {\n        return $table->getData();\n    }\n\n    public function schedulesTable(SchedulesTable $table): array\n    {\n        return $table->getData();\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/BasicAuth.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass BasicAuth\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  Request $request\n     * @param Closure $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        $AUTH_USER = config('meter.username');\n        $AUTH_PASS = config('meter.password');\n\n        header('Cache-Control: no-cache, must-revalidate, max-age=0');\n\n        $hasSuppliedCredentials = !(empty($_SERVER['PHP_AUTH_USER']) && empty($_SERVER['PHP_AUTH_PW']));\n\n        $isNotAuthenticated = (\n            !$hasSuppliedCredentials ||\n            $_SERVER['PHP_AUTH_USER'] != $AUTH_USER ||\n            $_SERVER['PHP_AUTH_PW'] != $AUTH_PASS\n        );\n\n        if ($isNotAuthenticated) {\n            header('HTTP/1.1 401 Authorization Required');\n            header('WWW-Authenticate: Basic realm=\"Access Denied\"');\n            exit;\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Http/routes.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\n// pages\nRoute::get('/', 'PagesController@home')->name('meter_home');\nRoute::get('requests', 'PagesController@requests')->name('meter_requests');\nRoute::get('queries', 'PagesController@queries')->name('meter_queries');\nRoute::get('commands', 'PagesController@commands')->name('meter_commands');\nRoute::get('events', 'PagesController@events')->name('meter_events');\nRoute::get('schedules', 'PagesController@schedules')->name('meter_schedules');\nRoute::get('server_stats', 'PagesController@serverStats')->name('meter_server_stats');\n\n// tables\nRoute::get('requests_table', 'TablesController@requestsTable')->name('meter_requests_table');\nRoute::get('queries_table', 'TablesController@queriesTable')->name('meter_queries_table');\nRoute::get('commands_table', 'TablesController@commandsTable')->name('meter_commands_table');\nRoute::get('events_table', 'TablesController@eventsTable')->name('meter_events_table');\nRoute::get('schedules_table', 'TablesController@schedulesTable')->name('meter_schedules_table');\n"
  },
  {
    "path": "src/Meter.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Traits\\RegistersMonitors;\n\nclass Meter\n{\n    use RegistersMonitors;\n\n    /**\n     * Indicates if Meter should monitor entries.\n     *\n     * @var bool\n     */\n    public static $shouldMonitor = false;\n\n    /**\n     * Starts Meter.\n     *\n     * @param Application $app\n     */\n    public static function start($app)\n    {\n        if (!config('meter.enabled')) {\n            return;\n        }\n\n        if (static::runningApprovedArtisanCommand($app) || static::handlingApprovedRequest($app)) {\n            static::registerMonitors($app);\n            static::startMonitoring();\n        }\n    }\n\n    /**\n     * Determine if the application is running an approved command.\n     *\n     * @param $app\n     * @return bool\n     */\n    protected static function runningApprovedArtisanCommand($app): bool\n    {\n        $ignoredCommands = array_merge([\n            'migrate',\n            'migrate:rollback',\n            'migrate:fresh',\n            'migrate:refresh',\n            'migrate:reset',\n            'migrate:install',\n            'package:discover',\n            'queue:listen',\n            'queue:work',\n            'horizon',\n            'horizon:work',\n            'horizon:supervisor',\n        ], config('meter.ignore_commands', []));\n\n        return $app->runningInConsole() && !in_array($_SERVER['argv'][1] ?? null, $ignoredCommands, true);\n    }\n\n    /**\n     * Determine if the application is handling an approved request.\n     *\n     * @param $app\n     * @return bool\n     */\n    protected static function handlingApprovedRequest($app): bool\n    {\n        $ignoredPaths = array_merge([\n            config('meter.path') . '*',\n            'meter*',\n            'debugbar*',\n            '_debugbar*',\n            'clockwork*',\n            '_clockwork*',\n            'telescope*',\n            'vendor/meter*',\n            'horizon*',\n            'vendor/horizon*',\n            'nova-api*',\n        ], config('meter.ignore_paths', []));\n\n        return !$app->runningInConsole() && !$app['request']->is($ignoredPaths);\n    }\n\n    /**\n     * Start monitoring.\n     *\n     * @return void\n     */\n    public static function startMonitoring()\n    {\n        static::$shouldMonitor = true;\n    }\n\n    /**\n     * Stop monitoring.\n     *\n     * @return void\n     */\n    public static function stopMonitoring()\n    {\n        static::$shouldMonitor = false;\n    }\n\n    /**\n     * Determine if Meter is monitoring.\n     *\n     * @return bool\n     */\n    public static function isMonitoring(): bool\n    {\n        return static::$shouldMonitor;\n    }\n}\n"
  },
  {
    "path": "src/MeterServiceProvider.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter;\n\nuse Illuminate\\Routing\\Router;\nuse Illuminate\\Support\\Facades\\Route;\nuse Illuminate\\Support\\ServiceProvider;\nuse Sarfraznawaz2005\\Meter\\Console\\PruneCommand;\nuse Sarfraznawaz2005\\Meter\\Console\\PublishCommand;\nuse Sarfraznawaz2005\\Meter\\Console\\ServerMonitorCommand;\nuse Sarfraznawaz2005\\Meter\\Http\\Middleware\\BasicAuth;\n\nclass MeterServiceProvider extends ServiceProvider\n{\n    public function boot(Router $router)\n    {\n        if ($this->app->runningInConsole()) {\n            $this->publishes([__DIR__ . '/Config/config.php' => config_path('meter.php')], 'meter-config');\n            $this->publishes([__DIR__ . '/Migrations' => database_path('migrations')], 'meter-migration');\n            $this->publishes([__DIR__ . '/Resources/Views' => resource_path('views/vendor/meter')], 'meter-views');\n            $this->publishes([__DIR__ . '/Resources/Assets' => public_path('vendor/meter')], 'meter-assets');\n        }\n\n        if (!config('meter.enabled')) {\n            return;\n        }\n\n        $this->registerDbConnection();\n\n        Meter::start($this->app);\n\n        if (method_exists($router, 'aliasMiddleware')) {\n            $router->aliasMiddleware('auth.basic_meter', BasicAuth::class);\n        } else {\n            $router->middleware('auth.basic_meter', BasicAuth::class);\n        }\n\n        Route::middlewareGroup('meter', array_merge(config('meter.middleware', []), ['web', 'auth.basic_meter']));\n\n        $this->loadViewsFrom(__DIR__ . '/Resources/Views', 'meter');\n\n        $this->loadMigrationsFrom(__DIR__ . '/Migrations');\n\n        Route::group([\n            'domain' => config('meter.domain', null),\n            'namespace' => 'Sarfraznawaz2005\\Meter\\Http\\Controllers',\n            'prefix' => config('meter.path'),\n            'middleware' => 'meter',\n        ], function () {\n            $this->loadRoutesFrom(__DIR__ . '/Http/routes.php');\n        });\n    }\n\n    // see: https://github.com/sarfraznawaz2005/meter/issues/2\n    // see: https://github.com/laravel/framework/issues/25768\n    protected function registerDbConnection()\n    {\n        $defaultConnection = config('database.default');\n\n        config(['database.connections.meter' => config(\"database.connections.{$defaultConnection}\")]);\n    }\n\n    /**\n     * Register the application services.\n     */\n    public function register()\n    {\n        $this->mergeConfigFrom(__DIR__ . '/Config/config.php', 'meter');\n\n        $this->commands([\n            PruneCommand::class,\n            PublishCommand::class,\n            ServerMonitorCommand::class,\n        ]);\n\n        $this->app->singleton('meter', static function () {\n            return new Meter;\n        });\n    }\n}\n"
  },
  {
    "path": "src/Migrations/2019_12_12_100000_create_meter_entries_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateMeterEntriesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::connection(config('meter.storage.database.connection'))\n            ->create('meter_entries', static function (Blueprint $table) {\n                $table->bigIncrements('id');\n                $table->string('type', 20);\n                $table->enum('is_slow', ['No', 'Yes'])->default('No');\n                $table->longText('content');\n                $table->dateTime('created_at')->nullable();\n\n                $table->index(['type']);\n                $table->index(['created_at']);\n            });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('meter_entries');\n    }\n}\n"
  },
  {
    "path": "src/Models/MeterModel.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass MeterModel extends Model\n{\n    protected $connection = 'meter';\n\n    protected $table = 'meter_entries';\n\n    protected $fillable = ['type', 'is_slow', 'content'];\n\n    protected $casts = [\n        'content' => 'json',\n    ];\n\n    const UPDATED_AT = null;\n\n    function __construct()\n    {\n        $this->connection = config('meter.storage.database.connection');\n    }\n\n    /**\n     * Scope the query for the given type.\n     *\n     * @param Builder $query\n     * @param string $type\n     * @return Builder\n     */\n    public function scopeType($query, $type): Builder\n    {\n        return $query->where('type', $type);\n    }\n\n    /**\n     * Scope the query for the given filter.\n     *\n     * @param Builder $query\n     * @return Builder\n     */\n    public function scopeFiltered($query): Builder\n    {\n        if (request()->has('all')) {\n            $builder = $query;\n        } elseif (request()->has('days')) {\n            // not using \"WHERE DATE(created_at)\" since created_at is index column.\n            $date = now()->subDays(request()->days)->toDateString();\n            $builder = $query->whereRaw(\"created_at >= '$date 00:00:00'\");\n        } elseif (request()->has('slow')) {\n            $builder = $query->where('is_slow', 1);\n        } else {\n            // default today\n            $builder = $query->whereRaw(\"created_at >= '\" . now()->toDateString() . \" 00:00:00'\");\n        }\n\n        return $builder;\n    }\n}\n"
  },
  {
    "path": "src/Monitors/CommandMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Console\\Events\\CommandFinished;\nuse Illuminate\\Console\\Events\\CommandStarting;\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Type;\nuse function foo\\func;\n\nclass CommandMonitor extends Monitor\n{\n    protected $startTime = 0;\n\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return mixed\n     */\n    public function register($app)\n    {\n        $app->events->listen(CommandStarting::class, function () {\n            $this->startTime = microtime(true);\n        });\n\n        return $app->events->listen(CommandFinished::class, [$this, 'collect']);\n    }\n\n    /**\n     * Collect entry data and save in $data variable.\n     *\n     * @param CommandFinished $event\n     */\n    public function collect(CommandFinished $event)\n    {\n        if (!Meter::isMonitoring() || $this->shouldIgnore($event)) {\n            return;\n        }\n\n        $content = [\n            'time' => floor((microtime(true) - $this->startTime) * 1000),\n            'command' => $event->command ?? $event->input->getArguments()['command'] ?? 'default',\n            'exit_code' => $event->exitCode,\n            'arguments' => $event->input->getArguments(),\n            'options' => $event->input->getOptions(),\n        ];\n\n        $this->record(Type::COMMAND, false, $content);\n    }\n\n    /**\n     * Determine if the event should be ignored.\n     *\n     * @param mixed $event\n     * @return bool\n     */\n    private function shouldIgnore($event): bool\n    {\n        return in_array($event->command, array_merge($this->options['ignore'] ?? [], [\n            'schedule:run',\n            'schedule:finish',\n            'package:discover',\n            'meter:prune',\n            'meter:publish',\n            'meter:servermonitor',\n        ]), true);\n    }\n}\n"
  },
  {
    "path": "src/Monitors/CpuMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass CpuMonitor extends Monitor\n{\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return void\n     */\n    public function register($app)\n    {\n        try {\n\n            $cpuPercent = shell_exec(\"grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage}'\");\n\n            $this->record(Type::CPU, false, ['percent' => round($cpuPercent)]);\n\n        } catch (\\Exception $e) {\n        }\n    }\n}\n"
  },
  {
    "path": "src/Monitors/DiskSpaceMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass DiskSpaceMonitor extends Monitor\n{\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return void\n     */\n    public function register($app)\n    {\n        $totalSpace = disk_total_space(base_path());\n        $freeSpace = disk_free_space(base_path());\n        $usedSpace = $totalSpace - $freeSpace;\n\n        $percent = round(($usedSpace / $totalSpace) * 100);\n\n        $this->record(Type::DISK, false, ['percent' => $percent]);\n    }\n}\n"
  },
  {
    "path": "src/Monitors/EventMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast;\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Str;\nuse ReflectionClass;\nuse ReflectionFunction;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Traits\\FormatsClosure;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass EventMonitor extends Monitor\n{\n    use FormatsClosure;\n\n    protected $startTime = 0;\n\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return mixed\n     */\n    public function register($app)\n    {\n        $this->startTime = microtime(true);\n\n        return $app->events->listen('*', function ($eventName, $payload) {\n            $this->collect($eventName, $payload);\n        });\n    }\n\n    /**\n     * Collect entry data and save in $data variable.\n     *\n     * @param $eventName\n     * @param $payload\n     * @throws \\ReflectionException\n     */\n    public function collect($eventName, $payload)\n    {\n        if (!Meter::isMonitoring() || $this->shouldIgnore($eventName)) {\n            return;\n        }\n\n        $formattedPayload = $this->extractPayload($eventName, $payload);\n\n        $content = [\n            'time' => floor((microtime(true) - $this->startTime) * 1000),\n            'name' => $eventName,\n            'payload' => empty($formattedPayload) ? null : $formattedPayload,\n            'listeners' => $this->formatListeners($eventName),\n            'broadcast' => class_exists($eventName)\n                ? in_array(ShouldBroadcast::class, (array)class_implements($eventName), true)\n                : false,\n        ];\n\n        $this->record(Type::EVENT, false, $content);\n    }\n\n    /**\n     * Extract the payload and tags from the event.\n     *\n     * @param string $eventName\n     * @param array $payload\n     * @return array\n     * @throws \\ReflectionException\n     */\n    protected function extractPayload($eventName, $payload): array\n    {\n        if (is_object($payload[0]) && isset($payload[0]) && class_exists($eventName)) {\n            return $this->extractProperties($payload[0]);\n        }\n\n        return collect($payload)->map(static function ($value) {\n            return is_object($value) ? [\n                'class' => get_class($value),\n                'properties' => json_decode(json_encode($value), true),\n            ] : $value;\n        })->toArray();\n    }\n\n    /**\n     * Extract the properties for the given object in array form.\n     *\n     * The given array is ready for storage.\n     *\n     * @param mixed $target\n     * @return array\n     * @throws \\ReflectionException\n     */\n    protected function extractProperties($target): array\n    {\n        return collect((new ReflectionClass($target))->getProperties())\n            ->mapWithKeys(static function ($property) use ($target) {\n                $property->setAccessible(true);\n\n                if (($value = $property->getValue($target)) instanceof Model) {\n                    return [$property->getName() => meterFormatModel($value)];\n                }\n\n                if (is_object($value)) {\n                    return [\n                        $property->getName() => [\n                            'class' => get_class($value),\n                            'properties' => json_decode(json_encode($value), true),\n                        ],\n                    ];\n                }\n\n                return [$property->getName() => json_decode(json_encode($value), true)];\n            })->toArray();\n    }\n\n    /**\n     * Format list of event listeners.\n     *\n     * @param string $eventName\n     * @return array\n     */\n    protected function formatListeners($eventName): array\n    {\n        return collect(app('events')->getListeners($eventName))\n            ->map(function ($listener) {\n                $listener = (new ReflectionFunction($listener))->getStaticVariables()['listener'];\n\n                if (is_string($listener)) {\n                    return Str::contains($listener, '@') ? $listener : $listener . '@handle';\n                }\n\n                if (is_array($listener)) {\n                    return get_class($listener[0]) . '@' . $listener[1];\n                }\n\n                return $this->formatClosureListener($listener);\n\n            })->reject(static function ($listener) {\n                return Str::contains($listener, 'Laravel\\\\Telescope');\n            })->map(static function ($listener) {\n\n                if (Str::contains($listener, '@')) {\n                    $queued = in_array(ShouldQueue::class, class_implements(explode('@', $listener)[0]), true);\n                }\n\n                return [\n                    'name' => $listener,\n                    'queued' => $queued ?? false,\n                ];\n\n            })->values()->toArray();\n    }\n\n    /**\n     * Determine if the event should be ignored.\n     *\n     * @param string $eventName\n     * @return bool\n     */\n    protected function shouldIgnore($eventName): bool\n    {\n        return $this->eventIsIgnored($eventName) || $this->eventIsFiredByTheFramework($eventName);\n    }\n\n    /**\n     * Determine if the event was fired internally by Laravel.\n     *\n     * @param string $eventName\n     * @return bool\n     */\n    protected function eventIsFiredByTheFramework($eventName): bool\n    {\n        return Str::is(\n            ['Illuminate\\*', 'eloquent*', 'bootstrapped*', 'bootstrapping*', 'creating*', 'composing*'],\n            $eventName\n        );\n    }\n\n    /**\n     * Determine if the event is ignored manually.\n     *\n     * @param string $eventName\n     * @return bool\n     */\n    protected function eventIsIgnored($eventName): bool\n    {\n        return Str::is($this->options['ignore'] ?? [], $eventName);\n    }\n}\n"
  },
  {
    "path": "src/Monitors/HttpConnectionsMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass HttpConnectionsMonitor extends Monitor\n{\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return void\n     */\n    public function register($app)\n    {\n        try {\n\n            $port = config('meter.monitors.' . __CLASS__ . '.port', 80);\n\n            $connections = shell_exec(\"netstat -an | grep :$port 2>&1\");\n\n            if (trim($connections)) {\n                $count = count(array_filter(explode(\"\\n\", $connections)));\n            }\n\n            $this->record(Type::CONNECTIONS, false, ['count' => $count]);\n\n        } catch (\\Exception $e) {\n        }\n    }\n}\n"
  },
  {
    "path": "src/Monitors/MemoryMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass MemoryMonitor extends Monitor\n{\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return void\n     */\n    public function register($app)\n    {\n        try {\n            if (stripos(PHP_OS, 'win') !== 0 && stripos(PHP_OS, 'mac') !== 0) {\n                $free = shell_exec('free');\n                $free = (string)trim($free);\n                $freeArr = explode(\"\\n\", $free);\n                $mem = explode(' ', $freeArr[1]);\n                $mem = array_filter($mem);\n                $mem = array_merge($mem);\n                $percent = round($mem[2] / $mem[1] * 100);\n\n                $this->record(Type::MEMORY, false, ['percent' => $percent]);\n            }\n        } catch (\\Exception $e) {\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Monitors/Monitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\n\nabstract class Monitor\n{\n    /**\n     * The configured monitor options.\n     *\n     * @var array\n     */\n    public $options = [];\n\n    /**\n     * The meter model.\n     *\n     * @var null|object\n     */\n    protected $model = null;\n\n    /**\n     * Create a new monitor instance.\n     *\n     * @param array $options\n     * @return void\n     */\n    public function __construct(array $options = [])\n    {\n        $this->options = $options;\n\n        $this->model = new MeterModel();\n    }\n\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return void\n     */\n    abstract public function register($app);\n\n    /**\n     * Saves collected data in DB.\n     *\n     * @param string $type\n     * @param boolean $isSlow\n     * @param array $content\n     * @return mixed\n     */\n    public function record($type, $isSlow, array $content)\n    {\n        Meter::stopMonitoring();\n\n        $result = true;\n        $skip = false;\n\n        if (count(config('meter.ignore_matched_string', [])) > 0) {\n\n            foreach (config('meter.ignore_matched_string', []) as $queryType) {\n\n                if (!is_array($queryType)) {\n                    continue;\n                }\n\n                if(count($queryType) == 0) {\n                    continue;\n                }\n\n                foreach ($queryType as $string) {\n                    if (in_array($string, $content)) {\n                        $skip = true;\n                        break;\n                    }\n                }\n            }\n\n        }\n\n        if ($skip === false) {\n\n            $result = $this->model->create([\n                'type' => $type,\n                'is_slow' => $isSlow ? '1' : '0',\n                'content' => $content,\n                'created_at' => now(),\n            ]);\n        }\n\n        Meter::startMonitoring();\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "src/Monitors/QueryMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Illuminate\\Database\\Events\\QueryExecuted;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Traits\\FetchesStackTrace;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass QueryMonitor extends Monitor\n{\n    use FetchesStackTrace;\n\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return mixed\n     */\n    public function register($app)\n    {\n        return $app->events->listen(QueryExecuted::class, [$this, 'collect']);\n    }\n\n    /**\n     * Collect entry data and save in $data variable.\n     *\n     * @param QueryExecuted $event\n     */\n    public function collect(QueryExecuted $event)\n    {\n        if (!Meter::isMonitoring()) {\n            return;\n        }\n\n        $time = $event->time;\n\n        $isSlow = isset($this->options['slow']) && $time >= $this->options['slow'];\n\n        $caller = $this->getCallerFromStackTrace();\n\n        $content = [\n            'connection' => $event->connectionName,\n            'sql' => $this->replaceBindings($event),\n            'time' => number_format($time, 2),\n            'file' => $caller['file'],\n            'line' => $caller['line'],\n        ];\n\n        $this->record(Type::QUERY, $isSlow, $content);\n    }\n\n    /**\n     * Replace the placeholders with the actual bindings.\n     *\n     * @param QueryExecuted $event\n     * @return string\n     */\n    public function replaceBindings($event): string\n    {\n        $sql = $event->sql;\n\n        foreach ($this->formatBindings($event) as $key => $binding) {\n            $regex = is_numeric($key)\n                ? \"/\\?(?=(?:[^'\\\\\\']*'[^'\\\\\\']*')*[^'\\\\\\']*$)/\"\n                : \"/:{$key}(?=(?:[^'\\\\\\']*'[^'\\\\\\']*')*[^'\\\\\\']*$)/\";\n\n            if ($binding === null) {\n                $binding = 'null';\n            } elseif (!is_int($binding) && !is_float($binding)) {\n                $binding = $event->connection->getPdo()->quote($binding);\n            }\n\n            $sql = preg_replace($regex, $binding, $sql, 1);\n        }\n\n        return $sql;\n    }\n\n    /**\n     * Format the given bindings to strings.\n     *\n     * @param QueryExecuted $event\n     * @return array\n     */\n    protected function formatBindings($event): array\n    {\n        return $event->connection->prepareBindings($event->bindings);\n    }\n}\n"
  },
  {
    "path": "src/Monitors/RequestMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Illuminate\\Foundation\\Http\\Events\\RequestHandled;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass RequestMonitor extends Monitor\n{\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return mixed\n     */\n    public function register($app)\n    {\n        return $app->events->listen(RequestHandled::class, [$this, 'collect']);\n    }\n\n    /**\n     * Collect entry data and save in $data variable.\n     *\n     * @param RequestHandled $event\n     */\n    public function collect(RequestHandled $event)\n    {\n        if (!Meter::isMonitoring()) {\n            return;\n        }\n\n        $isSlow = false;\n\n        $startTime = defined('LARAVEL_START') ? LARAVEL_START : $event->request->server('REQUEST_TIME_FLOAT');\n        $duration = $startTime ? floor((microtime(true) - $startTime) * 1000) : null;\n\n        if (isset($this->options['slow']) && $duration) {\n            $isSlow = $duration >= $this->options['slow'];\n        }\n\n        $content = [\n            'uri' => str_replace($event->request->root(), '', $event->request->fullUrl()) ?: '/',\n            'method' => $event->request->method(),\n            'controller_action' => optional($event->request->route())->getActionName(),\n            'middleware' => array_values(optional($event->request->route())->gatherMiddleware() ?? []),\n            'response_status' => $event->response->getStatusCode(),\n            'duration' => $duration,\n            'memory' => round(memory_get_peak_usage(true) / 1024 / 1025, 1),\n            'ip' => $event->request->ip(),\n        ];\n\n        $this->record(Type::REQUEST, $isSlow, $content);\n    }\n}\n"
  },
  {
    "path": "src/Monitors/ScheduleMonitor.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Monitors;\n\nuse Cron\\CronExpression;\nuse Illuminate\\Console\\Events\\CommandStarting;\nuse Illuminate\\Console\\Scheduling\\CallbackEvent;\nuse Illuminate\\Console\\Scheduling\\Event;\nuse Illuminate\\Console\\Scheduling\\Schedule;\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Meter;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass ScheduleMonitor extends Monitor\n{\n    protected $startTime = 0;\n\n    /**\n     * Listens to event(s) and performs actions.\n     *\n     * @param Application $app\n     * @return mixed\n     */\n    public function register($app)\n    {\n        return $app->events->listen(CommandStarting::class, [$this, 'collect']);\n    }\n\n    /**\n     * Collect entry data and save in $data variable.\n     *\n     * @param CommandStarting $event\n     */\n    public function collect(CommandStarting $event)\n    {\n        if (($event->command !== 'schedule:run' && $event->command !== 'schedule:finish') || !Meter::isMonitoring()) {\n            return;\n        }\n\n        $this->startTime = microtime(true);\n\n        collect(app(Schedule::class)->events())->each(function ($event) {\n            $event->then(function () use ($event) {\n\n                $expression = CronExpression::factory($event->expression);\n\n                $content = [\n                    'time' => floor((microtime(true) - $this->startTime) * 1000),\n                    'command' => $event instanceof CallbackEvent ? 'Closure' : $this->fixupCommand($event->command),\n                    'description' => $event->description,\n                    'expression' => $event->expression,\n                    'timezone' => $event->timezone,\n                    'user' => $event->user,\n                    'output' => $this->getEventOutput($event),\n                    'next_run' => $expression->getNextRunDate(),\n                ];\n\n                $this->record(Type::SCHEDULE, false, $content);\n            });\n        });\n    }\n\n    /**\n     * Get the output for the scheduled event.\n     *\n     * @param Event $event\n     * @return string|null\n     */\n    protected function getEventOutput(Event $event)\n    {\n        if ($event->shouldAppendOutput || !$event->output || $event->output === $event->getDefaultOutput() || !file_exists($event->output)) {\n            return '';\n        }\n\n        return trim(file_get_contents($event->output));\n    }\n\n    /**\n     * Removes PHP path from command name.\n     *\n     * @param $command\n     * @return string\n     */\n    protected function fixupCommand($command)\n    {\n        $parts = explode(' ', $command);\n\n        if (count($parts) > 2 && ($parts[1] === \"'artisan'\" || $parts[1] === '\"artisan\"')) {\n            array_shift($parts);\n        }\n\n        $command = implode(' ', $parts);\n\n        return trim(str_ireplace([\"'artisan'\", '\"artisan\"'], '', $command));\n    }\n}\n"
  },
  {
    "path": "src/Resources/Assets/meter.css",
    "content": "body, .wrapper {\n    font-family: Nunito !important;\n    background: #edf1f3;\n    color: #333;\n    font-size: .95rem;\n    border-radius: unset !important;\n}\n\n.wrapper {\n    margin-top: 4rem;\n}\n\n.logo {\n    font-size: 25px;\n}\n\n.card-body {\n    padding: 1.5rem 0.50rem 0.50rem 0.50rem;\n}\n\n.table td {\n    vertical-align: middle !important;\n    font-size: .90rem;\n}\n\n.navbar-nav .nav-item {\n    margin-left: 5px;\n}\n\n.nav-tabs .nav-link {\n    border: none;\n}\n\n.nav-item a {\n    font-size: .95rem;\n}\n\n.table thead {\n    background: #DAE0E5;\n    color: #666;\n    font-size: .90rem;\n}\n\n.table th:last-child {\n    text-align: center;\n}\n\n.card {\n    border: none;\n}\n\n.navbar-toggler {\n    width: 47px;\n    height: 34px;\n    background-color: #d3d3d3;\n    border: none;\n    outline: none;\n}\n\n.navbar-toggler .line {\n    width: 100%;\n    float: left;\n    height: 2px;\n    background-color: #999;\n    outline: none;\n    margin-bottom: 5px;\n}\n\ntable {\n    table-layout: fixed;\n    word-wrap: break-word;\n}\n\ntable.dataTable {\n    border-collapse: collapse !important;\n}\n\n.table-bordered td, .table-bordered th {\n    border: none;\n    border-bottom: 1px solid #eee !important;\n}\n\n.table td, .table th {\n    padding: .50rem;\n}\n\n.badge {\n    font-size: .90rem;\n    min-width: 40px;\n    color: #212529;\n}\n\n.badge-primary {\n    background-color: #8ebef2;\n}\n\n.badge-secondary {\n    background-color: #DAE0E5;\n}\n\n.badge-info {\n    background-color: #c4e7ed;\n}\n\n.badge-success {\n    background-color: #a2e5b1;\n}\n\n.badge-warning {\n    background-color: #FFF382;\n}\n\n.badge-danger {\n    background-color: #f4bcc1;\n}\n\n.dataTables_wrapper .dataTables_processing {\n    background-color: #a2e5b1;\n    color: #212529;\n    position: absolute !important;\n    top: 1% !important;\n}\n\n.table-hover tbody tr {\n    background-color: #fff !important;\n}\n\n.table-hover tbody tr:hover {\n    background-color: #edf1f3 !important;\n}\n\n.icon {\n    color: #666;\n    font-size: 1.2rem;\n}\n\n.icon:hover {\n    color: #000;\n    font-size: 1.2rem;\n}\n\n.modal-dialog {\n    position: relative;\n    display: table;\n    overflow-y: auto;\n    overflow-x: auto;\n    width: auto;\n    min-width: 300px;\n}\n\n.nav.nav-tabs {\n    padding-bottom: 2px;\n    border: none;\n}\n\n.tab-content, .main {\n    border-radius: 10px;\n    margin: 0 10px 50px 10px;\n}\n\n.section {\n    border-radius: 10px;\n    margin: 0 20px 25px 20px;\n    background: #fff;\n    padding: 1.5rem 0.5rem;\n    box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.02),\n    0 6.7px 5.3px rgba(0, 0, 0, 0.028),\n    0 12.5px 10px rgba(0, 0, 0, 0.035),\n    0 22.3px 17.9px rgba(0, 0, 0, 0.042),\n    0 41.8px 33.4px rgba(0, 0, 0, 0.05),\n    0 100px 80px rgba(0, 0, 0, 0.07);\n}\n\n.shadow {\n    box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.02),\n    0 6.7px 5.3px rgba(0, 0, 0, 0.028),\n    0 12.5px 10px rgba(0, 0, 0, 0.035),\n    0 22.3px 17.9px rgba(0, 0, 0, 0.042),\n    0 41.8px 33.4px rgba(0, 0, 0, 0.05),\n    0 100px 80px rgba(0, 0, 0, 0.07);\n}\n\n.meter_sql {\n    font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n    color: #c7254e;\n}\n\n.meter_sql .sql_keyword {\n    color: #2953e1;\n    text-transform: uppercase;\n}\n\n#detailsModal pre {\n    font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n    background: #eee;\n    padding: 10px;\n    border-radius: 5px;\n    font-weight: bold;\n}\n\npre.json .json_keyword {\n    color: #c7254e;\n}\n\npre.json .json_keyword_braces {\n    color: #2953e1;\n}\n\na.nav-link, a.nav-link:active, a.nav-link:visited {\n    color: #2953e1;\n}\n\na.nav-link:hover {\n    color: #ff1493;\n}\n\ndiv.table-responsive-sm {\n    background: #EDF1F3;\n    padding: 20px 5px;\n    border-radius: 10px;\n    margin: 10px;\n}\n\n.totals a {\n    text-decoration: none;\n}\n"
  },
  {
    "path": "src/Resources/Assets/meter.js",
    "content": "$(document).ready(function () {\n\n    meterSetup();\n\n    $('.dataTable').on('draw.dt', meterSetup);\n\n    // details modal\n    $(document).on('click', '.btnDetails', function () {\n        var details = '<table cellpadding=\"5\" style=\"font-size: .85rem;\">';\n        var detailsObject = $(this).data('details');\n        var $modal = $('#detailsModal');\n\n        for (var key in detailsObject) {\n            if (detailsObject.hasOwnProperty(key) && key !== 'Details') {\n                details += '<tr><td width=\"100\"><strong>' + key + '</strong></td><td>' + detailsObject[key] + '</td></tr>';\n            }\n        }\n\n        details += '</table>';\n\n        $modal.find('.modal-body').html(details);\n        $modal.modal('show');\n\n        return false;\n    });\n\n    $('#detailsModal').on('shown.bs.modal', function () {\n        meterHighlightSQL();\n        meterHighlightJson();\n    });\n});\n\nfunction meterSetup() {\n    $('[data-toggle=\"popover\"]').popover({\n        html: true,\n        placement: 'top',\n        trigger: 'hover'\n    });\n\n    $('[data-toggle=\"tooltip\"]').tooltip();\n\n    meterHighlightSQL();\n}\n\n// creates DataTables\nfunction meterTable(tableSelector, url, length, columns, extraOptions, data) {\n\n    length = length || 10;\n    extraOptions = extraOptions || {};\n    data = data || {};\n\n    var options = {\n        \"serverSide\": true,\n        \"processing\": true,\n        \"responsive\": true,\n        \"autoWidth\": false,\n        \"ordering\": false,\n        \"lengthChange\": false,\n        \"pageLength\": length,\n        \"ajax\": {\n            \"url\": url,\n            \"dataType\": \"json\",\n            \"type\": \"GET\",\n            \"data\": data\n        },\n        \"columns\": columns\n    };\n\n    // merge\n    options = $.extend({}, options, extraOptions);\n\n    return $(tableSelector).DataTable(options);\n}\n\n// highlights SQL keywords\nfunction meterHighlightSQL() {\n    var sqlReg = /\\b(AND|AS|ASC|BETWEEN|BY|CASE|CURRENT_DATE|CURRENT_TIME|DELETE|DESC|DISTINCT|EACH|ELSE|ELSEIF|FALSE|FOR|FROM|GROUP|HAVING|IF|IN|INSERT|INTERVAL|INTO|IS|JOIN|KEY|KEYS|LEFT|LIKE|LIMIT|MATCH|NOT|NULL|ON|OPTION|OR|ORDER|OUT|OUTER|REPLACE|RIGHT|SELECT|SET|TABLE|THEN|TO|TRUE|UPDATE|VALUES|WHEN|WHERE|CREATE|ALTER|ALL|DATABASE|GRANT|PRIVILEGES|IDENTIFIED|FLUSH|INNER|COUNT)(?=[^\\w])/ig;\n\n    document.querySelectorAll(\"td .meter_sql\").forEach(function(item) {\n        item.innerHTML = item.innerHTML.replace(sqlReg,'<span class=\"sql_keyword\">$1</span>');\n    });\n}\n\n// highlights JSON keywords\nfunction meterHighlightJson() {\n    var reg = /(.+?(?=: ))/g;\n\n    document.querySelectorAll(\"td pre.json\").forEach(function(item) {\n        item.innerHTML = item.innerHTML.replace(/({|}|\\[|\\])/g,'<span class=\"json_keyword_braces\">$1</span>');\n        item.innerHTML = item.innerHTML.replace(reg,'<span class=\"json_keyword\">$1</span>');\n    });\n}\n"
  },
  {
    "path": "src/Resources/Views/commands.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <ul class=\"nav nav-tabs justify-content-center\">\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link active\" data-toggle=\"tab\" href=\"#graph\">\n                <i class=\"fa fa-bar-chart\"></i> Graph\n            </a>\n        </li>\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link\" data-toggle=\"tab\" href=\"#index\">\n                <i class=\"fa fa-table\"></i> Commands\n            </a>\n        </li>\n    </ul>\n\n    <div class=\"tab-content\">\n\n        <div class=\"tab-pane fade show active\" role=\"tabpanel\" id=\"graph\">\n            @component('meter::components.chart', ['chart' => $chart, 'title' => 'Command Times'])@endcomponent\n        </div>\n\n        <div class=\"tab-pane fade\" role=\"tabpanel\" id=\"index\">\n            @component('meter::components.table',[\n                'url' => route('meter_commands_table'),\n                'columns' => ['Happened', 'Command', 'Time', 'Exit Code', 'More']\n            ])\n            @endcomponent\n        </div>\n    </div>\n\n@endsection\n\n"
  },
  {
    "path": "src/Resources/Views/components/chart.blade.php",
    "content": "<div class=\"section\">\n    @if (isset($title))\n        <div class=\"text-center text-primary\"><strong>{{$title}}</strong></div>\n    @endif\n\n    <div>{!! $chart->container() !!}</div>\n</div>\n\n@push('js')\n    {!! $chart->script() !!}\n@endpush\n"
  },
  {
    "path": "src/Resources/Views/components/table.blade.php",
    "content": "<div class=\"section\">\n    <table class=\"table-responsive-sm meter_table table table-hover mx-auto w-100\">\n        <thead>\n        <tr>\n            @foreach($columns as $column)\n                <th>{{$column}}</th>\n            @endforeach\n        </tr>\n        </thead>\n    </table>\n</div>\n\n@push('js')\n    <script>\n        meterTable('.table', '{{ $url }}', 25, [\n            @foreach($columns as $column)\n                {data: '{{$column}}'},\n            @endforeach\n        ], {\n            \"columnDefs\": [\n                @if (isset($columnDefs))\n                    @foreach($columnDefs as $columnDef)\n                        {!! $columnDef !!},\n                    @endforeach\n                @else\n                    {\"width\": \"10%\", \"targets\": -1}\n                @endif\n            ]\n        }, {\n            {{request()->has('days') ? 'days : ' . request()->days : ''}}\n            {{request()->has('slow') ? 'slow : 1' : ''}}\n            {{request()->has('all') ? 'all : 1' : ''}}\n        });\n    </script>\n@endpush\n"
  },
  {
    "path": "src/Resources/Views/dashboard.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <div class=\"section p-0\">\n        <div class=\"shadow card-group totals\">\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor::class . '.enabled', true))\n                <div class=\"card text-center text-white bg-primary border-primary\">\n                    <a href=\"{{route('meter_requests')}}\" class=\"text-white\">\n                        <div class=\"card-header\">\n                            <span class=\"h5\"><i class=\"fa fa-random\"></i> Requests</span>\n                        </div>\n                        <div class=\"card-body p-3\">\n                            <strong class=\"h1\">{{$totals->requests}}</strong>\n                        </div>\n                    </a>\n                </div>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor::class . '.enabled', true))\n                <div class=\"card text-center text-white bg-success border-success\">\n                    <a href=\"{{route('meter_queries')}}\" class=\"text-white\">\n                        <div class=\"card-header\">\n                            <span class=\"h5\"><i class=\"fa fa-database\"></i> Queries</span>\n                        </div>\n                        <div class=\"card-body p-3\">\n                            <strong class=\"h1\">{{$totals->queries}}</strong>\n                        </div>\n                    </a>\n                </div>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor::class . '.enabled', true))\n                <div class=\"card text-center text-white bg-info border-info\">\n                    <a href=\"{{route('meter_commands')}}\" class=\"text-white\">\n                        <div class=\"card-header\">\n                            <span class=\"h5\"><i class=\"fa fa-terminal\"></i> Commands</span>\n                        </div>\n                        <div class=\"card-body p-3\">\n                            <strong class=\"h1\">{{$totals->commands}}</strong>\n                        </div>\n                    </a>\n                </div>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor::class . '.enabled', true))\n                <div class=\"card text-center text-white bg-warning border-warning\">\n                    <a href=\"{{route('meter_events')}}\" class=\"text-white\">\n                        <div class=\"card-header\">\n                            <span class=\"h5\"><i class=\"fa fa-clock-o\"></i> Events</span>\n                        </div>\n                        <div class=\"card-body p-3\">\n                            <strong class=\"h1\">{{$totals->events}}</strong>\n                        </div>\n                    </a>\n                </div>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor::class . '.enabled', true))\n                <div class=\"card text-center text-white bg-danger border-danger\">\n                    <a href=\"{{route('meter_schedules')}}\" class=\"text-white\">\n                        <div class=\"card-header\">\n                            <span class=\"h5\"><i class=\"fa fa-calendar\"></i> Schedule</span>\n                        </div>\n                        <div class=\"card-body p-3\">\n                            <strong class=\"h1\">{{$totals->schedules}}</strong>\n                        </div>\n                    </a>\n                </div>\n            @endif\n\n        </div>\n    </div>\n\n    <div class=\"d-flex flex-wrap w-100\">\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $requestTimeChart, 'title' => 'Response Times'])@endcomponent\n            </div>\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $requestMemoryChart, 'title' => 'Request Memory Usage'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $queriesTimeChart, 'title' => 'Query Times'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $commandsTimeChart, 'title' => 'Command Times'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $eventsTimeChart, 'title' => 'Event Times'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $schedulesTimeChart, 'title' => 'Schedule Times'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $cpuChart, 'title' => 'Server CPU Usage'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $diskSpaceChart, 'title' => 'Server Disk Space Usage'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $serverMemoryChart, 'title' => 'Server Memory Usage'])@endcomponent\n            </div>\n        @endif\n\n        @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor::class . '.enabled', true) &&\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor::class . '.show_on_dashboard', true)\n        )\n            <div class=\"col-md-6 col-lg-6 col-sm-12 p-0 border-0\">\n                @component('meter::components.chart', ['chart' => $connectionsChart, 'title' => 'Server HTTP Connections Count'])@endcomponent\n            </div>\n        @endif\n\n    </div>\n\n@endsection\n"
  },
  {
    "path": "src/Resources/Views/events.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <ul class=\"nav nav-tabs justify-content-center\">\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link active\" data-toggle=\"tab\" href=\"#graph\">\n                <i class=\"fa fa-bar-chart\"></i> Graph\n            </a>\n        </li>\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link\" data-toggle=\"tab\" href=\"#index\">\n                <i class=\"fa fa-table\"></i> Events\n            </a>\n        </li>\n    </ul>\n\n    <div class=\"tab-content\">\n\n        <div class=\"tab-pane fade show active\" role=\"tabpanel\" id=\"graph\">\n            @component('meter::components.chart', ['chart' => $chart, 'title' => 'Event Times'])@endcomponent\n        </div>\n\n        <div class=\"tab-pane fade\" role=\"tabpanel\" id=\"index\">\n            @component('meter::components.table',[\n                'url' => route('meter_events_table'),\n                'columns' => ['Happened', 'Event', 'Time', 'Listeners', 'More']\n            ])\n            @endcomponent\n        </div>\n    </div>\n\n@endsection\n\n"
  },
  {
    "path": "src/Resources/Views/layout/filters.blade.php",
    "content": "<a\n    class=\"dropdown-item btnfilter {{(request()->has('days') || request()->has('slow') || request()->has('all')) ? '' : 'active'}}\"\n    href=\"{{route($route)}}\">\n    Today\n</a>\n\n@foreach(config('meter.filters', []) as $name => $days)\n    <a\n        class=\"dropdown-item btnfilter {{(request()->has('days') && request()->days == $days) ? 'active' : ''}}\"\n        href=\"{{route($route, ['days' => $days])}}\"\n    >\n        {{$name}}\n    </a>\n@endforeach\n\n<a\n    class=\"dropdown-item btnfilter {{request()->has('all') ? 'active' : ''}}\"\n    href=\"{{route($route, ['all' => 1])}}\">\n    All\n</a>\n\n@push('js')\n    <script>\n        document.addEventListener('DOMContentLoaded', function () {\n            document.querySelector('.filter_name').innerHTML = document.querySelector('.dropdown-item.btnfilter.active').innerHTML;\n        });\n    </script>\n@endpush\n\n"
  },
  {
    "path": "src/Resources/Views/layout/layout.blade.php",
    "content": "<!doctype html>\n<html lang=\"{{ app()->getLocale() }}\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"author\" content=\"Sarfraz Ahmed (sarfraznawaz2005@gmail.com)\">\n\n    <title>Meter</title>\n\n    <link href=\"https://fonts.googleapis.com/css?family=Nunito\" rel=\"stylesheet\">\n    <link href=\"https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css\" rel=\"stylesheet\">\n\n    <link rel=\"stylesheet\" href=\"{{ asset('vendor/meter/bootstrap/bootstrap.min.css') }}\">\n    <link rel=\"stylesheet\" href=\"{{ asset('vendor/meter/datatable/dataTables.bootstrap4.min.css') }}\">\n    <link rel=\"stylesheet\" href=\"{{ asset('vendor/meter/meter.css') }}\">\n\n    @stack('css')\n</head>\n<body>\n\n@include('meter::layout.links')\n\n<div class=\"card wrapper\">\n    <div class=\"card-body\">\n        @yield('content')\n    </div>\n</div>\n\n@include('meter::layout.modal')\n\n<script src=\"{{ asset('vendor/meter/jquery.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/bootstrap/popper.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/bootstrap/bootstrap.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/datatable/jquery.dataTables.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/datatable/dataTables.bootstrap4.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/moment.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/Chart.min.js') }}\"></script>\n<script src=\"{{ asset('vendor/meter/meter.js') }}\"></script>\n\n@stack('js')\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/Views/layout/links.blade.php",
    "content": "<nav class=\"navbar fixed-top navbar-expand-lg navbar-light bg-light\">\n\n    <span class=\"navbar-brand\">\n        <strong class=\"logo fa fa-dashboard\"></strong>\n        <strong>Meter</strong>\n    </span>\n\n    <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#collapsibleNavbar\">\n        <span class=\"line\"></span>\n        <span class=\"line\"></span>\n        <span class=\"line\" style=\"margin-bottom: 0;\"></span>\n    </button>\n\n    <div class=\"collapse navbar-collapse\" id=\"collapsibleNavbar\">\n        <ul class=\"navbar-nav w-100\">\n\n            <li class=\"nav-item\">\n                <a\n                    class=\"btn btn-light {{meterActiveLink('meter_home') ? 'active' : ''}}\"\n                    href=\"{{route('meter_home')}}\">\n                    Dashboard\n                </a>\n            </li>\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\RequestMonitor::class . '.enabled', true))\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_requests') ? 'active' : ''}}\"\n                        href=\"{{route('meter_requests')}}\">\n                        Requests\n                    </a>\n                </li>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\QueryMonitor::class . '.enabled', true))\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_queries') ? 'active' : ''}}\"\n                        href=\"{{route('meter_queries')}}\">\n                        Queries\n                    </a>\n                </li>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CommandMonitor::class . '.enabled', true))\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_commands') ? 'active' : ''}}\"\n                        href=\"{{route('meter_commands')}}\">\n                        Commands\n                    </a>\n                </li>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\EventMonitor::class . '.enabled', true))\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_events') ? 'active' : ''}}\"\n                        href=\"{{route('meter_events')}}\">\n                        Events\n                    </a>\n                </li>\n            @endif\n\n            @if (config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\ScheduleMonitor::class . '.enabled', true))\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_schedules') ? 'active' : ''}}\"\n                        href=\"{{route('meter_schedules')}}\">\n                        Schedule\n                    </a>\n                </li>\n            @endif\n\n            @if (\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\CpuMonitor::class . '.enabled', true) ||\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\DiskSpaceMonitor::class . '.enabled', true) ||\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\MemoryMonitor::class . '.enabled', true) ||\n            config('meter.monitors.' . Sarfraznawaz2005\\Meter\\Monitors\\HttpConnectionsMonitor::class . '.enabled', true)\n            )\n                <li class=\"nav-item\">\n                    <a\n                        class=\"btn btn-light {{meterActiveLink('meter_server_stats') ? 'active' : ''}}\"\n                        href=\"{{route('meter_server_stats')}}\">\n                        Server\n                    </a>\n                </li>\n            @endif\n\n            <li class=\"nav-item dropdown ml-auto\">\n                <a class=\"nav-link dropdown-toggle filter_name\" href=\"#\" data-toggle=\"dropdown\">Today </a>\n                <div class=\"dropdown-menu dropdown-menu-right\">\n                    @include('meter::layout.filters', ['route' => request()->route()->getName()])\n                </div>\n            </li>\n\n        </ul>\n    </div>\n</nav>\n"
  },
  {
    "path": "src/Resources/Views/layout/modal.blade.php",
    "content": "<div class=\"modal\" id=\"detailsModal\">\n    <div class=\"modal-dialog modal-dialog-scrollable\">\n        <div class=\"modal-content\">\n            <div class=\"modal-body\"></div>\n\n            <div class=\"modal-footer\" style=\"padding: 5px;\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "src/Resources/Views/queries.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <ul class=\"nav nav-tabs justify-content-center\">\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link active\" data-toggle=\"tab\" href=\"#graph\">\n                <i class=\"fa fa-bar-chart\"></i> Graph\n            </a>\n        </li>\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link\" data-toggle=\"tab\" href=\"#index\">\n                <i class=\"fa fa-table\"></i> Queries\n            </a>\n        </li>\n    </ul>\n\n    <div class=\"tab-content\">\n\n        <div class=\"tab-pane fade show active\" role=\"tabpanel\" id=\"graph\">\n            @component('meter::components.chart', ['chart' => $queriesTimeChart, 'title' => 'Query Times'])@endcomponent\n        </div>\n\n        <div class=\"tab-pane fade\" role=\"tabpanel\" id=\"index\">\n            @component('meter::components.table',[\n                'url' => route('meter_queries_table'),\n                'columns' => ['Happened', 'Query', 'Time', 'Slow', 'More'],\n                'columnDefs' => ['{\"width\": \"10%\", \"targets\": 0}', '{\"width\": \"5%\", \"targets\": -1}', '{\"width\": \"10%\", \"targets\": -2}', '{\"width\": \"10%\", \"targets\": -3}']\n            ])\n            @endcomponent\n        </div>\n    </div>\n\n@endsection\n"
  },
  {
    "path": "src/Resources/Views/requests.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <ul class=\"nav nav-tabs justify-content-center\">\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link active\" data-toggle=\"tab\" href=\"#graph\">\n                <i class=\"fa fa-bar-chart\"></i> Graph\n            </a>\n        </li>\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link\" data-toggle=\"tab\" href=\"#index\">\n                <i class=\"fa fa-table\"></i> Requests\n            </a>\n        </li>\n    </ul>\n\n    <div class=\"tab-content\">\n        <div class=\"tab-pane fade show active\" role=\"tabpanel\" id=\"graph\">\n            @component('meter::components.chart', ['chart' => $timeChart, 'title' => 'Response Times'])@endcomponent\n            @component('meter::components.chart', ['chart' => $memoryChart, 'title' => 'Memory Usage'])@endcomponent\n        </div>\n\n        <div class=\"tab-pane fade\" role=\"tabpanel\" id=\"index\">\n            @component('meter::components.table',[\n                'url' => route('meter_requests_table'),\n                'columns' => ['Happened', 'Verb', 'Path', 'Status', 'Time', 'Memory', 'Slow', 'More'],\n            ])\n            @endcomponent\n        </div>\n    </div>\n\n@endsection\n"
  },
  {
    "path": "src/Resources/Views/schedules.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n\n    <ul class=\"nav nav-tabs justify-content-center\">\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link active\" data-toggle=\"tab\" href=\"#graph\">\n                <i class=\"fa fa-bar-chart\"></i> Graph\n            </a>\n        </li>\n        <li class=\"nav-item\">\n            <a class=\"nav-item nav-link\" data-toggle=\"tab\" href=\"#index\">\n                <i class=\"fa fa-table\"></i> Schedules\n            </a>\n        </li>\n    </ul>\n\n    <div class=\"tab-content\">\n        <div class=\"tab-pane fade show active\" role=\"tabpanel\" id=\"graph\">\n            @component('meter::components.chart', ['chart' => $chart, 'title' => 'Schedule Times'])@endcomponent\n        </div>\n\n        <div class=\"tab-pane fade\" role=\"tabpanel\" id=\"index\">\n            @component('meter::components.table',[\n                'url' => route('meter_schedules_table'),\n                'columns' => ['Happened', 'Command', 'Expression', 'Time', 'More']\n            ])\n            @endcomponent\n        </div>\n    </div>\n\n@endsection\n"
  },
  {
    "path": "src/Resources/Views/server.blade.php",
    "content": "@extends('meter::layout.layout')\n\n@section('content')\n    @component('meter::components.chart', ['chart' => $cpuChart, 'title' => 'Server CPU Usage'])@endcomponent\n    @component('meter::components.chart', ['chart' => $diskSpaceChart, 'title' => 'Server Disk Space Usage'])@endcomponent\n    @component('meter::components.chart', ['chart' => $serverMemoryChart, 'title' => 'Server Memory Usage'])@endcomponent\n    @component('meter::components.chart', ['chart' => $connectionsChart, 'title' => 'Server HTTP Connections Count'])@endcomponent\n@endsection\n\n"
  },
  {
    "path": "src/Tables/CommandsTable.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass CommandsTable extends Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    public function columns(): array\n    {\n        return [\n            'is_slow',\n            'content',\n            'created_at',\n        ];\n    }\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    public function searchColumns(): array\n    {\n        return $this->columns();\n    }\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return (new MeterModel)->type(Type::COMMAND)->filtered()->orderBy('id', 'desc');\n    }\n\n    /**\n     * Transform data as we need.\n     *\n     * @param array $rows\n     * @return array\n     */\n    public function transform(array $rows): array\n    {\n        $transformed = [];\n\n        foreach ($rows as $row) {\n            $data['Happened'] = meterWithHtmlTitle(Carbon::parse($row['created_at'])->diffForHumans(), $row['created_at']);\n\n            $data['Command'] = $row['content']['command'];\n            $data['Time'] = $row['content']['time'] . ' ms';\n            $data['Exit Code'] = meterAutoBadge($row['content']['exit_code'], [\n                'success' => $row['content']['exit_code'] === 0,\n                'warning' => $row['content']['exit_code'] !== 0,\n            ]);\n\n            // additional for details button\n            $details['Arguments'] = '<pre class=\"json\">' . json_encode($row['content']['arguments'], JSON_PRETTY_PRINT) . '</pre>';\n            $details['Options'] = '<pre class=\"json\">' . json_encode($row['content']['options'], JSON_PRETTY_PRINT) . '</pre>';\n\n            $data['More'] = meterCenter(meterDetailsButton($details));\n\n            $transformed[] = $data;\n        }\n\n        return $transformed;\n    }\n}\n"
  },
  {
    "path": "src/Tables/EventsTable.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass EventsTable extends Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    public function columns(): array\n    {\n        return [\n            'is_slow',\n            'content',\n            'created_at',\n        ];\n    }\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    public function searchColumns(): array\n    {\n        return $this->columns();\n    }\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return (new MeterModel)->type(Type::EVENT)->filtered()->orderBy('id', 'desc');\n    }\n\n    /**\n     * Transform data as we need.\n     *\n     * @param array $rows\n     * @return array\n     */\n    public function transform(array $rows): array\n    {\n        $transformed = [];\n\n        foreach ($rows as $row) {\n            $data['Happened'] = meterWithHtmlTitle(Carbon::parse($row['created_at'])->diffForHumans(), $row['created_at']);\n\n            $data['Event'] = $row['content']['name'];\n            $data['Time'] = $row['content']['time'] . ' ms';\n            $data['Listeners'] = count($row['content']['listeners']);\n\n            // additional for details button\n            $details['Listeners'] = '<pre class=\"json\">' . json_encode($row['content']['listeners'], JSON_PRETTY_PRINT) . '</pre>';\n            $details['Payload'] = '<pre class=\"json\">' . json_encode($row['content']['payload'], JSON_PRETTY_PRINT) . '</pre>';\n            $details['Broadcast'] = $row['content']['broadcast'];\n\n            $data['More'] = meterCenter(meterDetailsButton($details));\n\n            $transformed[] = $data;\n        }\n\n        return $transformed;\n    }\n}\n"
  },
  {
    "path": "src/Tables/QueriesTable.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Str;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass QueriesTable extends Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    public function columns(): array\n    {\n        return [\n            'is_slow',\n            'content',\n            'created_at',\n        ];\n    }\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    public function searchColumns(): array\n    {\n        return $this->columns();\n    }\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return (new MeterModel)->type(Type::QUERY)->filtered()->orderBy('id', 'desc');\n    }\n\n    /**\n     * Transform data as we need.\n     *\n     * @param array $rows\n     * @return array\n     */\n    public function transform(array $rows): array\n    {\n        $transformed = [];\n\n        foreach ($rows as $row) {\n            $data['Happened'] = meterWithHtmlTitle(Carbon::parse($row['created_at'])->diffForHumans(), $row['created_at']);\n\n            $data['Query'] = '<div class=\"meter_sql\">' . Str::limit($row['content']['sql'], 80) . '</div>';\n            $data['Time'] = $row['content']['time'] . ' ms';\n\n            $data['Slow'] = meterAutoBadge($row['is_slow'], [\n                'secondary' => $row['is_slow'] === 'No',\n                'danger' => $row['is_slow'] === 'Yes'\n            ]);\n\n            // additional for details button\n            $details['Query'] = '<div class=\"meter_sql\">' . $row['content']['sql'] . '</div>';\n            $details['Connection'] = $row['content']['connection'];\n            $details['File'] = $row['content']['file'];\n            $details['Line'] = $row['content']['line'];\n\n            $data['More'] = meterCenter(meterDetailsButton($details));\n\n            $transformed[] = $data;\n        }\n\n        return $transformed;\n    }\n}\n"
  },
  {
    "path": "src/Tables/RequestsTable.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass RequestsTable extends Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    public function columns(): array\n    {\n        return [\n            'is_slow',\n            'content',\n            'created_at',\n        ];\n    }\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    public function searchColumns(): array\n    {\n        return $this->columns();\n    }\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return (new MeterModel)->type(Type::REQUEST)->filtered()->orderBy('id', 'desc');\n    }\n\n    /**\n     * Transform data as we need.\n     *\n     * @param array $rows\n     * @return array\n     */\n    public function transform(array $rows): array\n    {\n        $transformed = [];\n\n        foreach ($rows as $row) {\n            $data['Happened'] = meterWithHtmlTitle(Carbon::parse($row['created_at'])->diffForHumans(), $row['created_at']);\n\n            $data['Verb'] = meterBadge($row['content']['method']);\n            $data['Path'] = meterWithHtmlTitle($row['content']['uri'], $row['content']['controller_action']);\n\n            $data['Status'] = meterAutoBadge($row['content']['response_status'], [\n                'success' => $row['content']['response_status'] < 400,\n                'warning' => $row['content']['response_status'] >= 400 && $row['content']['response_status'] < 500,\n                'danger' => $row['content']['response_status'] >= 500,\n            ]);\n\n            $data['Time'] = $row['content']['duration'] . ' ms';\n            $data['Memory'] = $row['content']['memory'] . ' MB';\n\n            $data['Slow'] = meterAutoBadge($row['is_slow'], [\n                'secondary' => $row['is_slow'] === 'No',\n                'danger' => $row['is_slow'] === 'Yes'\n            ]);\n\n            // additional for details button\n            $details['Controller'] = $row['content']['controller_action'];\n            $details['Middleware'] = $row['content']['middleware'];\n            $details['IP'] = $row['content']['ip'];\n\n            $data['More'] = meterCenter(meterDetailsButton($details));\n\n            $transformed[] = $data;\n        }\n\n        return $transformed;\n    }\n}\n"
  },
  {
    "path": "src/Tables/SchedulesTable.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\n\nclass SchedulesTable extends Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    public function columns(): array\n    {\n        return [\n            'is_slow',\n            'content',\n            'created_at',\n        ];\n    }\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    public function searchColumns(): array\n    {\n        return $this->columns();\n    }\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return (new MeterModel)->type(Type::SCHEDULE)->filtered()->orderBy('id', 'desc');\n    }\n\n    /**\n     * Transform data as we need.\n     *\n     * @param array $rows\n     * @return array\n     */\n    public function transform(array $rows): array\n    {\n        $transformed = [];\n\n        foreach ($rows as $row) {\n            $data['Happened'] = meterWithHtmlTitle(Carbon::parse($row['created_at'])->diffForHumans(), $row['created_at']);\n\n            $data['Command'] = $row['content']['command'];\n            $data['Expression'] = meterBadge($row['content']['expression']);\n            $data['Time'] = $row['content']['time'] . ' ms';\n\n            // additional for details button\n            $details['Description'] = $row['content']['description'];\n            $details['Timezone'] = $row['content']['timezone'];\n            $details['User'] = $row['content']['user'];\n            $details['Output'] = $row['content']['output'] ? '<pre>' . $row['content']['output'] . '</pre>' : 'null';\n\n            $data['More'] = meterCenter(meterDetailsButton($details));\n\n            $transformed[] = $data;\n        }\n\n        return $transformed;\n    }\n}\n"
  },
  {
    "path": "src/Tables/Table.php",
    "content": "<?php\n/**\n * Created by PhpStorm.\n * User: Sarfraz\n * Date: 12/12/2019\n * Time: 2:10 PM\n */\n\nnamespace Sarfraznawaz2005\\Meter\\Tables;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Pagination\\Paginator;\n\nabstract class Table\n{\n    /**\n     * Columns to be shown in table.\n     *\n     * @return array\n     */\n    abstract public function columns(): array;\n\n    /**\n     * Searchable columns in table\n     *\n     * @return array\n     */\n    abstract public function searchColumns(): array;\n\n    /**\n     * Table Query\n     *\n     * @return Builder\n     */\n    abstract public function builder(): Builder;\n\n    /**\n     * Returns data for DataTable\n     *\n     * @return array\n     */\n    public function getData(): array\n    {\n        $entries = null;\n        $columns = $this->columns();\n        $searchColumns = $this->searchColumns();\n        $builder = $this->builder();\n\n        $draw = request()->draw;\n        $start = request()->start;\n        $length = request()->length;\n        $orderColumn = request()->order[0]['column'] ?? null;\n        $dir = request()->order[0]['dir'] ?? null;\n        $searchValue = trim(request()->search['value']);\n\n        // sets the current page\n        Paginator::currentPageResolver(static function () use ($start, $length) {\n            return ($start / $length + 1);\n        });\n\n        if ($searchValue) {\n            $where = '';\n\n            foreach ($searchColumns as $searchColumn) {\n                $where .= \"`$searchColumn` like '%$searchValue%' OR \";\n            }\n\n            $where = rtrim($where, 'OR ');\n            $builder->whereRaw(\"($where)\");\n        }\n\n        $builder->select($columns);\n\n        if ($orderColumn) {\n            $builder->orderBy($columns[$orderColumn], $dir);\n        }\n\n        $rows = $builder->paginate($length);\n\n        $entries = $rows->toArray()['data'];\n\n        if (method_exists($this, 'transform')) {\n            $entries = $this->transform($entries);\n        }\n\n        return $entries ? [\n            'draw' => $draw,\n            'recordsTotal' => $rows->total(),\n            'recordsFiltered' => $rows->total(),\n            'data' => $entries\n        ] : [\n            'draw' => 0,\n            'recordsTotal' => 0,\n            'recordsFiltered' => 0,\n            'data' => [],\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Traits/FetchesStackTrace.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Traits;\n\nuse Illuminate\\Support\\Str;\n\ntrait FetchesStackTrace\n{\n    /**\n     * Find the first frame in the stack trace outside of Telescope/Laravel.\n     *\n     * @return mixed\n     */\n    protected function getCallerFromStackTrace()\n    {\n        $trace = collect(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS))->forget(0);\n\n        return $trace->first(function ($frame) {\n            if (!isset($frame['file'])) {\n                return false;\n            }\n\n            return !Str::contains($frame['file'],\n                base_path('vendor' . DIRECTORY_SEPARATOR . $this->ignoredVendorPath())\n            );\n        });\n    }\n\n    /**\n     * Choose the frame outside of either Telescope/Laravel or all packages.\n     *\n     * @return string|null\n     */\n    protected function ignoredVendorPath()\n    {\n        if (!($this->options['ignore_packages'] ?? true)) {\n            return 'laravel';\n        }\n    }\n}\n"
  },
  {
    "path": "src/Traits/FormatsClosure.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Traits;\n\nuse Closure;\nuse ReflectionFunction;\n\ntrait FormatsClosure\n{\n    /**\n     * Format a closure-based listener.\n     *\n     * @param  \\Closure  $listener\n     * @return string\n     *\n     * @throws \\ReflectionException\n     */\n    protected function formatClosureListener(Closure $listener): string\n    {\n        $listener = new ReflectionFunction($listener);\n\n        return sprintf('Closure at %s[%s:%s]',\n            $listener->getFileName(),\n            $listener->getStartLine(),\n            $listener->getEndLine()\n        );\n    }\n}\n"
  },
  {
    "path": "src/Traits/RegistersMonitors.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Traits;\n\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Sarfraznawaz2005\\Meter\\Console\\ServerMonitorCommand;\n\ntrait RegistersMonitors\n{\n    /**\n     * The class names of the registered monitors.\n     *\n     * @var array\n     */\n    protected static $monitors = [];\n\n    /**\n     * Determine if a given monitor has been registered.\n     *\n     * @param string $class\n     * @return bool\n     */\n    public static function hasMonitor($class): bool\n    {\n        return in_array($class, static::$monitors, true);\n    }\n\n    /**\n     * Register the configured Meter monitors.\n     *\n     * @param Application $app\n     * @return void\n     */\n    protected static function registerMonitors($app)\n    {\n        $serverMonitors = ServerMonitorCommand::$serverMonitors;\n\n        foreach (config('meter.monitors') as $key => $monitor) {\n\n            if (is_string($key) && $monitor === false) {\n                continue;\n            }\n\n            if (is_array($monitor) && !($monitor['enabled'] ?? true)) {\n                continue;\n            }\n\n            $monitor = $app->make(is_string($key) ? $key : $monitor, [\n                'options' => is_array($monitor) ? $monitor : [],\n            ]);\n\n            $class = get_class($monitor);\n\n            // exclude server monitors\n            if (in_array($class, $serverMonitors, true)) {\n                unset($monitor);\n                continue;\n            }\n\n            static::$monitors[] = $class;\n\n            $monitor->register($app);\n        }\n    }\n\n    /**\n     * Returns all registered monitors.\n     *\n     * @return array\n     */\n    protected static function getMonitors(): array\n    {\n        return static::$monitors;\n    }\n}\n"
  },
  {
    "path": "src/Type.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter;\n\nfinal class Type\n{\n    const QUERY = 'query';\n    const REQUEST = 'request';\n    const COMMAND = 'command';\n    const EVENT = 'event';\n    const SCHEDULE = 'schedule';\n    const CPU = 'cpu';\n    const DISK = 'disk';\n    const MEMORY = 'memory';\n    const CONNECTIONS = 'connections';\n}\n"
  },
  {
    "path": "tests/ConsoleTest.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tests;\n\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Support\\Facades\\File;\nuse Tests\\TestCase;\n\nclass ConsoleTest extends TestCase\n{\n    public function test_publish_command_works()\n    {\n        if (File::exists(public_path('vendor/meter/meter.css'))) {\n            unlink(public_path('vendor/meter/meter.css'));\n        }\n\n        $this->assertFalse(File::exists(public_path('vendor/meter/meter.css')));\n\n        Artisan::call('meter:publish');\n\n        $this->assertTrue(File::exists(public_path('vendor/meter/meter.css')));\n    }\n}\n"
  },
  {
    "path": "tests/MeterModelTest.php",
    "content": "<?php\n\nnamespace Sarfraznawaz2005\\Meter\\Tests;\n\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Sarfraznawaz2005\\Meter\\Models\\MeterModel;\nuse Sarfraznawaz2005\\Meter\\Type;\nuse Tests\\TestCase;\n\nclass MeterModelTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_it_can_save_entries()\n    {\n        $model = factory(MeterModel::class)->create(['type' => Type::EVENT, 'No', 'test content']);\n\n        $this->assertEquals('test content', $model->content);\n    }\n}\n"
  }
]