Newer
Older
.. _section-development:
Development
================================================================================
This is the documentation for developers of the Mentat library itself, or developers
of components and modules usable by or pluggable into the Mentat system.
Key information
--------------------------------------------------------------------------------
* `Project Mentat: official website <https://mentat.cesnet.cz/en/index>`__
* `Project Warden: official website <https://warden.cesnet.cz/en/index>`__
* `IDEA: official website <https://idea.cesnet.cz/en/index>`__
* `Project issue tracking system (Redmine) <https://homeproj.cesnet.cz/projects/mentat>`__
* `Primary source code repository (Git) <https://homeproj.cesnet.cz/git/mentat-ng.git/>`__
* `Automated build system (Alchemist) <https://alchemist.cesnet.cz>`__
Getting the code
--------------------------------------------------------------------------------
We are using the `Git <https://git-scm.com/>`__ SCM system to manage our codebase.
Use following command to clone the repository without the push privileges::
$ git clone --recurse-submodules https://homeproj.cesnet.cz/git/mentat-ng.git/ mentat-ng
$ cd mentat-ng
Please note the use of ``--recurse-submodules`` option. We are using submodules
in our project and some options may be unavailable to you without them present
(like generating documentation locally).
General guidelines
--------------------------------------------------------------------------------
* Let `PEP 20 <https://www.python.org/dev/peps/pep-0020/>`__ be the guide for your mind.
* Let `PEP 8 <https://www.python.org/dev/peps/pep-0008/>`__ be the guide for your hand.
* Let you and `PEP 257 <https://www.python.org/dev/peps/pep-0257/>`__ and `PEP 287 <https://www.python.org/dev/peps/pep-0287/>`__ be the guide for others.
* Use `Sphinx-doc <http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`__ format to document the code.
* Pull and merge often.
* Use *devel* branch for small updates and bugfixes.
* For bigger features fork *devel*, merge after accepting, delete branch.
* Use *release* branch only for code that is ready to be released into production.
* Use *master* branch only for production level and stable code.
* *master* and *release* branches **must not** break unittests, lint or build in general. *devel* branch should not.
* Unless you have been explicitly allowed to, do not use *master* and *release* branches.
* New feature should be accompanied with unit tests.
* Do not introduce new dependencies into core library. Dependent code should go into its own submodule, so dependency can be runtime and enforced by system administrator if necessary, but not by library.
* Reuse existing (even soft) dependencies. There is no need to use three competing IP address libraries. However, do not prevent application developer to use different one in his app, should he need to.
--------------------------------------------------------------------------------
There is a project master *Makefile* in the root of the project repository which
can perform various essential or useful development tasks. You can get the full
list of all available make commands/targets by executing one of the following
commands::
Of course you need to have *make* utility installed on your system, on Debian-based
system you can use following command::
$ aptitude install make
Development prerequisites
````````````````````````````````````````````````````````````````````````````````
There are several development prerequisites, that already have to be present on
your development machine. These prerequisites are not installed automatically for
you, because the installation is too complex, too customizable or simply best to
be performed by the user himself. These prerequisites currently are:
* `Python 3 <https://www.python.org/>`__: Please use version similar to current stable Python3 release on current stable Debian release (`current <https://packages.debian.org/stretch/python3>`__).
* `Pip <https://pip.pypa.io/en/stable/>`__: Python package manager, we recommend installation with `get-pip.py <https://pip.pypa.io/en/stable/installing/#installing-with-get-pip-py>`__ to get the latest release, you may sometimes encounter weird bugs when installing newer packages with old versions of pip.
* `Yarn <https://yarnpkg.com/en/>`__: NPM package manager for web interface libraries. This package manager is responsible for managing frontend development libraries like jQuery, Bootstrap, D3 etc.
* `Grunt <https://gruntjs.com/>`__: JavaScript task runner for web interface development. It is responsible for taking care of frontend related tasks like JavaScript and CSS minification
* `PostgreSQL 11 <https://www.postgresql.org/>`__: Relational database, used for persistent data storage. Please use version 11 wherever possible.
You can check for presence of all of these dependencies with this handy make target:
# Check for presence of all prerequisites:
$ make deps-prerequisites
In case you get any errors please follow the official documentation to install the
missing prerequisite.
Preparing development environment
````````````````````````````````````````````````````````````````````````````````
If you want to participate on the development of this project there is a handy
make target that will make all preparations for you to get you started as soon as
possible. Please execute the following command from the root directory of the
cloned repository to initialize correct Python virtual environment, install all
requirements (including those required only for development) and finally install
the project locally in editable mode:
# Bootstrap Python virtual environment for development:
$ make venv
# Activate virtual environment before any development work:
$ . venv/bin/activate
# Perform the installation magic:
(venv) $ make develop
# Deactivate virtual environment when it is not needed anymore with:
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
Dependencies
````````````````````````````````````````````````````````````````````````````````
There is a number of makefile targets called ``deps`` and ``deps-`` that are responsible
for helping with dependency management. Please study the ``make help`` output to
view the list of available targets.
If your code requires some additional third party dependencies please follow these
procedures:
* Debian dependencies
* Debian dependencies must be specified in the ``deploy/mentat/ctrl/control.tmpl``
file. Please study the `documentation <https://www.debian.org/doc/debian-policy/ch-controlfields.html#binary-package-control-files-debian-control>`__ to correctly
use Debian dependency system.
* Python dependencies
* Use `pip <https://pip.pypa.io/en/stable/reference/>`__ command to manage Python
dependencies.
* Dependencies that are always required must be listed in ``conf/requirements.pip``
file (including version) and in ``conf/requirements-latest.pip`` file (without
version).
* Dependencies that are required only for development must be listed in ``conf/requirements-dev.pip``
file (including version) and in ``conf/requirements-latest-dev.pip`` file (without
version).
* In this project it is preferred to use pip for native Python dependencies. In
some cases you may however choose to use Debian package for pulling in the
required library instead.
* Web interface dependencies
* Use `yarn <https://yarnpkg.com/en/docs/usage>`_ command to manage frontend
dependencies.
Example workflow for adding Python dependency::
# Install library locally:
(venv) $ pip install flask
# Get the version of the library:
(venv) $ pip freeze | grep -i flask
# Now write the library name with version to `conf/requirements.pip` and
# without version to `conf/requirements-latest.pip`.
# In case the library is required only for development write the library name
# with version to `conf/requirements-dev.pip` and without version to
# `conf/requirements-latest-dev.pip`.
# Make sure the dependency gets installed also using the makefile target:
(venv) $ make deps-python
(venv) $ make deps-python-dev
Example workflow for adding frontend dependency::
# Install dependency with yarn:
(venv) $ yarn add jquery
# Install development dependency with yarn:
(venv) $ yarn add grunt --dev
# Make sure the dependency gets installed also using the makefile target:
(venv) $ make deps-webui
For upgrading all the dependencies to latest versions you may use following make
targets::
# Activate virtual environment before any development work:
$ . venv/bin/activate
(venv) $ make deps-python-upgrade
(venv) $ make deps-python-upgrade-dev
(venv) $ make deps-webui-upgrade
Jan Mach
committed
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
Running development version of Mentat system
````````````````````````````````````````````````````````````````````````````````
Mentat system can be executed from within the Git repository. We worked hard to
make sure it will not wander around your filesystem. The key to make everything
work is the environment variable ``APP_ROOT_PATH``, which controls the base root
of the application. It is basically a soft implementation of a very lightweight
chroot. Application can adjust various filesystem paths to the value of this
variable. During the preparation of development environment a local ``./chroot``
subdirectory was prepared automatically for you. You may use it in a following
fashion::
# A: Use it manually, be carefull to provide the APP_ROOR_PATH as absolute path:
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) mentat-controller.py --command start
# B: For your convenience there is also a makefile target:
(venv) $ make run-mentat-dev
For your convenience there is a very handy makefile target ``ctrl-mentat-dev``,
which is capable of passing commands to your local development instance of
:ref:`section-bin-mentat-controller`. You may use it in a following fashion::
# This:
(venv) $ make ctrl-mentat-dev COMMAND=start
# Is same as this:
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) mentat-controller.py --command start
# This:
(venv) $ make ctrl-mentat-dev COMMAND=status
# Is same as this:
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) mentat-controller.py --command status
# This:
(venv) $ make ctrl-mentat-dev COMMAND=stop
# Is same as this:
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) mentat-controller.py --command stop
Make sure to read following documentation sections to understand the usage of the
Mentat system and its various components:
* :ref:`section-quickstart`
Running development web server
````````````````````````````````````````````````````````````````````````````````
The web interface for this project is written in excellent `Flask <http://flask.pocoo.org/>`__
microframework, that comes with built-in webserver for development. It can be
launched in following ways::
# A: You may use the Flask built-in command in a following way:
Jan Mach
committed
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) FLASK_APP=hawat FLASK_ENV=development FLASK_CONFIG=development FLASK_CONFIG_FILE=$(realpath ./hawat.local.conf) flask run
# B: You may custom command line interface to launch webserver in development
# mode and with development configuration:
Jan Mach
committed
(venv) $ APP_ROOT_PATH=$(realpath ./chroot) FLASK_ENV=development FLASK_CONFIG=development FLASK_CONFIG_FILE=$(realpath ./hawat.local.conf) hawat-cli run
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# C: Use following makefile target to do the same as the three above with less
# typing:
(venv) $ make run-webui-dev
There are following environment variables you may use to tweak the application
launch according to your needs:
* ``FLASK_DEBUG``
This configuration controls state of the internal debugger independently on the
``FLASK_ENV`` setting. It is a boolean value and should be either ``True`` or
``False``. Default value is ``False``.
* ``FLASK_ENV``
This configuration controls application environment setting. This is a string
value and should be either ``development`` or ``production``. Default value is
``production``.
* ``FLASK_CONFIG``
This configuration controls the name of the configuration class from :py:mod:`mydojo.config`
module that will be used to configure the application. Valid value is one of the
:py:attr:`mydojo.config.CONFIG_MAP`. Default value is ``default``.
* ``FLASK_CONFIG_FILE``
This configuration controls the name of the configuration file that will be used
to further configure the application. Values in this file are applied last and
will override anything in the configuration classes from :py:mod:`mydojo.config`.
Default value is empty. It must point to existing file if set, otherwise an exception
will be raised. Please use absolute path to the file to avoid any surprises.
.. note::
The ``FLASK_CONFIG_FILE`` is especially handy for customizing the local
application configuration during development process or during deployment.
For more information please study following resources:
* `Flask: Command Line Interface <http://flask.pocoo.org/docs/1.0/cli/>`__
* `Flask: Configuration Handling <http://flask.pocoo.org/docs/1.0/config/>`__
* `Flask API: Configuration <http://flask.pocoo.org/docs/1.0/api/#configuration>`__
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
Documentation
````````````````````````````````````````````````````````````````````````````````
The project documentation consists of the part generated directly from the source
code docstrings and of the part written manually. It is generated using the
`Sphinx-doc <http://www.sphinx-doc.org/en/stable/contents.html>`__ tool into various
formats. Please use `RST <http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`__
markup features where appropriate to increase readability and cross-reference to
related content. It should however still be possible to view the documentation of
all Python modules in *Pythonic* way via `pydoc3 <https://docs.python.org/3/library/pydoc.html>`__
and the result should still be more or less readable. Please test it immediately with:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ pydoc3 ./path/to/module.py
You may generate and review the documentation locally by executing the following
command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make docs
# View the documentation in your default web browser:
(venv) $ make docs-view
# When necessary you may also remove all documentation related artifacts and
# rebuild:
(venv) $ make clean-build-docs
(venv) $ make docs
(venv) $ make docs-view
Documentation will be generated into ``doc/sphinx/_build/html/manual.html``.
Important resources for you to study:
* `pydoc3 <https://docs.python.org/3/library/pydoc.html>`__
* `Sphinx-doc <http://www.sphinx-doc.org/en/stable/contents.html>`__
* `reStructuredText Primer <http://www.sphinx-doc.org/en/stable/rest.html>`__
* `Sphinx markup constructs <http://www.sphinx-doc.org/en/stable/markup/index.html>`__
* `The Python domain <http://www.sphinx-doc.org/en/stable/domains.html#the-python-domain>`__
* `Documenting functions and methods <http://www.sphinx-doc.org/en/stable/domains.html#info-field-lists>`__
Internationalization and translations
````````````````````````````````````````````````````````````````````````````````
The web interface and some other parts of the system are localized to provide best
experience for target user. Following libraries are used to accomplish this task:
* `pybabel <http://babel.pocoo.org/en/latest/index.html>`__
* `flask-babel <https://pythonhosted.org/Flask-Babel/>`__
The web interface translations are included in the :py:mod:`hawat` module. The most
important files are following:
* ``lib/hawat/babel.cfg`` - Babel configuration file
* ``lib/hawat/messages.pot`` - Extracted translations, generated automatically
* ``lib/hawat/translations/`` - Directory containing translations to various languages
Strings in the python source code are marked for translation when you wrap them
in one of the following functions: ``gettext()``, ``lazy_gettext()``, ``tr_()``.
The last one is defined internally and is used for translating constants or enums.
Strings in the Jinja2 templates are marked for translation when you wrap them with
``gettext()`` or ``_()`` functions.
After adding new strings into the web interface that will need translating please
follow this procedure::
# Pull (extract and update) all translation strings into message catalogs:
(venv) $ make hpybabel-update
# Now please edit the translation files. For example for czech locale please
# edit file ``lib/hawat/translations/cs/messages.po``.
# When you are happy with your translations compile the message catalogs with:
(venv) $ make hpybabel-compile
Jan Mach
committed
Similarly the ``make mpybabel-update`` and ``make hpybabel-compile`` targets can be
used to compile translations of Mentat reporting templates. These are located in
following directories:
* ``conf/templates/informant/``: Report templates for :ref:`section-bin-mentat-informant`.
* ``conf/templates/reporter/``: Report templates for :ref:`section-bin-mentat-reporter`.
* ``conf/templates/utest/``: Templates for library unit tests.
Checking code with Pyflakes
````````````````````````````````````````````````````````````````````````````````
You may check the whole codebase with `Pyflakes <https://github.com/PyCQA/pyflakes>`__
tool by executing following command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make pyflakes
Or you may check just the single file by executing following command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ cd lib
(venv) $ pyflakes path/to/module.py
Important resources:
* `pyflakes <https://github.com/PyCQA/pyflakes>`__
Checking code with Pylint
````````````````````````````````````````````````````````````````````````````````
You may check the whole codebase with `Pylint <https://pylint.readthedocs.io/en/latest/>`__
tool by executing following command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make pylint
Or you may check just the single file by executing following command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ cd lib
(venv) $ pylint --rcfile=../.pylintrc-lib path/to/module.py
Important resources:
* `pylint <https://pylint.readthedocs.io/en/latest/>`__
Running unit tests
````````````````````````````````````````````````````````````````````````````````
You may run prepared unit tests on the whole codebase by executing the following
command:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make test
Important resources:
* `nosetests <http://nose.readthedocs.io/en/latest/>`__
Building web interface
````````````````````````````````````````````````````````````````````````````````
The web interface development requires certain specific tasks like copying third
party libraries from ``node_modules`` directory to correct locations, JavaScript
and CSS minifications etc. When you are developing web interface following makefile
target will be very handy to you:
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make build-webui
Database schema migrations
--------------------------------------------------------------------------------
Event database migrations
````````````````````````````````````````````````````````````````````````````````
Due to the performance reasons the event database abstraction layer is implemented
directly on top of the `psycopg2 <http://initd.org/psycopg/>`__ driver. To be
consistent with metadata database migrations we are using separate configured instance
of `Alembic <https://alembic.sqlalchemy.org/en/latest/index.html>`__ database
migration utility. The migration environment is located in ``migrations-events``
subdirectory.
To create new migration during development follow these steps::
cd migrations-events
alembic revision -m "revision description"
Now edit the generated revision file to suit your needs. You may wish to use
following resources as reference:
* `Operation Reference <https://alembic.sqlalchemy.org/en/latest/ops.html>`__
* `Cookbook <https://alembic.sqlalchemy.org/en/latest/cookbook.html>`__
Migration can be then invoked locally from within the migration environment directory::
cd migrations-events
alembic upgrade head
alembic history
To enable execution of database migrations on target systems after installation
from package there is a simple wrapper script ``/etc/mentat/scripts/sqldb-migrate-e.sh``::
/etc/mentat/scripts/sqldb-migrate-e.sh upgrade head
/etc/mentat/scripts/sqldb-migrate-e.sh history
* `Alembic <https://alembic.sqlalchemy.org/en/latest/index.html>`__
Metadata database migrations
````````````````````````````````````````````````````````````````````````````````
Important resources:
* `Alembic <https://alembic.sqlalchemy.org/en/latest/index.html>`__
* `Flask-Migrate <https://flask-migrate.readthedocs.io/en/latest/>`__
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
Versioning
--------------------------------------------------------------------------------
This project uses the `semantic versioning <https://semver.org/>`__. When the
**production** level packages are being built and deployed, the automated build
system takes the project version directly from following files (paths are relative
to project root):
* ``lib/mentat/__init__.py``
* ``package.json``
Sadly you have to adjust the version string on both of these places, currently
there is no way how to do it on one.
When building the **release** or **development** level packages, the automated
build system appends an internal build number as additional subversion. This way
each build produces unique version string and unique package. This feature can
be used during development to reduce the need for incrementing the version numbers
manually between each builds.
Tagging
--------------------------------------------------------------------------------
Each major and minor version release must be tagged within the repository. Please
use only annotated or signed tags and provide short comment for the release. Before
tagging please view existing tags so that you can attempt to maintain the style of
the tag messages.
.. code-block:: shell
# List all existing tags
git tag -l -n999
# Create new annotated tag and provide message
git tag -a v2.0.0
# Push tags to remote servers (if you are permitted to do so)
git push origin v2.0.0
git push buildbot v2.0.0
# Number of commits between last two versions:
$ git rev-list --count v1.0.0..v0.0.1
# Total changes between last two versions:
$ git log --numstat --pretty="%H" v1.0.0..v0.0.1 | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%d\n", plus, minus)}'
Building Python packages
--------------------------------------------------------------------------------
If you want to build native Python packages locally please use following makefile
target:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make build-whl
Generated packages will be placed into ``./dist`` subdirectory.
Building Debian packages
--------------------------------------------------------------------------------
If you want to build native Debian packages locally please use following makefile
target:
.. code-block:: shell
# Always make sure your virtual environment is activated:
$ . venv/bin/activate
# Run tests:
(venv) $ make build-deb
Generated packages will be placed into ``./deploy/mentat/`` subdirectory.
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
Examples
--------------------------------------------------------------------------------
Implementing example daemon module
````````````````````````````````````````````````````````````````````````````````
Before going further please read the documentation and study source code of following
libraries:
* :py:mod:`pyzenkit.baseapp`
* :py:mod:`pyzenkit.zendaemon`
* :py:mod:`mentat.daemon.piper`
Now save following content into the file ``/etc/mentat/examples/mentat-demopiper.py``:
.. code-block:: python
import pyzenkit
import mentat.const
import mentat.daemon.piper
class DemoPrintComponent(pyzenkit.zendaemon.ZenDaemonComponent):
def get_events(self):
return [
{
'event': 'message_process',
'callback': self.cbk_event_message_process,
'prepend': False
}
]
def cbk_event_message_process(self, daemon, args):
daemon.logger.info(
"Processing message: '{}': '{}'".format(
args['id'], str(args['data']).strip()
)
)
daemon.queue.schedule('message_commit', args)
self.inc_statistic('cnt_printed')
return (daemon.FLAG_CONTINUE, None)
class DemoPiperDaemon(mentat.daemon.piper.PiperDaemon):
def __init__(self):
super().__init__(
name = 'mentat-demopiper.py',
description = 'DemoPiperDaemon - Demonstration daemon',
path_bin = '/usr/local/bin',
path_cfg = '/tmp',
path_log = '/var/mentat/log',
path_run = '/var/mentat/run',
path_tmp = '/tmp',
default_config_dir = None,
default_queue_in_dir = '/var/mentat/spool/mentat-demopiper.py',
default_queue_out_dir = None,
schedule = [
('message_enqueue', {'data': '{"testA1": 1, "testA2": 2}'}),
('message_enqueue', {'data': '{"testB1": 1, "testB2": 2}'}),
(mentat.const.DFLT_EVENT_START,)
],
schedule_after = [
(mentat.const.DFLT_INTERVAL_STATISTICS, mentat.const.DFLT_EVENT_LOG_STATISTICS)
],
components = [
DemoPrintComponent()
]
)
if __name__ == "__main__":
DemoPiperDaemon().run()
Now let`s create configuration file ``/tmp/mentat-demopiper.py``. It must contain
a valid JSON dictionary, that may or may not be empty, so it must contain at least
following:
.. code-block:: python
# Configuration for module
{}
Note, that you may use single-line comments. Any line, that beginswith ``#`` is
ignored. However there may be only white characters on the line before the comment.
Now add your module somewhere into the message processing pipeline. For the simplicity
let`s put it after the default ``mentat-storage.py`` module, so that we have to make
only one change in existing configuration files. Replace the existing value for
``queue_out_dir`` with following line in ``/etc/mentat/mentat-storage.py.conf`` file:
.. code-block:: python
"queue_out_dir": "/var/mentat/spool/mentat-demopiper.py",
And finally add your new module to the ``/etc/mentat/mentat-controller.py.conf``
file into the key ``modules``, so that you can start and stop it together with
the rest of the modules:
.. code-block:: python
{
"exec": "mentat-demopiper.py",
"args": [
# Enable debug information before daemonization
"--debug"
# Force logging level ['debug', 'info', 'warning', 'error', 'critical']
"--log-level=debug"
]
},
Place it on top of the list so that it gets started first since it is the last
module in the message processing chain.
Now everything is ready for you to start everything up:
.. code-block:: shell
# Create symlink to example
ln -s /etc/mentat/examples/mentat-demopiper.py /usr/local/bin/mentat-demopiper.py
# Stop all currently running components
mentat-controller.py --command stop
# Start all currently components
mentat-controller.py --command start
# Generate test messages
mentat-ideagen.py --count 10
# View log file
tail -f /var/mentat/log/mentat-demopiper.py.log