Keep a huge Erlang code base, developed by multiple teams, in a manageable state.
Kappa can tell you which team owns this particular app / module / database table and how they can be contacted (e.g. to send an alarm).
Restrict inter-app calls to only a set of API-modules. Calls from one app to other app's private modules are not allowed.
Direct access to records defined in header files makes it hard to change the record's structure. Kappa allows only a defined set of modules to access specific record's fields directly.
Divide your apps into multiple layers (e.g. external interfaces and APIs / business logic layer / database level / system utilities / test-only / external dependencies, etc.) and apply restrictions on calls between applications that belong to different layers (allowed at all? if allowed, in which direction?)
⚠️ Most of the checks rely on the presence ofdebug_info
compiler option!
rebar3 escriptize
_build/default/bin/kappa
Usage: kappa [<mode>] [-a [<apps>]] [-m [<mods>]] [-x [<exclusive>]]
[-f [<functions>]] [-v [<violations>]] [-r [<reverse>]]
[-c [<count>]] [-g [<graph>]] [-G [<graph_file>]]
[-p [<path>]] [-?] [name ...]
<mode> api: report non api call violations
layers: report layer violations
all: report api and layer violations
summary: print a one line summary of all violations in
the system. Options other than -p are ignored.
The format is:
<time> <non api calls> <layer violations> <sum> [default: all]
-a, --apps List applications violating invariants [default: false]
-m, --mods List modules violating invariants [default: true]
-x, --exclusive Only report violations where the module is a part of
the analyzed set [default: false]
-f, --functions Draw graph over functions. Use carefully.
Only works with -m [default: false]
-v, --violations Show only violations in graph. [default: false]
-r, --reverse Report callers to the mod/app rather than callees
[default: false]
-c, --count Report only the number of warnings [default: false]
-g, --graph Store a graph centered around the mods/apps.
Default file path is '/tmp/graph.svg' [default: false]
-G, --graph-file Store a graph centered around the mods/apps at
specified location. [default: undefined]
-p, --path Analyze another system rather than the current.
Default is current directory [default: Current Directory]
-?, --help Show usage screen
names List of applications or modules to check.
Default is to check the whole system
Kappa's configuration is loaded from 4 files:
architecture_file
- where all the layers and applications are listed with their owner IDs and API modulesownership_file
- with all the teams and their contact detailsdb_ownership_file
- where all the database tables are listed with their ownersrecord_field_use_file
- where all the shared records are listed together with their access modules and allowed exceptions
There are 2 additional files where approved rule violations can be listed:
approved_api_violations_file
- where we can temporary allow calls from one application to another application's non-API moduleapproved_layer_violations_file
- where we can temporary allow calls between applications belonging to layers, which are normally not allowed to communicate.
Their location can be configured via kappa
's application env, but
some functions can accept their location as an argument.
Each application needs to have a block in architecture_file
with an
application
and owner
keys. Each API module also needs to be
listed under its application. Example:
[ {application, monitor}
, {owner, operations}
, {api, [ alarm, log ]}
].
Where owner is the name of your team, application is the name of application your api module belongs to and api is a list of all API modules.
You can specify ignore rules to reduce the number of modules in the
api section and to avoid manually adding them. They are added to
kappa
's application env under always_api
key.
Several types of rules are supported:
- ignore app_name:
app_name
. This will make modules with the same name as their applications be treated as API modules. - ignore by suffix:
{suffix, "api"}
. This will make all modules with names ending inapi
be treated as API modules. - ignore by prefix:
{prefix, "api"}
. This will make all modules with names starting withapi
be treated as API modules. - ignore by directory:
{dir, "api"}
. This will make all modules, which source files are stored insrc/api
subdirectory be treated as API modules. - ignore by behaviour:
{behaviour, api}
. This will make all modules with-behaviour(api)
be treated as API modules.
Full example:
{env, [
{always_api, [
app_name,
{behaviour, api},
{dir, "api"}
]
}
]
}
See our guide on contributing.
See our changelog.
Copyright © 2021 Klarna Bank AB
For license details, see the LICENSE file in the root of this project.