Pattoo¶
pattoo
stores timeseries data in a database and makes it available for users via a GraphQL API.
Visit the Pattoo GitHub site to see the code.
Introduction¶
General information about the project, including the the prerequisite steps to get it operational on your system.
About Pattoo¶
pattoo
allows you to use your web browser to chart your organization’s constantly changing data.
It was inspired by the need to collect and visualize data from various DevOps, network, industrial PLC controllers, electro-mechanical and enterprise systems on a single web dashboard.
This data is collected by pattoo
agents. There are standard agents for:
- Linux
- SNMP
- Modbus TCP
- Bacnet/IP
- OPC UA
With programming skill, you can create your own custom agents if needed.
Operational Overview¶
pattoo
has a number of inter-related components. You can see how they all work together on the pattoo web page.
The Palisadoes Foundation¶
pattoo
is based on the original infoset
code created by the Palisadoes Foundation as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015.
Basic Installation¶
This section covers some key steps to get you started.
Prerequisites¶
There are some software components that need to be installed prior to starting.
pattoo
requires the installation of a MySQL or MariaDB database. Make sure this software is installed beforehand.pattoo
only runs on Python 3.6 or higher
Let’s install the software.
Installation¶
Follow these steps.
Install
git
on your system.Select and create the parent directory in which you want to install
pattoo
.$ mkdir -p /installation/parent/directory $ cd /installation/parent/directory
Clone the repository to the parent directory using the
git clone
command. You can also choose to downloading and unzip the file in the parent directory. The repository can be found at: https://github.com/PalisadoesFoundation/pattoo$ cd /installation/parent/directory $ git clone https://github.com/PalisadoesFoundation/pattoo.git
Enter the
/installation/parent/directory/pattoo
directory with thepattoo
files.Install the required packages using the
pip_requirements
document in thepattoo
root directory$ pip3 install -r pip_requirements.txt
Create the
MySQL
orMariaDB
database forpattoo
with the correct authentication parameters provided in the Configuration Guide In this example adjust the name of your database and the password accordingly.$ sudo mysql
CREATE DATABASE pattoo; GRANT ALL PRIVILEGES ON pattoo.* TO pattoo@"localhost" IDENTIFIED BY 'PATTOO_PASSWORD'; FLUSH PRIVILEGES; exit;
Use the Configuration Guide to create a working configuration.
Run the installation script
$ sudo setup/install.py install all
View additional installation options Installation Modes
Configure the required
cron
jobs. Periodic Jobs
Configuration Guide¶
After installation, you will need to create a configuration file in a directory dedicated to pattoo
.
Setting the Configuration Directory Location¶
Currently the configuration directory is automatically set when the installationscript is run
Configuration Options¶
There are two ways to configure pattoo
. These are the:
- Quick Method
- Expert Method
Quick Method¶
Use the quick method if you are new to pattoo
.
$ sudo setup/pattoo_installation.py install configuration
The above command will set the most optimal defaults for your system for pattoo.
Additionally, the pattoo user and group will be created with the home directory for the pattoo user being /home/pattoo All related directories and their subdirectories will be owned by the pattoo user
To guarantee success you will need to know the following beforehand.
db_name
: Database namedb_username
: Database usernamedb_password
: Database passworddb_hostname
: Database hostname
Expert Method¶
This section goes into configuration parameters in great detail.
Copy the Templates to Your Configuration Directory¶
Follow the steps in this section if you don’t already have a valid configuration files in your PATTOO_CONFIGDIR
directory.
Copy the template files in the examples/etc
directory to the PATTOO_CONFIGDIR
location.
NOTE: If a /path/to/configuration/directory/pattoo_server.yaml
or /path/to/configuration/directory/pattoo.yaml
file already exists in the directory then skip this step and edit the file according to the steps in following sections.
$ cp examples/etc/pattoo_server.yaml.template \
/path/to/configuration/directory/pattoo_server.yaml
$ cp examples/etc/pattoo.yaml.template \
/path/to/configuration/directory/pattoo.yaml
The next step is to edit the contents of both files.
Edit Your Configuration Files¶
The pattoo
server uses two configuration files:
pattoo.yaml
: Provides general configuration information for allpattoo
related applications.pattoo.yaml
also defines howpattoo
agents should connect to thepattoo
server APIs.pattoo_server.yaml
: Provides configuration details for all thepattoo
server’s API daemons. These APIs accept data frompattoo
agents and also provide data topattoo
related applications through your browser.
Take some time to read up on YAML
formatted files if you are not familiar with them. A background knowledge is always helpful.
The pattoo_server.yaml
file created from the template will have sections that you will need to edit with custom values. Don’t worry, these sections are easily identifiable as they all start with PATTOO_
NOTE: The indentations in the YAML configuration are important. Make sure indentations line up. Dashes ‘-‘ indicate one item in a list of items (if applicable).
pattoo_api_agentd:
ip_bind_port: 20201
ip_listen_address: 0.0.0.0
pattoo_apid:
ip_bind_port: 20202
ip_listen_address: 0.0.0.0
pattoo_ingesterd:
ingester_interval: 3600
batch_size: 500
graceful_timeout: 10
pattoo_db:
db_pool_size: 10
db_max_overflow: 10
db_hostname: PATTOO_DB_HOSTNAME
db_name: PATTOO_DB_NAME
db_password: PATTOO_DB_PASSWORD
db_username: PATTOO_DB_USERNAME
This table outlines the purpose of each configuration parameter.
Section | Configuration Parameters | Description |
---|---|---|
pattoo_api_agentd |
||
ip_listen_address |
IP address used by the pattoo_api_agentd daemon for accepting data from remote pattoo agents. Default of ‘0.0.0.0’ which indicates listening on all available network interfaces. You can also use IPv6 nomenclature such as :: . The pattoo APIs don’t support IPv6 and IPv4 at the same time. |
|
ip_bind_port |
TCP port of used by the pattoo_api_agentd daemon for accepting data from remote pattoo agents. Default of 20201. |
|
pattoo_apid |
||
ip_listen_address |
IP address used by the pattoo_apid daemon for providing data to remote clients. Default of ‘0.0.0.0’ which indicates listening on all available network interfaces. You can also use IPv6 nomenclature such as :: . The pattoo APIs don’t support IPv6 and IPv4 at the same time. |
|
ip_bind_port |
TCP port of used by the pattoo_apid daemon for providing data to remote clients. Default of 20202. |
|
pattoo_ingesterd |
||
ingester_interval |
The interval between checking for new agent files in the cache directory. Only valid if using the pattoo_ingesterd daemon. |
|
batch_size |
The number of files to read per processing batch until all files are processed. | |
graceful_timeout |
The amount of time required for the ingester to finish processing data when the stop or restart command is excuted before it is forcefully stopped or restarted. | |
pattoo_db |
||
db_hostname |
Hostname of the database server | |
db_username |
Username required for database access | |
db_password |
Password required for database access | |
db_name |
Name of database | |
db_pool_size |
This is the largest number of connections that will be keep persistently with the database | |
db_max_overflow |
Maximum overflow size. When the number of connections reaches the size set in db_pool_size , additional connections will be returned up to this limit. This is the floating number of additional database connections to be made available. |
The pattoo.yaml
file created from the template will have sections that you will need to edit with custom values. Don’t worry, these sections are easily identifiable as they all start with PATTOO_
NOTE: The indentations in the YAML configuration are important. Make sure indentations line up. Dashes ‘-‘ indicate one item in a list of items (if applicable).
pattoo:
log_level: debug
log_directory: PATTOO_LOG_DIRECTORY
cache_directory: PATTOO_CACHE_DIRECTORY
daemon_directory: PATTOO_DAEMON_DIRECTORY
system_daemon_directory: PATTOO_SYSTEM_DAEMON_DIRECTORY
This table outlines the purpose of each configuration parameter.
Section | Configuration Parameters | Description |
---|---|---|
pattoo |
||
log_directory |
Path to logging directory. Make sure the username running the daemons have RW access to files there. | |
log_level |
Default level of logging. debug is best for troubleshooting. |
|
cache_directory |
Directory that will temporarily store data data from agents prior to be added to the pattoo database. |
|
daemon_directory |
Directory used to store daemon related data that needs to be maintained between reboots | |
system_daemon_directory |
Directory used to store daemon related data that should be deleted between reboots. This should only be configured if you are running pattoo daemons as systemd daemons. The systemd daemon installation procedure automatically adjusts this configuration. This parameter defaults to the daemon_directory value if it is not configured. |
Configuring systemd Daemons¶
You can also setup all the pattoo
related daemons located in this GitHub repository as system daemons by executing the setup/systemd/bin/install_systemd.py
script.
The script requires you to specify the following parameters. Make sure you have a username and group created for running your pattoo
services.
usage: install_systemd.py [-h] -f CONFIG_DIR -u USERNAME -g GROUP
optional arguments:
-h, --help show this help message and exit
-f CONFIG_DIR, --config_dir CONFIG_DIR
Directory where the pattoo configuration files will be located
-u USERNAME, --username USERNAME
Username that will run the daemon
-g GROUP, --group GROUP
User group to which username belongs
Note The daemons are not enabled or started by default. You will have to do this separately using the systemctl
command after running the script.
$ sudo setup/systemd/bin/install_systemd.py --user pattoo --group pattoo --config_dir /etc/pattoo
SUCCESS! You are now able to start/stop and enable/disable the following systemd services:
pattoo_api_agentd.service
pattoo_apid.service
pattoo_ingesterd.service
$
Backup and Restoration¶
Always take precautions. Backup your data as you’ll never know when you’ll need to restore it.
Backup¶
It is strongly advised that you backup your agents to protect you in the event of catastrophe.
The following directories need to be saved periodically.
- The
PATTOO_CONFIGDIR
directory which contains your configuration - The
daemon_directory
location defined in your configuration. This area stores important authentication information. - The
pattoo
directory which contains your source code.
We’ll discuss data restoration next.
Restoration¶
It’s important to follow these steps in this order when restoring pattoo
after a disaster.
- FIRST make sure all the
pattoo
agents are stopped. - SECOND restore the contents of the
daemon_directory
location defined in your configuration. This area stores important authentication information. - Restore the
PATTOO_CONFIGDIR
directory which contains your configuration - Restore the
pattoo
directory which contains your source code.
You should now be able to restart your agents without issue.
Daemon and Cron Setup¶
How to get the daemons running to collect data.
Periodic Jobs¶
You will need to configure some jobs to improve pattoo
performance and troubleshooting.
Logrotate Configuration¶
The default pattoo
debug logging mode can quickly create large logging files. The logrotate utility can automatically compress and archive them.
- Copy the the
examples/logrotate.d/pattoo
file to the/etc/logrotate.d
directory. - Edit the file path accordingly.
Read up on the logrotate utility if you are not familiar with it. The documentation is easy to follow.
Pattoo Web API Daemon¶
pattoo_apid
serves pattoo
agent data from the database via a web API.
Installation¶
Follow these steps.
- Follow the installation steps in the Basic Installation file.
- Configure the main section of the configuration file following the steps in Configuration Guide file.
- Start the desired daemons using the commands below. You may want to make these
systemd
daemons, if so follow the steps in the Basic Installation file.
Usage¶
pattoo_apid
has a simple command structure.
The daemon will require a configuration file in the etc/
directory. See the configuration section for details.
$ bin/pattoo_apid.py --help
usage: pattoo_apid.py [-h] [--start] [--stop] [--status] [--restart]
[--force]
optional arguments:
-h, --help show this help message and exit
--start Start the agent daemon.
--stop Stop the agent daemon.
--status Get daemon daemon status.
--restart Restart the agent daemon.
--force Stops or restarts the agent daemon ungracefully when used with --stop or
--restart.
$
Configuration¶
No additional configuration steps beyond that in the Configuration Guide file are required.
Testing¶
There are a number of steps you can take to make sure everything is OK.
- If you have setup the daemon for
systemd
then you can use thesystemctl
command to get the status of the daemon. - The daemon should be running on the port configured with the
ip_bind_port
parameter. Use thenetstat
command to verify this. - Visit the URL
http://localhost:20202/pattoo/api/v1/web/status
to get the status page. - Use the Performance and Troubleshooting for further steps to take
Making pattoo_apid
Start Automatically After Reboot¶
The easiest way to do this is to consider Configuring systemd Daemons. Otherwise you will need to manually restart the daemon after a reboot.
Pattoo Agent API Daemon¶
The pattoo_api_agentd
API daemon accepts data from remote pattoo
agents for storage in a database.
Installation¶
Follow these steps.
- Follow the installation steps in the Basic Installation file.
- Configure the main section of the configuration file following the steps in Configuration Guide file.
- Start the desired daemons using the commands below. You may want to make these
systemd
daemons, if so follow the steps in the Basic Installation file.
Usage¶
pattoo_api_agentd
has a simple command structure.
The daemon will require a configuration file in the etc/
directory. See the configuration section for details.
$ bin/pattoo_api_agentd.py --help
usage: pattoo_api_agentd.py [-h] [--start] [--stop] [--status] [--restart]
[--force]
optional arguments:
-h, --help show this help message and exit
--start Start the agent daemon.
--stop Stop the agent daemon.
--status Get daemon daemon status.
--restart Restart the agent daemon.
--force Stops or restarts the agent daemon ungracefully when used with --stop or
--restart.
$
Configuration¶
No additional configuration steps beyond that in the Configuration Guide file are required.
Testing¶
There are a number of steps you can take to make sure everything is OK.
- If you have setup the daemon for
systemd
then you can use thesystemctl
command to get the status of the daemon. - The daemon should be running on the port configured with the
ip_bind_port
parameter. Use thenetstat
command to verify this. - The
pattoo_api_agentd
temporarily stores all the data it receives frompattoo
agents in thecache/
directory. Check there for recent.json
files. - Visit the URL
http://localhost:20201/pattoo/api/v1/agent/status
to get the status page. - Use the Performance and Troubleshooting for further steps to take
Making pattoo_api_agentd
Start Automatically After Reboot¶
The easiest way to do this is to consider Configuring systemd Daemons. Otherwise you will need to manually restart the daemon after a reboot.
Pattoo Ingester Daemon¶
pattoo_ingesterd
batch processes agent data received by the pattoo
agent API daemon.
Installation¶
Follow these steps.
- Follow the installation steps in the Basic Installation file.
- Configure the main section of the configuration file following the steps in Configuration Guide file.
- Start the desired daemons using the commands below. You may want to make these
systemd
daemons, if so follow the steps in the Basic Installation file.
Usage¶
pattoo_ingesterd
has a simple command structure.
The daemon will require a configuration file in the etc/
directory. See the configuration section for details.
$ bin/pattoo_ingesterd.py --help
usage: pattoo_ingesterd.py [-h] [--start] [--stop] [--status] [--restart]
[--force]
optional arguments:
-h, --help show this help message and exit
--start Start the agent daemon.
--stop Stop the agent daemon.
--status Get daemon daemon status.
--restart Restart the agent daemon.
--force Stops or restarts the agent daemon ungracefully when used with --stop or
--restart.
$
Configuration¶
No additional configuration steps beyond that in the Configuration Guide file are required.
Testing¶
There are a number of steps you can take to make sure everything is OK.
- If you have setup the daemon for
systemd
then you can use thesystemctl
command to get the status of the daemon. - Use the Performance and Troubleshooting for further steps to take
The pattoo_ingester
¶
There is also a bin/pattoo_ingester.py
script that can be used as needed for troubleshooting. Here’s how to use it:
- Edit your
PATTOO_CONFIGDIR
path accordingly. - Stop the
pattoo_ingesterd
daemon. - Edit your
PATTOO_CONFIGDIR
path accordingly. - Check your log files for any possible errors.
Making pattoo_ingesterd
Start Automatically After Reboot¶
The easiest way to do this is to consider Configuring systemd Daemons. Otherwise you will need to manually restart the daemon after a reboot.
Using the CLI¶
How to use the Command Line Interface (CLI).
Using the CLI¶
The command line interface allows you to interact with the database in a number of ways.
Location of the CLI Script¶
The CLI script is located in the bin/
directory and is called bin/pattoo_cli.py
.
Running the CLI script without any parameters will display the usage options as seen below.
$ bin/pattoo_cli.py
usage: pattoo_cli.py [-h] {show,create,set,import,assign} ...
This program is the CLI interface to configuring pattoo
positional arguments:
{show,create,set,import,assign}
show Show contents of pattoo DB.
create Create entries in pattoo DB.
set Show contents of pattoo DB.
import Import data into the pattoo DB.
assign Assign contents of pattoo DB.
optional arguments:
-h, --help show this help message and exit
Language¶
pattoo
is meant to support multiple languages. The default language is English with a language code of en
. Agents do not post language specific data, but the keys used to define the data will need to be translated to descriptions that are meaningful to the end user.
Language translation files should be provided with any pattoo agent you install. You may have to create your own translation files for agents that poll data from non-standard data sources.
Viewing Languages¶
To view languages configured in the pattoo
database use the bin/pattoo_cli.py show language
command.
$ bin/pattoo_cli.py show language
idx_language code name
1 en English
Upadating Language Names¶
You can update the name of a language using the bin/pattoo_cli.py set language
command. You must specify the language code and provide a name using the --name
qualifier
$ bin/pattoo_cli.py set language --code 'en' --name 'English (Jamaican)'
In this example we have changed the name to ‘English (Jamaican)’
Creating Languages¶
To create a new language use the bin/pattoo_cli.py create language
command.
$ bin/pattoo_cli.py create language --code 'es' --name 'Spanish'
In this case we create a new language with the name “Spanish” and identifying code “es”
Agents¶
As stated before, pattoo agents
report data to the central pattoo
server.
Viewing Agents¶
To view the agents posting data to the pattoo
server use the bin/pattoo_cli.py show agent
command.
$ bin/pattoo_cli.py show agent
idx_agent agent_program agent_target enabled
1 pattoo_agent_snmp_ifmibd localhost 1
2 pattoo_agent_snmpd localhost 1
3 pattoo_agent_os_autonomousd nada 1
4 pattoo_agent_os_spoked nada 1
Assigning Agents to Key-Pair Translations Groups¶
There are some important things to know first.
1. Each agent has an idx_agent
number that can be seen in the first column of the bin/pattoo_cli.py show agent
command.
1. Each agent group has an idx_pair_xlate_group
number that can be seen in the first column of the bin/pattoo_cli.py show key_translation
command.
To assign an agent
to an agent group
use the bin/pattoo_cli.py assign agent
command.
$ bin/pattoo_cli.py assign agent --idx_agent 2 --idx_pair_xlate_group 4
In this case we have assigned agent with an idx_agent
agent number of 2
to the idx_pair_xlate_group
group number 4
Key-Pair Translations¶
Agents only post key-value pairs to the pattoo
server. Translations are short descriptions of what each key means. The aim is for you to see these descriptions instead of the keys when you look at pattoo
data with the pattoo-web
UI.
When a translation for a key reported by an agent
is installed, the translation is seen in pattoo-web
instead of the key itself. This makes pattoo
data more meaningful.
You don’t have to install translations for every agent
that reports data. You just have to assign agents
to agent groups
, then you assign a single set of translations to the agent group
.
Viewing Agent Group Key-Pair Translation Assignments¶
You can view these agent group
to translation group
assignments using the bin/pattoo_cli.py show key_translation_group
command.
$ bin/pattoo_cli.py show key_translation_group
idx_pair_xlate_group translation_group_name enabled
1 Pattoo Default 1
2 IfMIB Agents 1
3 OS Agents 1
Creating Translation Groups¶
To create a new translation group use the bin/pattoo_cli.py create key_translation
command.
$ bin/pattoo_cli.py create key_translation --name "Stock Market Symbol Translations"
In this case we create a new translation group with the name “Stock Market Symbol Translations”
Upadating Translation Group Names¶
You can update the name of a translation group using the bin/pattoo_cli.py set key_translation_group
command. You must specify the group’s idx_pair_xlate_group
value and a name.
$ bin/pattoo_cli.py set key_translation_group --idx_pair_xlate_group 20 --name 'New Translation Group Name'
In this example we have changed the name to ‘New Translation Group Name’ for idx_pair_xlate_group
20.
Viewing Agent Key-Pair Translation Groups¶
To view translation groups use the bin/pattoo_cli.py show key_translation
command.
$ bin/pattoo_cli.py show key_translation
idx_pair_xlate_group name language key translation units enabled
1 Pattoo Default 1
2 IfMIB Agents en pattoo_agent_snmp_ifmibd_ifalias Interface Alias 1
en pattoo_agent_snmp_ifmibd_ifdescr Interface Description
en pattoo_agent_snmp_ifmibd_ifhcinbroadcastpkts Interface Broadcast Packets (HC inbound) Packets / Second
en pattoo_agent_snmp_ifmibd_ifhcinmulticastpkts Interface Multicast Packets (HC inbound) Packets / Second
...
...
...
3 OS Agents en pattoo_agent_os_autonomousd_cpu_frequency CPU Frequency Frequency 1
en pattoo_agent_os_autonomousd_cpu_stats_ctx_switches CPU (Context Switches) Events / Second
en pattoo_agent_os_autonomousd_cpu_stats_interrupts CPU (Context Switches) Events / Second
en pattoo_agent_os_autonomousd_cpu_stats_soft_interrupts CPU (Soft Interrupts) Events / Second
en pattoo_agent_os_autonomousd_cpu_stats_syscalls CPU (System Calls) Events / Second
Creating Agent Key-Pair Translation Group CSV Files¶
Creating a CSV key-pair translation file is easy. Follow these steps.
Make sure the first row has the following headings separated by commas.
language,key,translation,units
Each subsequent row must have values that correspond to the headings. Each value must be separated by a comma.
1. The
language
must correspond to the language configured in yourpattoo.yaml
configuration file.pattoo-web
will only evaluate translation entries that match to the configured language. 1. Thekey
value must correspond to any expected keys from key-value pairs reported by an agent. 1. Thetranslation
must correspond to the brief text you want to use to describe thekey
1. Theunits
value is used to let users know the unit of measure to be used for the data being tracked by thekey
language,key,translation,units en,pattoo_agent_os_spoked_disk_io_write_bytes,Disk I/O (Bytes Written),Bytes / Second en,pattoo_agent_os_spoked_disk_io_write_count,Disk I/O (Write Count),Writes / Second en,pattoo_agent_os_spoked_disk_io_write_merged_count,Disk I/O (Write Merged Count),Writes / Second en,pattoo_agent_os_spoked_disk_io_write_time,Disk I/O (Write Time), en,pattoo_agent_os_spoked_disk_partition,Disk Partition, en,pattoo_agent_os_spoked_disk_partition_device,Disk Partition,
Not all key-value pairs will need
units
. For example,agent
metadata won’t have them. In this case don’t put a value forunits
and end the line with a comma (,
). The previous example shows three lines of translations includingunits
followed by three withoutunits
.
Importing Agent Key-Pair Translation Group Files¶
There are some important things to know first.
1. Each translation group
has an idx_pair_xlate_group
number that can be seen in the first column of the bin/pattoo_cli.py show key_translation_group
command.
1. The translations for the translation group
must be in a CSV file formatted according to the guidelines mentioned previously.
To import a translation file’s data and assign it to a translation group
use the bin/pattoo_cli.py import key_translation
command.
$ bin/pattoo_cli.py import key_translation --idx_pair_xlate_group 7 --filename agent_name_1_english.csv
In this case we have imported translations from a file named agent_name_1_english.csv
and assigned it to a translation group
with an idx_pair_xlate_group
number of 7
.
You only need to import translations for the key-pairs you require. Any previously existing translation for an key-pair configured in the file will be updated. key-pairs not in the file will not be updated.
Agent Translations¶
Not only do an agent’s key-pairs need translations, but the agents themselves need translations too. This is because an agent
only reports its name when posting which, through translations, allows pattoo
to be more flexible in supporting many different spoken languages.
Without translations, all references to a pattoo
agent will just be by its name, which could be confusing.
Viewing Agent Translations¶
To view agent translations use the bin/pattoo_cli.py show agent_translation
command.
$ bin/pattoo_cli.py show agent_translation
language agent_program translation enabled
en pattoo_agent_os_autonomousd Pattoo Standard OS Autonomous Agent 1
pattoo_agent_os_spoked Pattoo Standard OS Spoked Agent
pattoo_agent_snmpd Pattoo Standard SNMP Agent
pattoo_agent_snmp_ifmibd Pattoo Standard IfMIB SNMP Agent
pattoo_agent_modbustcpd Pattoo Standard Modbus TCP Agent
pattoo_agent_bacnetipd Pattoo Standard BACnet IP Agent
Creating Agent Translation CSV Files¶
Creating a CSV agent translation file is easy. Follow these steps.
Make sure the first row has the following headings separated by commas.
language,key,translation
Each subsequent row must have values that correspond to the headings. Each value must be separated by a comma.
1. The
language
must correspond to the language configured in yourpattoo.yaml
configuration file.pattoo-web
will only evaluate translation entries that match to the configured language. 1. Thekey
value must correspond to the name of an agent. 1. Thetranslation
must correspond to the brief text you want to use to describe thekey
language,key,translation
en,pattoo_agent_os_autonomousd,Pattoo Standard OS Autonomous Agent
en,pattoo_agent_os_spoked,Pattoo Standard OS Spoked Agent
en,pattoo_agent_snmpd,Pattoo Standard SNMP Agent
en,pattoo_agent_snmp_ifmibd,Pattoo Standard IfMIB SNMP Agent
en,pattoo_agent_modbustcpd,Pattoo Standard Modbus TCP Agent
en,pattoo_agent_bacnetipd,Pattoo Standard BACnet IP Agent
Importing Agent Translation Files¶
To import an agent translation file’s data use the bin/pattoo_cli.py import agent_translation
command.
$ bin/pattoo_cli.py import agent_translation --filename agent_name_translation_english.csv
In this case we have imported translations from a file named agent_name_translation_english.csv
.
You only need to import translations for the agents
you require. Any previously existing translation for an agent
configured in the file will be updated. agents
not in the file will not be updated.
Testing GraphQL Queries¶
Developer testing tools.
GraphQL API¶
You can use the pattoo API to retrieve data using a GraphQL interface. It’s best to become familiar with GraphQL before reading further.
After completing this tutorial you’ll be able to do programmatic GraphQL queries.
Queries with GraphQL¶
By default the pattoo
server will run on port TCP 20202.
Interactive GraphQL¶
Interactive GraphQL allows you to test your queries using your web browser.
If you are running it on your local machine go to the http://localhost:20202/pattoo/api/v1/web/igraphql to see the interactive query tool.
Non Interactive GraphQL¶
If you want to access GraphQL programmatically, without using your browser then you’ll need to access the non-interactive GraphQL URL.
If you are running it on your local machine go to the http://localhost:20202/pattoo/api/v1/web/graphql URL to get your results.
Retrieving GraphQL data with Pattoo-Web¶
You can use the get function in this file to get GraphQL data from the pattoo API server. https://github.com/PalisadoesFoundation/pattoo-web/blob/master/pattoo_web/phttp.py
How The Database Maps to GraphQL Queries¶
Note This section is very detailed, but it will help you with understanding how the GraphQL keywords required for your queries were created.
There are two important files in the repository’s pattoo/db directory.
- models.py: Defines the database structure using the python SQLAlchemy package
- schema.py: Maps the database structure from SQLAlchemy to GraphQL queries using the graphene-sqlalchemy package.
Models.py¶
This file defines the tables and columns in the database.
- Each class defines a table
- Each variable in the class defines the columns. The variable name is the column name
The python graphene-sqlalchemy package used to present GraphQL will convert column names into camelCase, removing any underscores. Therefore a column named idx_datapoint will be idxDatapoint in your GraphQL queries.
You will notice some tables will have foreign keys as part of the RDBMS structure. Here is an example in the AgentXlate table:
class AgentXlate(BASE):
"""Class defining the pt_agent_xlate table of the database."""
__tablename__ = 'pt_agent_xlate'
__table_args__ = (
UniqueConstraint('idx_language', 'agent_program'),
{'mysql_engine': 'InnoDB'}
)
idx_agent_xlate = Column(
BIGINT(unsigned=True), primary_key=True,
autoincrement=True, nullable=False)
idx_language = Column(
BIGINT(unsigned=True),
ForeignKey('pt_language.idx_language'),
index=True, nullable=False, server_default='1')
You will also notice that this class also has a backref relationship near the bottom. This is what graphene-sqlalchemy uses to track the relationships for queries. In this case, the backref has the name Agent_xlate_language which will be converted to agentXlateLanguage camelCase in your GraphQL queries
language = relationship(
Language,
backref=backref(
'Agent_xlate_language', uselist=True,cascade='delete,all'))
Schemas.py¶
This file contains the mappings from SQLAlchemy table definitions to GraphQL queries.
- Database tables defined as SQLAlchemy classes in models.py are imported as Model classes in this file.
- You’ll notice that if you manually type in your GraphQL queries in the /igraphql URL that you’ll see lists of each available table column with explanations. These explanations are defined in the Attribute classes in this file.
- Attributes and models are tied together in the SQLAlchemyObjectType classes.
from pattoo.db.models import AgentXlate as AgentXlateModel
class InstrumentedQuery(SQLAlchemyConnectionField):
"""Class to allow GraphQL filtering by SQlAlchemycolumn name."""
def __init__(self, type_, **kwargs):
...
...
...
class AgentXlateAttribute():
"""Descriptive attributes of the AgentXlate table.
A generic class to mutualize description of attributes for both queries
and mutations.
"""
idx_agent_xlate = graphene.String(
description='AgentXlate table index.')
idx_language = graphene.String(
description='Language table index (ForeignKey).')
agent_program = graphene.String(
resolver=resolve_agent_program,
description=('Agent progam'))
translation = graphene.String(
resolver=resolve_translation,
description='Translation of the agent program name.')
enabled = graphene.String(
description='"True" if enabled.')
class AgentXlate(SQLAlchemyObjectType, AgentXlateAttribute):
"""AgentXlate node."""
class Meta:
"""Define the metadata."""
model = AgentXlateModel
interfaces = (graphene.relay.Node,)
Next we’ll discuss the Query class you’ll find further down the file. This class:
- Uses the InstrumentedQuery class to filter queries by database column values. This InstrumentedQuery class makes things a lot easier. The graphene-sqlalchemy implementation of GraphQL has limited filtering capabilities. For example:
- Every row of every database table has a fixed unique automatically generated GraphQL ID which is a graphene.relay.node.GlobalID object. You can filter specifically on this ID.
- You also get lists of database row results containing the first X and last X rows.
- Lists of database row results can also be obtained for values before and/or after X GraphQL ID values retrieved from a database table.
- Custom filtering for specific values in a database column can be using resolvers, but you have to manually create a resolver for each table’s column. This per query customization is not ideal.
- Has Node entries for single value GraphQL queries, or as a definition inside an “edges” section of a GraphQL query. You can filter Nodes by the GraphQL graphene.relay.node.GlobalID too. This will be shown later.
class Query(graphene.ObjectType):
"""Define GraphQL queries."""
node = relay.Node.Field()
# Results as a single entry filtered by 'id' and as a list
agent_xlate = graphene.relay.Node.Field(AgentXlate)
all_agent_xlate = InstrumentedQuery(AgentXlate)
Query Examples¶
Here are some query examples using the example database table we have been using. Run these queries in the /igraphql url.
Note:
- In all the examples in this section the “id” represents the graphene.relay.node.GlobalID string. You can use this to get information on a specific row of a specific table.
- The InstrumentedQuery related queries in the Query class can only filter on a database table value, not the graphene.relay.node.GlobalID string.
Agent Table Queries¶
This section covers Agent table queries.
All Known Agents¶
This will provide information on all the known polling agents.
The agentProgram value will be used later for getting a translation into a meaningful name.
{
allAgent {
edges {
node {
id
idxAgent
agentPolledTarget
agentProgram
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
All Datapoints Polled by Agent where id = “X”¶
You’ll notice that this query also gives you the following information that will be required for translations later on: #. key-value pair key value for translating Datapoint metadata #. agentProgram for translating the program name into something meaningful #. idxPairXlateGroup for translating the key values
{
agent(id: "QWdlbnQ6Mg==") {
datapointAgent {
edges {
cursor
node {
id
idxDatapoint
idxAgent
agent {
agentProgram
agentPolledTarget
idxPairXlateGroup
pairXlateGroup {
id
}
}
glueDatapoint {
edges {
node {
pair {
key
value
}
}
}
}
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
}
All Charts in which Datapoints Polled by Agent appear. Where id = “X”¶
This query will show:
- All Datapoints for an Agent
- The charts to which each datapoint belongs
- The favorites to which the charts belong
{
agent(id: "QWdlbnQ6MQ==") {
datapointAgent {
edges {
cursor
node {
id
idxDatapoint
idxAgent
chartDatapointDatapoint {
edges {
node {
idxChartDatapoint
chart {
id
idxChart
name
checksum
favoriteChart {
edges {
node {
idxFavorite
}
}
}
}
}
}
}
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
}
DataPoint Table Queries¶
Here we have some representative queries you can do:
View All DataPoints¶
To see all DataPoints and their data enter this query on the left hand side of the viewer.
{
allDatapoints {
edges {
node {
id
idxDatapoint
checksum
dataType
lastTimestamp
pollingInterval
enabled
}
}
}
}
Here is the result of all DataPoints. Take note of (id: "RGF0YVBvaW50OjE=")
as we’ll use it for querying timeseries data.
{
"data": {
"allDatapoints": {
"edges": [
{
"node": {
"id": "RGF0YVBvaW50OjE=",
"idxDatapoint": "1",
"checksum": "ea5ee349b38fa7dc195b3689872c8487e7696201407ef27231b19be837fbc6da0847f5227f1813d893100802c70ffb18646e2097a848db0b7ea4ec15caced101",
"dataType": 99,
"lastTimestamp": 1575174588079,
"pollingInterval": 10000,
"enabled": "1"
}
},
{
"node": {
"id": "RGF0YVBvaW50OjI=",
"idxDatapoint": "2",
"checksum": "2b15d147330183c49a1672790bf09f54f8e849f9391c82385fd8758204e87940ab1ffef1bb67ac725de7cc0aa6aba9b6baeff34497ee494c38bee7f24eef65df",
"dataType": 99,
"lastTimestamp": 1575174588084,
"pollingInterval": 10000,
"enabled": "1"
}
}
]
}
}
}
Pair Table Queries¶
Here we have some representative queries you can do:
View All Key-Pair-Values¶
To see all Key-Pair-Values enter this query on the left hand side of the viewer.
{
allPairs {
edges {
node {
id
idxPair
key
value
}
}
}
}
Here is the result of all Key-Pair-Values.
{
"data": {
"allPairs": {
"edges": [
{
"node": {
"id": "UGFpcjox",
"idxPair": "1",
"key": "pattoo_agent_hostname",
"value": "palisadoes"
}
},
{
"node": {
"id": "UGFpcjoy",
"idxPair": "2",
"key": "pattoo_agent_id",
"value": "23a224313e4aaa4678a81638025ab02b42cb8a5b7c47b3dd2efced06d1a13d39"
}
},
{
"node": {
"id": "UGFpcjoz",
"idxPair": "3",
"key": "pattoo_agent_polled_device",
"value": "device.example.com"
}
},
{
"node": {
"id": "UGFpcjo0",
"idxPair": "4",
"key": "pattoo_agent_program",
"value": "pattoo_agent_modbustcpd"
}
}
]
}
}
}
Glue Table Queries¶
Here we have some representative queries you can do:
View All GluePoints¶
To see all GluePoints enter this query on the left hand side of the viewer. This table maps all the key-value pairs associated with an individual DataPoint
{
allGlues {
edges {
node {
id
idxPair
idxDatapoint
}
}
}
}
{
"data": {
"allGlues": {
"edges": [
{
"node": {
"id": "R2x1ZTooMSwgMSk=",
"idxPair": "1",
"idxDatapoint": "1"
}
},
{
"node": {
"id": "R2x1ZTooMSwgMik=",
"idxPair": "1",
"idxDatapoint": "2"
}
},
{
"node": {
"id": "R2x1ZTooMSwgMyk=",
"idxPair": "1",
"idxDatapoint": "3"
}
},
{
"node": {
"id": "R2x1ZTooMSwgNCk=",
"idxPair": "1",
"idxDatapoint": "4"
}
}
]
}
}
}
Data Table Queries¶
Here we have some representative queries you can do:
View All Numeric Timeseries Data for DataPoint id “x”¶
To see all numeric data for a specific datapoint (id: "RGF0YVBvaW50OjE=")
, enter this query on the left hand side of the viewer.
{
datapoint(id: "RGF0YVBvaW50OjE=") {
id
idxDatapoint
checksum
dataType
pollingInterval
dataChecksum {
edges {
node {
id
timestamp
value
}
}
}
}
}
Here is all the timeseries data from (id: "RGF0YVBvaW50OjE=")
.
{
"data": {
"datapoint": {
"id": "RGF0YVBvaW50OjE=",
"idxDatapoint": "1",
"checksum": "ea5ee349b38fa7dc195b3689872c8487e7696201407ef27231b19be837fbc6da0847f5227f1813d893100802c70ffb18646e2097a848db0b7ea4ec15caced101",
"dataType": 99,
"pollingInterval": 10000,
"dataChecksum": {
"edges": [
{
"node": {
"id": "RGF0YTooMSwgMTU3NTE3MjgzNTAyOCk=",
"timestamp": "1575172835028",
"value": "738.0000000000"
}
},
{
"node": {
"id": "RGF0YTooMSwgMTU3NTE3Mjg0NTIxOSk=",
"timestamp": "1575172845219",
"value": "738.0000000000"
}
},
{
"node": {
"id": "RGF0YTooMSwgMTU3NTE3Mjg1NTM2NCk=",
"timestamp": "1575172855364",
"value": "738.0000000000"
}
}
]
}
}
}
}
Language Table Queries¶
This query provides all the configured languages. The code returned is the language code. In the results, a code of en is english. Make translation queries based on this code value.
{
allLanguage {
edges {
node {
id
idxLanguage
code
name
}
}
}
}
Agent Translation Table Queries¶
This section outlines how to view Agent translation data.
All Agent Translation Table Entries¶
You can use this query to get the translation for an agentProgram name for a specific language.This is useful for the home page.
{
allAgentXlate {
edges {
node {
id
idxAgentXlate
idxLanguage
agentProgram
translation
enabled
tsCreated
tsModified
language {
id
name
code
idxLanguage
}
}
}
}
}
Translation for a Specific agentProgram (all Languages)¶
In this case we get translations for the agentProgram named pattoo_agent_snmp_ifmibd.
{
allAgentXlate(agentProgram: "pattoo_agent_snmp_ifmibd") {
edges {
node {
id
idxAgentXlate
idxLanguage
agentProgram
translation
enabled
tsCreated
tsModified
}
}
}
}
Single Node from Agent Translation table filtered by an ID¶
In this case:
- The ID is a graphene.relay.node.GlobalID string.
- The translation for the agentProgram is in the “translation” field.
{
agentXlate(id: "QWdlbnRYbGF0ZToy") {
id
idxAgentXlate
idxLanguage
agentProgram
translation
enabled
tsCreated
tsModified
}
}
Filtered Agent Translation table entry with Language where idxAgentXlate = “4”¶
There are some things to note:
- This will provide a list of translations for all configured languages. The translation for the agentProgram is in the “translation” field.
- Normally you’d be able to filter by “id” with GraphQL. Unfortunately this capability was lost when we added the customized ability to filter by any database table column. Hopefully the Python Graphene (GraphQL) team will be able to fix this later as part of their standard build.
{
allAgentXlate(idxAgentXlate: "4") {
edges {
node {
id
idxAgentXlate
idxLanguage
agentProgram
translation
enabled
tsCreated
tsModified
language {
id
name
}
}
}
}
}
Key-Pair Translation Queries¶
This section outlines how to view key-pair translation data.
View all key-pair Translations¶
Here’s the query you’ll need to view all translations:
{
allPairXlate {
edges {
node {
id
idxLanguage
idxPairXlate
idxPairXlateGroup
key
translation
}
}
}
}
View key-pair Translations for idxPairXlateGroup = “x”¶
In this example, we filter by idxPairXlateGroup
{
allPairXlate (idxPairXlateGroup: "2"){
edges {
node {
id
idxLanguage
idxPairXlate
idxPairXlateGroup
key
translation
}
}
}
}
Favorites Table Queries¶
This section outlines how to view favorites data.
View all Favorites and Their Assigned Charts¶
This is the query string you’ll need to see all the favorites in the database.
{
allFavorite {
edges {
node {
id
idxFavorite
order
user {
id
idxUser
username
firstName
lastName
}
chart {
name
chartDatapointChart {
edges {
node {
idxDatapoint
}
}
}
}
}
}
}
}
User Table Queries¶
This section outlines how to view favorites data.
View all Favorites for All Users¶
This query will show:
- All users
- Their favorites
- The charts associated with each favorite
{
allUser {
edges {
node {
id
username
firstName
lastName
enabled
favoriteUser {
edges {
node {
order
chart {
id
idxChart
name
}
}
}
}
}
}
}
}
View all Favorites for a Specific User (by filter other than ID)¶
This query will show:
- The filtered username (“pattoo”)
- Its favorites
- The charts associated with each favorite
{
allUser(username: "pattoo") {
edges {
node {
id
username
favoriteUser {
edges {
node {
order
chart {
id
idxChart
name
}
}
}
}
}
}
}
}
View all Favorites for a Specific User (by ID)¶
This query will show:
- The user
- Its favorites
- The charts associated with each favorite
{
user(id: "VXNlcjox") {
id
username
favoriteUser {
edges {
node {
order
chart {
id
idxChart
name
}
}
}
}
}
}
Authenticate Username and Password¶
This is a custom query that requires you enter a username and password. Regular query results are returned when found, a Null result is returned upon failure.
{
authenticate(username: "palisadoes@example.org", password: "123456") {
id
}
}
Results are returned when found.
{
"data": {
"authenticate": [
{
"id": "VXNlcjo3"
}
]
}
}
A Null result is returned when not found.
{
"data": {
"authenticate": null
}
}
Pagination¶
This section outlines how to do simple pagination
View all Datapoints¶
This query will return all Datapoint values.
{
allDatapoints {
edges {
node {
idxDatapoint
idxAgent
id
tsCreated
tsModified
}
}
}
}
View First X Datapoints¶
It’s important to note the startCursor and endCursor values when wanting to paginate. They are useful in subsequent queries where you may want ranges of values that are not relative to the very start and very end of database table rows.
{
allDatapoints(first: x) {
edges {
node {
idxDatapoint
idxAgent
id
tsCreated
tsModified
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
View Last X Datapoints¶
It’s important to note the startCursor and endCursor values when wanting to paginate. They are useful in subsequent queries where you may want ranges of values that are not relative to the very start and very end of database table rows.
{
allDatapoints(last: x) {
edges {
node {
idxDatapoint
idxAgent
id
tsCreated
tsModified
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
Next X Datapoints¶
Note:
- It’s important to note the endCursor of the previous query.
- The next X results would need a query like the one below, starting at the endCursor value of the previous query.
{
allDatapoints(first: X, after: "END_CURSOR_VALUE") {
edges {
node {
idxDatapoint
idxAgent
id
tsCreated
tsModified
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
Previous X Datapoints¶
Note:
- It’s important to note the startCursor of the previous query.
- The previous X results would need a query like the one below, starting at the startCursor value of the previous query.
{
allDatapoints(last: X, before: "START_CURSOR_VALUE") {
edges {
node {
idxDatapoint
idxAgent
id
tsCreated
tsModified
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
Mutation Examples¶
Mutation is the terminology that GraphQL uses for database updates. Here are some query examples using the example database table we have been using. Run these queries in the /igraphql url.
Chart Table Mutation¶
This section outlines how to mutate chart data.
Add a New Chart¶
This mutation will add the chart then return the resulting fields:
- id
- name
- Enabled status
mutation {
createChart(Input: {name: "Flying Fish"}) {
chart {
id
name
enabled
}
}
}
{
"data": {
"createChart": {
"chart": {
"id": "Q2hhcnQ6MjM5",
"name": "Flying Fish",
"enabled": "1"
}
}
}
}
Modify Chart Name¶
This mutation will change the chart name from “Flying Fish” to “Teddy Bear”:
mutation {
updateChart(Input: {idxChart: "239", name: "Teddy Bear"}) {
chart {
id
name
enabled
}
}
}
{
"data": {
"updateChart": {
"chart": {
"id": "Q2hhcnQ6MjM5",
"name": "Teddy Bear",
"enabled": "1"
}
}
}
}
ChartDataPoint Table Mutation¶
This section outlines how to mutate ChartDataPoint data.
Add a New ChartDataPoint¶
This mutation will add a DataPoint to an existing chart then return the resulting fields:
mutation {
createChartDataPoint(Input: {idxDatapoint: "3", idxChart: "239"}) {
chartDatapoint {
id
idxChartDatapoint
idxDatapoint
idxChart
}
}
}
{
"data": {
"createChartDataPoint": {
"chartDatapoint": {
"id": "Q2hhcnREYXRhUG9pbnQ6MjQy",
"idxChartDatapoint": "242",
"idxDatapoint": "3",
"idxChart": "239"
}
}
}
}
Modify ChartDataPoint Name¶
This mutation will remove a DataPoint from the ChartDataPoint entry (Disable the entry for the chart):
mutation {
updateChartDataPoint(Input: {idxChartDatapoint: "242", enabled: "0"}) {
chartDatapoint {
id
idxChartDatapoint
idxDatapoint
idxChart
enabled
}
}
}
{
"data": {
"updateChartDataPoint": {
"chartDatapoint": {
"id": "Q2hhcnREYXRhUG9pbnQ6MjQy",
"idxChartDatapoint": "242",
"idxDatapoint": "3",
"idxChart": "239",
"enabled": "0"
}
}
}
}
User Table Mutation¶
This section outlines how to mutate user data.
Add a New User¶
This mutation will add a User then return the resulting fields:
mutation {
createUser(Input: {username: "foo@example.org", firstName: "Foo", lastName: "Fighter", password: "123456"}) {
user {
id
idxUser
firstName
lastName
username
enabled
}
}
}
{
"data": {
"createUser": {
"user": {
"id": "VXNlcjoz",
"idxUser": "3",
"firstName": "Foo",
"lastName": "Fighter",
"username": "foo@example.org",
"enabled": "1"
}
}
}
}
Modify User FirstName¶
This mutation will remove a DataPoint from the ChartDataPoint entry (Disable the entry for the chart):
mutation {
updateUser(Input: {idxUser: "3", firstName: "Street"}) {
user {
idxUser
firstName
lastName
username
enabled
}
}
}
{
"data": {
"updateUser": {
"user": {
"idxUser": "3",
"firstName": "Street",
"lastName": "Fighter",
"username": "foo@example.org",
"enabled": "1"
}
}
}
}
Favorite Table Mutation¶
This section outlines how to mutate favorite data.
Add a New Favorite¶
This mutation will add a Favorite then return the resulting fields:
mutation {
createFavorite(Input: {idxUser: "3", idxChart: "149", order: "2"}) {
favorite{
id
idxFavorite
idxChart
idxUser
enabled
}
}
}
{
"data": {
"createFavorite": {
"favorite": {
"id": "RmF2b3JpdGU6Mg==",
"idxFavorite": "2",
"idxChart": "149",
"idxUser": "3",
"enabled": "1"
}
}
}
}
Modify Favorite¶
This mutation will remove the Favorite entry (Disable the entry):
mutation {
updateFavorite(Input: {idxFavorite: "2", enabled: "0"}) {
favorite {
idxFavorite
idxChart
idxUser
enabled
}
}
}
{
"data": {
"updateFavorite": {
"favorite": {
"idxFavorite": "2",
"idxChart": "149",
"idxUser": "3",
"enabled": "0"
}
}
}
}
Queries with REST¶
It’s best to become familiar with REST before trying these tests.
Here are some things to remember.
- By default the
pattoo
server will run on port TCP 20202. - If you are running it on your local machine the RESTful API URLs will all start with http://localhost:20202/pattoo/api/v1/web/rest. All the examples assume make reference to this fact. So if the uri
/data
is mentioned then assume we are referring to the complete URL of http://localhost:20202/pattoo/api/v1/web/rest/data
Let’s begin.
Why a RESTful Interface?¶
We provide a RESTful interface for ease of comparison with GraphQL for a limited set of functions. There will be no further development of the RESTful beyond what is listed here. Do not write any pattoo
related code based on REST. This feature is deprecated and will soon be removed.
Using the RESTful Interface (Deprecated)¶
View DataPoint data¶
To view data for generated by a specific DataPoint visit the /data
URI. Add the idx_datapoint
value to the end to get /data/1
for idx_datapoint
value of 1.
- By default a week’s worth of data is returned.
- There is no ability to get data for all DataPoints simultaneously.
- You can use the
?secondsago=X
query string to get data startingX
seconds ago to the most recently stored data.
In this case we have data from /data/1?secondsago=3600
[
{
"1573619400" : 3878839847
},
{
"1573619700" : 3879239629
},
{
"1573620000" : 3879652192
},
{
"1573620300" : 3880050372
},
{
"1573620600" : 3880449410
},
{
"1573620900" : 3880856015
},
{
"1573621200" : 3881272430
},
{
"1573621500" : 3881704477
},
{
"1573621800" : 3882250116
},
{
"1573622100" : 3882650025
},
{
"1573622400" : 3883064936
}
]
Miscellaneous Information¶
Technical background information on the project.
Creating pattoo
Agents¶
Documentation on how to create your own custom agents can be found here.
Performance and Troubleshooting¶
Performance tuning and troubleshooting are related. So we created a page for both!
Troubleshooting¶
Troubleshooting steps can be found in the PattooShared troubleshooting documentation
pattoo
Performance Tuning¶
There are a number of ways to improve pattoo
performance.
Use RAM disks for Caching¶
We have seen a 10X improvement in the pattoo_ingester
records / second performance when using a RAM disk versus SSDs. We recommend using RAM disks and SSDs for your cache directory over regular hard drives in production environments.
Run the pattoo_ingester
More Frequently¶
The pattoo_ingester
needs to run periodically to import agent data files into the database. You want to ensure that it can keep up with this task. Check your logs to make sure that the completion time of each pattoo_ingester
run is less than the configured polling_interval
. Increase the crontab
frequency if it isn’t.
Database Performance Improvements¶
The pattoo_ingester
makes many connections to the database. You have a number of options if it crashes. Check your logs for the cause of errors to help you choose the best corrective action.
If the errors state that you have too many connections, then increase
max_connections
value in the server configuration file. The default is 200. Try 300 and increase as needed.[mysqld] max_connections = 300
If the errors mention
pool_size
ormax_overflow
, then edit your configuration file and adjust those values.db_pool_size: 10 db_max_overflow: 10
Reduce Logging¶
The default pattoo
debug
logging level can create large files. This is done to make it easier to troubleshoot the initial installation. Set the level to info
for most scenarios.
JSON Formatting for pattoo-agents¶
JSON data formatting can be found in the Pattoo Shared data documentation
Pattoo Terminology¶
A complete glossary of terms can be found in the Pattoo Shared glossary documentation
Developers¶
How To Contribute¶
Start contributing today!
Introduction¶
Below is the workflow for having your contribution accepted into the pattoo
repository.
Create an Issue or comment on an existing issue to discuss the feature
If the feature is approved, assign the issue to yourself
Fork the project
Clone the fork to your local machine
Add the original project as a remote (git remote add upstream https://github.com/PalisadoesFoundation/pattoo, check with: git remote -v)
Create a topic branch for your change (git checkout -b
BranchName
)you may create additional branches if modifying multiple parts of the code
Write code and Commit your changes locally. An example of a proper
git commit
message can be seen below:When you need to synch with upstream (pull the latest changes from main repo into your current branch), do:
git fetch upstream
git merge upstream/master
Check for unnecessary white space with
git diff --check
.Write the necessary unit tests for your changes.
Run all the tests to assure nothing else was accidentally broken
Push your changes to your forked repository (git push origin
branch
)Perform a pull request on GitHub
Your code will be reviewed
If your code passes review, your pull request will be accepted
Code Style Guide¶
For ease of readability and maintainability code for all pattoo
projects must follow these guidelines. Code that does not comply will not be added to the master
branch.
- All
pattoo
projects use the Google Python Style Guide for general style requirements - All
pattoo
python projects use the The Chromium Projects Python Style Guidelines for docstrings. - Indentations must be multiples of 4 blank spaces. No tabs.
- All strings must be enclosed in single quotes
- In addition too being
pylint
compliant, the code must be PEP8 and PEP257 compliant too. - There should be no trailing spaces in files
Guidelines to remember¶
- Always opt for the most pythonic solution to a problem
- Avoid applying idioms from other programming languages
- Import each module with its full path name. ie: from pack.subpack import module
- Use exceptions where appropriate
- Use doc strings
- Try not to have returns at multiple points in a function unless they are failure state returns.
- If you are in the middle of a development session and have to interrupt your work, it is a good idea to write a broken unit test about what you want to develop next. When coming back to work, you will have a pointer to where you were and get back on track faster.
Commits¶
The pattoo
projects strive to maintain a proper log of development through well structured git commits. The links below offer insight and advice on the topic of commit messages:
Sample .vimrc File for Compliance¶
You can use this sample .vimrc file to help meet our style requirements
Testing Your Code¶
Make sure you create your own unittests for all the classes, methods, and functions you have created or modified. Place them in the tests/ directory in a subdirectory that matches the relative location of your production code under the pattoo/ directory.
Create Unittest Database¶
Assuming you already have the pattoo database set up, these steps will copy the contents of the pattoo database to a new pattoo_unittest database so that it can be used by the local unittests.
- ::
- $ mysqldump -u root -p pattoo > pattoo.sql Enter password: $ mysql -u root -p pattoo_unittest < pattoo.sql Enter password:
Database Setup¶
The unittests assume that a MySQL / MariaDB testing database has been created with the following parameters:
- db_hostname: localhost
- db_username: travis
- db_password: K2nJ8kFdthEbuwXE
- db_name: pattoo_unittest
Create a database and grant full privileges to the travis user.
# mysql
MariaDB [(none)]> CREATE DATABASE pattoo_unittest;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON pattoo_unittest.* TO 'travis'@'localhost' identified by 'K2nJ8kFdthEbuwXE';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit;
#
Setting up Syslog Error Codes¶
pattoo uses unique error code numbers for syslog messages to make troubleshooting easier. Run the tests/bin/error_code_report.py script before the unittests to make there are no duplicates. The unittests will fail if there are duplicates.
$ tests/bin/error_code_report.py
Pattoo Logging Error Code Summary Report
----------------------------------------
Starting Code : 20001
Ending Code : 20141
Duplicate Codes to Resolve : []
Available Codes : [20141, 20142, 20143, 20144, 20145]
$
Everything is OK if there are no Duplicate Codes to Resolve.
Running Tests¶
The tests/bin/do_all_tests.py script will recursively run all unittests in the tests/ directory.