diff --git a/docs/10_Introduction.md b/docs/10_Introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..c7192b0356901838530053e8a43e97daa605c705 --- /dev/null +++ b/docs/10_Introduction.md @@ -0,0 +1,24 @@ +## Introduction + +### Why? What? + +The IML appmonitor has a client and a server written in PHP. + +All our web projects running with PHP were simple to integrate. But what about all the projects running on NodeJs, Ruby, Python, Java? The can run their checks and need to create a JSON response in the required syntax. + +This project was initiated to create a compiled client from PHP sources that can be configured with an ini file to perform needed checks. Such a binary is independent from any programming language. + +### Requirements + +#### For usage of the client + +* A binary for your platform must be available for download or must be built. Linux x86_64 is the 1st target platform +* no other requirements + +#### To built a new binary + +* git +* wget +* PHP 8 cli client (no special modules needed) + +Tested on Linux only so far. diff --git a/docs/20_Installation.md b/docs/20_Installation.md new file mode 100644 index 0000000000000000000000000000000000000000..321a7af64e4e11708738d16d2878898bf1f5d804 --- /dev/null +++ b/docs/20_Installation.md @@ -0,0 +1,7 @@ +## Installation + +TODO + +You need a local copy of the compiled single binary. + +It's not a must to put it into a folder that is covered by PATH variable. diff --git a/docs/30_Usage.md b/docs/30_Usage.md new file mode 100644 index 0000000000000000000000000000000000000000..7f4d885fd608d42632cf9ac0e8be7618fadaa1cd --- /dev/null +++ b/docs/30_Usage.md @@ -0,0 +1,156 @@ +## Show help + +```text +./src/amcli -h +IML Appmonitor as CLI client 0.1 + +This client performs appmonitor checks and puts the results as JSON to stdout. +You can use the compiled binary on non PHP systems. +(c) 2025 Institute for Medical education * University of Bern + +SYNTAX: amcli [OPTIONS] --ini=<INI-FILE> + +OPTIONS: + -h, --help Print this help and exit + -i, --ini Set an INI File to parse + -l, --list list available checks and exit + -m, --modules list available Php modules in this binary and exit + -v, --verbose Enable verbose output + -V, --version Show version and exit + +EXAMPLES: + + amcli -i=my.ini + amcli --ini=my.ini + Execute checks from INI file 'my.ini'. + + amcli --list + List available checks. + +``` + +## Execute checks + +Checks can be defined by writing an INI file that contains meta information and sections for each check. +To execute it use the `--ini` parameter and reference the file (as absolute path or relative to your current working directory). + +`[<PATH>]amcli --ini=<FILENAME>` + +## Define checks + +The infomation for the checks is structured in sections. + +* `[meta]` - defines the meta information for the web application, its hostname and more. This section is optional but I am naerly sure you want to override the defaults +* `[notifications]` - define application specific receivers that get a message from appmonitor server on status change of this app. +* `[<OTHER>]` - define one check per section. + +First an example: + +```ini +; ======================================================================= +; +; APPMONITOR CLI CLIENT +; +; to understand the entries of metadata see JSON in +; <https://os-docs.iml.unibe.ch/appmonitor/Client/Description_of_response.html> +; +; for the checks see its parameters +; <https://os-docs.iml.unibe.ch/appmonitor/PHP_client/Plugins/Checks/index.html> +; +; ======================================================================= + + +; ----------------------------------------------------------------------- +; METADATA +; ----------------------------------------------------------------------- + +[meta] +host = "www.example.com" +website = "Company website" +ttl = 300 +tags[]="monitoring" + +[notifications] +email[]="support@example.com" +email[]="webmaster@example.com" + +; for slack use the following format +; <channelname> + comma + <webhook url> +slack[]='{ "#support-channel": "https://hooks.slack.com/services/XXXXXX/YYYYYY/ZZZZZ" }' + + +; ----------------------------------------------------------------------- +; CHECKS +; ----------------------------------------------------------------------- + +["hello plugin"] +description="I sust wann say hello" +function="hello" +params='{ +"message": "Here I am" +}' + +; ----------------------------------------------------------------------- +``` + +#### Types of values + +The binary uses the php function `parse_ini_file` - see <https://www.php.net/manual/en/function.parse-ini-file.php>. + +* The **section** is in brackets eg. `[<SECTION>]` +* In each section is a set of keys and values, separated by `=` +* **keys** (variable): + + * a string with letters, digits, underscore + * Use multiple `<VARNAME>[]` to create an an array with list items + * `<VARNAME>[<KEY>]` is unused so far + +* **values** + + * numbers of integer, float (no quoting) + * strings in single quotes or double quotes + * Specialties: We use JSON syntax in these ini variables to parse + * [notifications] -> slack + * [check] -> params + * Environment variables or PHP configuration values can be embedded using `${<VARMAME>}`; it works with unquoted value or double quoted strings but not inside single quotes. + +In the example above see the value behind `params=`. It is aquoted string using single quotes `'`. The JSON key and value must be quoted with double quotes. + +The values for each check are check specific. Have a look to the origin docs for each check - see <https://os-docs.iml.unibe.ch/appmonitor/PHP_client/Plugins/Checks/index.html>. + +To have a minimal working example have a the folder `tests/configs` or here <https://git-repo.iml.unibe.ch/iml-open-source/appmonitor-cli-client/-/tree/main/tests/configs?>. But here are not all supported keys. + +## Exitcodes + +The binary could stop and exit with non zero exitcode. + +### amcli + +| Exitcode | Description +| --- | --- +| 0 | OK. An option was executed (help, list modules or checks) or the check was executed successfully +| 1 | include include_checks.php failed (php file only) +| 2 | include_checks.php failed (php file only) +| 3 | INI file was not given. Maybe just a missing `=` char in `--ini=<FILE>`? +| 4 | Given Ini file does not exist +| 5 | Given Ini file cannot be parsed +| 6 | Ini value `params=` is no JSON + +### appmonitor-client class + +| Exitcode | Description +| --- | --- +| 10 | incomplete reponse data detected eg. no check, no result code +| 11 | Access denied: Ip restriction was set +| 12 | Access denied: No token or wrong token was given + +### appmonitor-checks class + +| Exitcode | Description +| --- | --- +| 20 | Missing key in a given hash +| 21 | Mising value in a given hash +| 22 | Check not found. Check your `function`value +| 23 | Check didn't response a hash (=error in check) +| 24 | Check responded a too small hash (=error in check) +| 25 | The unit in a space value is unknown diff --git a/docs/40_Build.md b/docs/40_Build.md new file mode 100644 index 0000000000000000000000000000000000000000..e137f50b43e4f590afe8e08b0da3c8a126e3794a --- /dev/null +++ b/docs/40_Build.md @@ -0,0 +1,83 @@ +## Requirements + +To update and test the command line tool you need + +* git +* a local PHP8 cli. + +## Prepare environemnt + +### Get sources + +In your personal development folder checkout the repsitory + +```shell +cd <YOUR-PROJECTS> +git clone https://git-repo.iml.unibe.ch/iml-open-source/appmonitor-cli-client.git +cd appmonitor-cli-client +``` + +You get this initial structure: + +```txt +. +├── build.php +├── inc_functions.php +├── inc_vars.php +├── installer.php +├── readme.md +└── src + └── amcli.php +``` + +### Installer + +Run the `./installer.php` to download apmonitor source and spc. It prepares the micro build and creates a merged php file of all appmonitor client checks. + +The newly created files and dirs are: + +```txt +. +├── build << working directory for builds +│ +├── external +│ ├── appmonitor << cloned IML appmonitor project +│ └── bin +│ └── spc << downloaded spc binary +│ +├── src +│ └── include_checks.php << merged appmonitor client checks +: +``` + +### Build + +To build the amcli binary start `./build.php`. First it merges src/amcli.php and src/include_checks.php to src/amcli.php**.tmp** which is used for the build command of spc. + +Output directory is `built_packages`. + +After building the binary it executes it (with -V to show the version). If it is OK then it creates a copy with platform and architecture suffix. + +### Repeat? + +You need to re-run install.php + build.php if + +* there is a newer appmonitor client version +* you compile with a newer php version +* you change the set of included php modules. + +The build.php (without install.php) needs to be executed if the src/amcli.php was changed. + +## Start over + +Remove the dirs + +* built_packages +* build +* external + +... and this file + +* src/include_checks.php + +Then start `./installer.php` and `./build.php` diff --git a/docs/_index.md b/docs/_index.md new file mode 100644 index 0000000000000000000000000000000000000000..ecb565982e10fd226d26c2f8e7de36cab282fa8b --- /dev/null +++ b/docs/_index.md @@ -0,0 +1,11 @@ +<html> +<div class="hero"> + <h2>Appmonitor CLI</h2> + Cli client of IML appmonitor for non PHP web projects +</div> +</html> + +👤 Author: Axel Hahn; Institute for Medical Education; University of Bern \ +📄 Source: <https://git-repo.iml.unibe.ch/iml-open-source/appmonitor-cli-client> \ +📜 License: GNU GPL 3.0 \ +📗 Docs: <https://os-docs.iml.unibe.ch/appmonitor-cli-client/> diff --git a/docs/config.json b/docs/config.json new file mode 100644 index 0000000000000000000000000000000000000000..b152b6a734dcf20c30128f83eb44833d53aa793d --- /dev/null +++ b/docs/config.json @@ -0,0 +1,26 @@ +{ + "title": "Appmonitor cli client", + "author": "Axel Hahn", + "tagline": "Complied client for appmonitor checks that can be used on non-php web apps.", + "ignore": { + "files": ["30_PHP-client/Plugins/Checks/_skeleton.md"], + "folders": ["99_Not_Ready"] + }, + "html": { + "auto_toc": true, + "auto_landing": false, + "date_modified": false, + "jump_buttons": true, + "edit_on_github_": "iml-it/__PROJECT__/tree/master/docs", + "edit_on_": { + "name": "Gitlab", + "basepath": "https://git-repo.iml.unibe.ch/iml-open-source/appmonitor-cli-client/tree/main/docs" + }, + "links": { + "Git Repo": "https://git-repo.iml.unibe.ch/iml-open-source/appmonitor-cli-client/", + "IML Opensource": "https://os-docs.iml.unibe.ch/" + }, + "theme": "daux-blue", + "search": true + } +} diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 0000000000000000000000000000000000000000..90a0bc938f147608a1d4fd11952e4825f076862c --- /dev/null +++ b/docs/style.css @@ -0,0 +1,336 @@ +/* + override css elements of daux.io blue theme + version 2024-10-31 +*/ +:root { + /* Axels Overrides */ + --color-text: #234; + --link-color: #228; + --brand-color: var(--color-text); + --brand-background: var(--body-background); + --code-tag-background-color: #f0f3f3; + --code-tag-border-color: #dee; + --code-tag-box-shadow: none; + --hr-color: none; + --pager-background-color: #f8fafa; + --pager-border-color: none; + --search-field-background: none; + --search-field-border-color: none; + --sidebar-background: var(--body-background); + --sidebar-border-color: none; + --sidebar-link-active-background: #f0f4f6; + --toc--inner-border-color: none; + /* Axels custom values */ + --axel_bg-toc: #f8fafa; + --axel_bg-toc-head: #f8f8f8; + --axel_brand-background: none; + --axel_brand-pre-background: rgb(255, 0, 51); + --axel_brand-pre-background-hover: rgb(255, 0, 51); + --axel_h1_header: none; + --axel_h1: #111; + --axel_h1-bg: none; + --axel_h1-bottom: 3px solid none; + --axel_h2: #222; + --axel_h2-bg: none; + --axel_h2-bottom: 0px solid #467; + --axel_h2-hero-bottom: 2px solid #912; + --axel_h3: #333; + --axel_h3-bottom: 0px solid #ddd; + --axel_h4: #666; + --axel_h5: #888; + --axel_hero_bg: #faf8f6; + --axel_img-border: 2px dashed #ccc; + --axel_nav-bg: #fcfcfc; + --axel_nav-buttomborder: #ddd; + --axel_pre-background: #faf8f6; + --axel-th-background: #e0e4e8; + --axel-article-nav-border-top: 0px dotted #ddd; +} + +.dark { + /* Axels Overrides */ + --color-text: #c0c0c0; + --link-color: #88e; + --brand-color: var(--color-text); + --brand-background: var(--body-background); + --body-background: #101418; + --hr-color: none; + --code-tag-background-color_: #bcc; + --search-field-background: none; + --search-field-border-color: none; + --sidebar-background: var(--body-background); + --sidebar-border-color: none; + --sidebar-link-active-background: #333; + --sidebar-link-color: var(--link-color); + /* Axels custom values */ + --axel_bg-toc: var(--body-background); + --axel_bg-toc-head: #333; + --axel_brand-background: none; + --axel_brand-pre-background: rgb(255, 0, 51); + ; + --axel_brand-pre-background-hover: rgb(255, 0, 51); + ; + --axel_h1_header: none; + --axel_h1: #578; + --axel_h1-bg: none; + --axel_h1-bottom: none; + --axel_h2: #467; + --axel_h2-bg: none; + --axel_h2-bottom: 0px solid #256; + --axel_h2-hero-bottom: 2px solid #712; + --axel_h3: #589; + --axel_h3-bottom: 0px solid #333; + --axel_h4: #478; + --axel_h5: #278; + --axel_hero_bg: #242424; + --axel_img-border: 2px dashed #555; + --axel_nav-bg: #242424; + --axel_nav-buttomborder: #555; + --axel_pre-background: #bcc; + --axel-th-background: #203038; + --axel-article-nav-border-top: 0px dotted #234; +} + +/* ---------- left side ---------- */ +a.Brand::before { + background: var(--axel_brand-pre-background); + color: #fff; + font-family: arial; + font-weight: bold; + padding: 0.5em 0.3em; + content: 'IML'; + margin-right: 0.4em; + float: left; +} + +a.Brand:hover::before { + background: var(--axel_brand-pre-background-hover); +} + +a.Brand { + background: var(--axel_brand-background); + font-size: 200%; + height: 4em; +} + +/* ---------- page header: breadcrumb ---------- */ +.Page__header { + border: none; +} + +.Page__header a { + color: var(--axel_h1_header); +} + +.Page__header h1 { + font-size: 1.3em; +} + +/* ---------- page content ---------- */ +.s-content { + padding-top: 6em; +} + +/** +h1::before{color: #aaa;content: 'h1: ';} +h2::before{color: #aaa;content: 'h2: ';} +h3::before{color: #aaa;content: 'h3: ';} +h4::before{color: #aaa;content: 'h4: ';} +h5::before{color: #aaa;content: 'h5: ';} +h6::before{color: #aaa;content: 'h6: ';} +*/ +h2::before{color: #888;content: ': : ';} +h3::before{color: #ccc;content: '> ';} +h4::before{color: #ccc;content: '_ ';} + +.s-content h1::before{ + color: #f00; + content: 'FEHLER: Keine Überschrift 1 in einer Markdown-Datei für Daux verwenden! Mit H2 beginnen!'; + content: '!! h1 !! '; +} + +.s-content h1 { + background: var(--axel_h1-bg); + color: var(--axel_h1); + font-size: 200%; + font-weight: bold; + margin-bottom: 2em; + margin-top: 2em; + border-bottom: var(--axel_h1-bottom); +} + +.s-content h2 { + background: var(--axel_h2-bg); + color: var(--axel_h2); + font-size: 190%; + font-weight: bold; + margin-top: 4em; + border-bottom: var(--axel_h2-bottom); +} + +.Page__header > h1:first-of-type { + margin-top: 0em; + margin-left: -1em; + padding-left: 1em; + position: fixed; + min-width: 100%; + background: var(--body-background); + box-shadow: 0 2em 1em var(--body-background); +} + +h2:first-of-type { + margin-top: 0em; +} + +img{ + border: var(--axel_img-border); + border-radius: 1.5em; + padding: 0.7em; +} + +.s-content h3 { + background: var(--axel_h3-bg); + color: var(--axel_h3); + font-size: 150%; + font-weight: bold; + margin-top: 3em; + border-bottom: var(--axel_h3-bottom); +} + + +.s-content > h4 { + color: var(--axel_h4); + font-size: 140%; + font-weight: bold; + margin: 2em 0; +} + +.s-content > h5 { + color: var(--axel_h5); + font-size: 135%; + font-weight: bold; + margin: 2em 0; +} + +.s-content .TableOfContentsContainer h4 { + margin: 1em 0; + font-size: 110%; + text-align: center; + background-color: rgba(0, 0, 0, 0.1); + padding: 0.3em; + font-weight: bold; + font-family: Arial; +} +ul.TableOfContents a{ + color: var(--color-text); +} +.s-content pre { + background: var(--axel_pre-background); + border-radius: 0.5em; + padding: 1rem; +} + +/* FIX smaller fnt size in tables */ +.s-content table { + font-size: 1em; +} + +.s-content table th { + background: var(--axel-th-background); +} + +.s-content h3 code { + border: none; + background: none; +} + +article nav { + border-top: var(--axel-article-nav-border-top); + margin: 8em 0 5em; +} + +.Pager li>a { + padding: 1em 2em; +} + +/* ---------- classes ---------- */ +.required { + color: #a42; +} + +.optional { + color: #888; +} + +div.hero { + background: var(--axel_hero_bg); + border-radius: 2em; + padding: 5em 2em; + text-align: center; + margin-bottom: 1.5em; +} + +div.hero h2 { + color: var(--color-text); + background: none; + border-bottom: var(--axel_h2-hero-bottom); + font-size: 300%; + margin: 0 0 2em; +} + +/* ---------- TOC ---------- */ + +.TableOfContentsContainer { + background-color: var(--axel_bg-toc); + padding: 0.5em; +} + +.s-content .TableOfContentsContainer h4 { + background-color: var(--axel_bg-toc-head); + border-top-left-radius: 1em; + border-bottom: 2px solid var(--axel_bg-toc-bottom-border); + font-size: 1.1em; + margin: 0; + padding: 0.3em; + display: none; +} + +.TableOfContentsContainer__content { + border-width: 0px; + font-size: 0.5em; + height: inherit; + overflow: auto; +} + +ul.TableOfContents ul { + list-style-type: none; + padding-left: 1em; +} + +.TableOfContents a:hover{ + text-decoration: underline; +} + +@media(min-width:1700px) { + .TableOfContentsContainer { + background: none; + position: fixed; + right: 2em; + top: 4em; + height: 90%; + } +} + +/* ----- Icons on links --- */ + +.EditOn a::before{ + content: '✏️ '; +} + +.Links a::before { + content: '🌐 '; +} + +.Links a[href^="https://os-docs.iml.unibe.ch"]::before { + content: '📗 '; +}