Moving files
11
.gitignore
vendored
|
@ -1,5 +1,8 @@
|
|||
web/vendor/**/*
|
||||
/vendor
|
||||
/.idea
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
.env
|
||||
web/sync.php
|
||||
/**/node_modules
|
||||
/**/dist
|
||||
.phpunit.result.cache
|
||||
/node_modules
|
||||
/storage
|
||||
|
|
112
README.md
|
@ -1,88 +1,24 @@
|
|||
# MONITOLITE
|
||||
|
||||
**MonitoLite** is an old project I recently dug up from my archives. I developed this script years ago for my personal needs.
|
||||
I figured it could be useful for others so I **rewrote** and **updated** it from scratch in a modern way.
|
||||
|
||||
|
||||
## What it does
|
||||
|
||||
**MonitoLite** is a very simple monitoring tool developed in Perl. It supports :
|
||||
* **ping monitoring**: sends a `ping` command to the specified host. Raises an alert if the host is down
|
||||
* **http monitoring**: requests the provided URL and raises an alert if the URL returns an error. Optionally you may specify a string to search on the page using the `param` database field. It raises an alert if the specified text could not be found on the page.
|
||||
|
||||
In case of an alert, the script sends an email notifications to the specified contacts (one or many).
|
||||
The script also sends a recovery email notification when the alert is over.
|
||||
|
||||
It uses a SQL backend for handling the tasks and the status of the tasks.
|
||||
Tested on MySQL only but should support other SQL-based DBMS.
|
||||
|
||||
It comes with a very straightforward dashboard written in PHP. This is **optional**, the `monitolite.pl` script runs as standalone.
|
||||
**Caution**: the backend is not password-protected. You should make sure you add your own security layer via IP filtering or basic authentication.
|
||||
|
||||
|
||||
I rewrote a couple of things today to make sure the script still works.
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
* Perl : with DBI::MySQL, Dotenv, Net::Ping, Email::MIME, Email::Sender::Simple, Email::Sender::Transport::SMTP, LWP::Simple, LWP::UserAgent, LWP::Protocol::https
|
||||
* a MTA: Postfix, ...
|
||||
* PHP 7+ (optional): with PDO
|
||||
* a webserver (optional): Apache, Nginx, ...
|
||||
* a Database server: MySQL, other? (untested)
|
||||
* access to CRON tasks
|
||||
* possibly `root` access for the `ping` command to run (needs confirmation)
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
* clone this repo
|
||||
* install Perl dependencies
|
||||
* install PHP composer dependencies: `cd ./web && composer install`
|
||||
* install Javascript dependencies: `cd ./web && npm install`
|
||||
* compile the Javascript sources: `cd ./web && npx mix --production`
|
||||
* create a Database and import the schema from `sql/create.sql`
|
||||
* create your own `.env` file: `cp env.example .env` and adapt it to your needs
|
||||
* create a webserver vhost with document root to the `web` directory
|
||||
* add tasks and contacts into the database (no backend yet)
|
||||
* run the script: `perl monitolite.pl`
|
||||
* check the web dashboard for results.
|
||||
* when everything works, you may create a CRON `* * * * * cd <change/this/to/the/correct/path> && /usr/bin/perl monitolite.pl > /dev/null`
|
||||
|
||||
|
||||
## Settings
|
||||
|
||||
* DB_TYPE=mysql
|
||||
* DB_HOST=127.0.0.1
|
||||
* DB_USER=vagrant
|
||||
* DB_PASSWORD=vagrant
|
||||
* DB_NAME=monitoring
|
||||
* DB_PORT=3306
|
||||
* SMTP_HOST=localhost
|
||||
* SMTP_USER=
|
||||
* SMTP_PASSWORD=
|
||||
* SMTP_PORT=80
|
||||
* SMTP_SSL=1
|
||||
* MAIL_FROM=axel@monitolite.fr
|
||||
* NB_TRIES=3
|
||||
* ARCHIVE_DAYS=10
|
||||
|
||||
## MORE INFORMATION COMING SOON.
|
||||
|
||||
## TODO
|
||||
|
||||
* Make CRUD possible from the backend for adding tasks and contacts
|
||||
* Multithreading
|
||||
* SMS Notifications
|
||||
* Better dashboard
|
||||
* Protected backend with authentication
|
||||
* Create an installation script
|
||||
* Raise alert when tasks are not run at the correct frequency (CRON down or other reason)
|
||||
* Set a notification capping limit to prevent many notifications to be sent in case of an up-and-down host
|
||||
* Add a notification history log
|
||||
* Keep track of tasks response time
|
||||
* Daemonize the script (instead of CRONs)
|
||||
# Lumen PHP Framework
|
||||
|
||||
[](https://travis-ci.org/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
|
||||
Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Lumen attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as routing, database abstraction, queueing, and caching.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
Documentation for the framework can be found on the [Lumen website](https://lumen.laravel.com/docs).
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to Lumen! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Lumen, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
|
||||
|
||||
## License
|
||||
|
||||
The Lumen framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
|
|
|
@ -64,18 +64,21 @@ class ApiController extends Controller
|
|||
LEFT JOIN `tasks_history` as h ON (h.task_id = t.id)
|
||||
LEFT JOIN `groups` as g ON (g.id = t.group_id)
|
||||
WHERE (t.last_execution IS NULL OR h.datetime = t.last_execution) AND t.id = :task_id
|
||||
LIMIT 1
|
||||
', [
|
||||
'task_id' => $id
|
||||
]);
|
||||
|
||||
if ($query) {
|
||||
return response()->json($query);
|
||||
foreach ($query as $q) {
|
||||
return response()->json($q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleTaskStatus(Request $request, $id) {
|
||||
if( ! $active = $request->input('active')) {
|
||||
throw new ApiException('Invalid parameters');
|
||||
if($active = $request->input('active')) {
|
||||
//throw new ApiException('Invalid parameters');
|
||||
}
|
||||
|
||||
$active = intval($active);
|
0
web/composer.lock → composer.lock
generated
0
web/package-lock.json → package-lock.json
generated
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 352 B After Width: | Height: | Size: 352 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 330 B After Width: | Height: | Size: 330 B |
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 247 B After Width: | Height: | Size: 247 B |
|
@ -41,6 +41,19 @@ const store = new Vuex.Store({
|
|||
setTasks(state, tasks) {
|
||||
state.tasks = tasks
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
updateTask(state, update) {
|
||||
//let tasks = state.tasks
|
||||
|
||||
for (let i in state.tasks[update.group_id]['tasks']) {
|
||||
if (state.tasks[update.group_id]['tasks'][i].id == update.id) {
|
||||
//tasks[update.group_id]['tasks'][i] = update
|
||||
state.tasks[update.group_id]['tasks'][i] = Object.assign({}, state.tasks[update.group_id]['tasks'][i], update)
|
||||
}
|
||||
}
|
||||
console.log(state.tasks)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
106
resources/views/components/grouplist.vue
Normal file
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="tasks">
|
||||
<div
|
||||
v-for="group in tasks"
|
||||
v-bind:key="group.id"
|
||||
class="task"
|
||||
>
|
||||
<a :name="'group-'+group.id"></a>
|
||||
<h3>
|
||||
Tasks for group <span class="highlight">{{ group.name }} <small>(#{{ group.id }})</small></span>
|
||||
<!-- <p class="context-menu"><img src="img/menu.svg" width="40" /></p> -->
|
||||
</h3>
|
||||
|
||||
<div class="block-content">
|
||||
<table id="tasks_tbl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">Up?</th>
|
||||
<th width="*">Host</th>
|
||||
<th width="5%">Type</th>
|
||||
<th width="20%">Last checked</th>
|
||||
<th width="13%">Frequency (min)</th>
|
||||
<th width="5%">Active</th>
|
||||
<th width="5%">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="task in group.tasks"
|
||||
v-bind:key="task.id"
|
||||
>
|
||||
<td :class="statusText(task.status)">
|
||||
<img :src="'img/'+statusText(task.status)+'.svg'" width="16" alt="Status" />
|
||||
</td>
|
||||
<td>
|
||||
<a :href="task.host" target="_blank">{{ task.host }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<img :src="task.type == 'http' ? 'img/http.svg' : 'img/ping.svg'" width="16" alt="Type of check" :title="'Type: '+task.type" />
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
v-if="task.last_execution"
|
||||
>
|
||||
{{ moment(task.last_execution).fromNow() }}
|
||||
<img src="img/info.svg" alt="Infos" width="16" :title="'Result: '+task.output" />
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
>
|
||||
Never
|
||||
</span>
|
||||
<td>{{ task.frequency / 60 }}</td>
|
||||
<td>{{ task.active == 1 ? 'Yes' : 'No' }}</td>
|
||||
<td>
|
||||
<router-link :to="{ name: 'taskdetails', params: { id: task.id }}">
|
||||
<img src="img/see.svg" alt="Details" width="16" />
|
||||
</router-link>
|
||||
<a
|
||||
v-on:click.prevent="disableTask(task.id, task.active)"
|
||||
href="#"
|
||||
>
|
||||
<img src="img/disable.svg" alt="Disable" width="16" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
tasks: function() {
|
||||
return this.$store.state.tasks
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
statusText: function (status) {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'up';
|
||||
break;
|
||||
case 0:
|
||||
return 'down';
|
||||
break;
|
||||
default:
|
||||
return 'unknown';
|
||||
}
|
||||
},
|
||||
disableTask: function(task_id, current_status) {
|
||||
this.$http.post('/api/toggleTaskStatus/'+task_id, {
|
||||
active: + !current_status
|
||||
})
|
||||
.then(response => this.$store.dispatch('updateTask', response.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -77,10 +77,10 @@ export default {
|
|||
}
|
||||
},
|
||||
disableTask: function(task_id, current_status) {
|
||||
console.log('Disabling task #'+task_id)
|
||||
this.$http.post('/api/toggleTaskStatus/'+task_id, {
|
||||
active: !current_status
|
||||
active: + !current_status
|
||||
})
|
||||
.then(response => this.$store.commit('updateTask', response.data))
|
||||
}
|
||||
}
|
||||
}
|
6
web/.gitignore
vendored
|
@ -1,6 +0,0 @@
|
|||
/vendor
|
||||
/.idea
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
.env
|
||||
.phpunit.result.cache
|
|
@ -1,24 +0,0 @@
|
|||
# Lumen PHP Framework
|
||||
|
||||
[](https://travis-ci.org/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
[](https://packagist.org/packages/laravel/lumen-framework)
|
||||
|
||||
Laravel Lumen is a stunningly fast PHP micro-framework for building web applications with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Lumen attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as routing, database abstraction, queueing, and caching.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
Documentation for the framework can be found on the [Lumen website](https://lumen.laravel.com/docs).
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to Lumen! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Lumen, please send an e-mail to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
|
||||
|
||||
## License
|
||||
|
||||
The Lumen framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
|
@ -1,50 +0,0 @@
|
|||
<template>
|
||||
<div class="tasks">
|
||||
<div
|
||||
v-for="group in tasks"
|
||||
v-bind:key="group.id"
|
||||
class="task"
|
||||
>
|
||||
<a :name="'group-'+group.id"></a>
|
||||
<h3>
|
||||
Tasks for group <span class="highlight">{{ group.name }} <small>(#{{ group.id }})</small></span>
|
||||
<!-- <p class="context-menu"><img src="img/menu.svg" width="40" /></p> -->
|
||||
</h3>
|
||||
|
||||
<div class="block-content">
|
||||
<task-list :tasks="group.tasks"></task-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import TaskList from './tasklist.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TaskList
|
||||
},
|
||||
computed: {
|
||||
tasks: function() {
|
||||
return this.$store.state.tasks
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
statusText: function (status) {
|
||||
switch (status) {
|
||||
case '1':
|
||||
return 'up';
|
||||
break;
|
||||
case '0':
|
||||
return 'down';
|
||||
break;
|
||||
default:
|
||||
return 'unknown';
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
2
web/storage/app/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
3
web/storage/framework/cache/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
*
|
||||
!data/
|
||||
!.gitignore
|
2
web/storage/framework/cache/data/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
2
web/storage/framework/views/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
2
web/storage/logs/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|