Welcome to Nivio’s documentation!

Nivio is a tool for application landscape management targeted at teams (developers, operators, managers). It follows a no-op approach, i.e. there is no interface for manual data maintenance. Instead, Nivio pulls all its information from data sources, like files and web APIs (e.g. monitoring items) or allows pushing information via its API.

Rendered graph
  • It is easy to install and to maintain. Runs dockerized on a single server with moderate to low hardware requirements. It stores the items, so it can be discarded at any time and be refilled with the next start.
  • No-op usage Besides its initial configuration, it is designed to gather the application landscape information from configurable items, preferably code repositories.
  • Renders the landscapes as a graph See above.
  • Multiple configuration sources While Nivio has its proprietary YAML format, you can also use docker-compose files, or use them as basis and enrich them using further files
  • PULL and PUSH Basic indexing of landscapes driven by observed configuration files, or send data to the API.
  • Aggregation of item state Using sources, like Prometheus, and marking items accordingly.

Getting Started

Installation

The easiest way to get started is by bringing up Nivio in Docker:

export NIVIO_BASE_URL=http://localhost:8080
docker run -it --rm -e NIVIO_BASE_URL -p 8080:8080 dedica/nivio:latest

Take a look at http://localhost:8080/

A friendly reminder on the application starting screen tells you that there are no landscapes loaded, yet. To do so, follow the instructions below.

Creating the first landscape

The simplest possible landscape definition consists of:

  • an identifier, used e.g. when updating the landscape
  • a name, that is shown in the UI
  • at least 1 item (things get weird if there are no items at all)

In YAML, it looks like this:

1
2
3
4
5
identifier: tutorial
name: Nivio Tutorial
items:
  - identifier: item-1
    name: My first item

Create the file tutorial.yaml and upload (POST) this file using curl:

curl -X POST -H "Content-Type: application/yaml" --data-binary @tutorial.yaml ${NIVIO_BASE_URL}/api/landscape

Take another look at http://localhost:8080/

_images/first.png

You should find your landscape with the item in it. The item might be assigned to a default group called domain.

The OpenAPI (aka Swagger) documentation is located at /v3/api-docs (JSON) or /swagger-ui.html (HTML GUI).

Updating the landscape

For example, simply change the name of the item and run the same curl command again.

The landscape diagram should update immediately in your browser.

As long as the landscape’s identifier is the same, it will be updated in place. If you change the landscape identifier in the YAML file, then Nivio will create a new, separate landscape.

curl -X PUT -H "Content-Type: application/yaml" --data-binary @tutorial.yaml ${NIVIO_BASE_URL}/api/landscape/tutorial

If the update doesn’t seem to be happening, make sure the curl request didn’t fail and you used PUT as method. If the reason is not obvious, you can also investigate in the Nivio logs.

For some changes, unfortunately though, you will have to restart Nivio and submit the landscape afresh.

Exploring the Nivio model

Adding your own groups

  • Without groups, all items will be assigned to a default group. Items can be assigned to groups using the group attribute.
  • If a group does not exist, nivio creates it. To customize a group, add it to the configuration.
  • However, you can’t create a group with no attributes. Nivio will not accept the landscape. So at least add an owner.
  • If intended to delete already set group attributes such as description or contact, you can do so. But please pay attention that this is not true for the attributes of items or of the landscape. The reason is that group attributes for the groups are all manually set, and the user should have full control about it. For items, instead, best practice is that attributes stick to the old values if they are missing in one configuration file. This is because items are mainly set by several config files. Also, landscapes are not intended to have missing attributes. Therefore, the landscape’s attributes stick to formerly set ones if they are missing.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
groups:
  letters:
    owner: Myself
    description: All the letters
  numbers:
    owner: Myself
    description: All the numbers
items:
  - identifier: a
    name: Item A
    group: letters
    ...
_images/groups.png

Adding relations between items

  • Relations are a key element of every graph. Note that relations are directional in Nivio.
  • A relation can have a weight attribute between 0-5 to control the width of the line between the two items.
_images/relations.png

Adding icons

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 - identifier: a
   name: Item A
   group: letters
   icon: https://visioguy.github.io/IconSets/aws/icons/amazon_ec2.png
 - identifier: b
   name: Item B
   group: letters
   icon: https://visioguy.github.io/IconSets/aws/icons/amazon_dynamodb.png
 - identifier: c
   name: Item C
   group: letters
   icon: https://visioguy.github.io/IconSets/aws/icons/amazon_simple_queue_service_(sqs).png
_images/icons.png

Observations

  • We are not using them here, but don’t forget that Nivio supports all the [Material Design Icons](https://materialdesignicons.com/) out of the box!
  • If you do use custom icons intensively, you should find a place for hosting them. You can define an environment variable NIVIO_ICON_FOLDER which contains a path reachable for the app.

Introducing KPIs

Before you can set a KPI on an item, you need to define the KPI itself.

Here we create one called capacity. It requires a value of 90-100 in order to be considered healthy (green), 80-90 for semi-healthy (yellow), and everything else will be considered unhealthy (red):

1
2
3
4
5
6
7
8
config:
  kpis:
    capacity:
      label: capacity
      ranges:
        GREEN: 90;100
        YELLOW: 80;90
        RED: 0;80

Now the KPI can be used simply by adding the corresponding attribute to any item:

1
2
3
4
items:
  - identifier: a
    name: Item A
    capacity: 87
_images/relations.png

Observations

  • The status of a KPI (i.e. its color) is automatically assessed based on the attribute value - awesome! 🏆
  • There are two other colors that you could use, orange and brown.
  • You only need to define a KPI once, then you can use the respective attribute on as many items as you need to. And of course, an item can use multiple KPIs.
  • Nivio ships with a number of default KPIs (for more information see Data Assessment using KPIs section)

Summary

Conclusion

Once you have figured out its configuration language, Nivio is a great tool for quickly creating a cool visualization of your graph and of the dependencies between the entities you are managing, whether it’s software architecture, an application landscape, your organization, or any other domain. The addition of dynamic KPIs and the status aggregation make it really easy to spot issues quickly!

Best practices

  • Use groups and items. Use relations between items. They also can have weights.
  • A group requires at least 1 attribute in order to work. Use owner, because Nivio always shows something on the owner anyways, and “No owner” doesn’t look great.
  • The following attributes should be on every item: a name, an icon, a group assignment, KPI attributes for the info tab, and any random word with a value for the details tab. This way, the item’s details will be nicely filled out across the info, relations (if applicable), and details tabs.
  • Define your own KPIs that make the most sense for your use case.
  • Find a place to host your custom icons. Don’t abuse and don’t rely on external hosts!
  • Make sure to read Using Templates to dynamically assign data before putting too much effort into item configuration.

Caveats

  • The colors that are automatically assigned to groups tend to be dark and lack contrast, because they are also used for printing with white background. While you can assign colors manually, it’s very tedious to do so.
  • You can experiment a lot with the structure of the landscape, but better figure out the attributes once and then stick to them. For example, icons, or color of groups, etc. - in order to see them updated everywhere (or at all!) you’ll often have to restart Nivio and submit the landscape again.

Bonus: Having Nivio pull your data

In order to have data automatically observed to changes Nivio expects a seed configuration at start time. You need to set the environment variable SEED. The configuration file contains basic data, references to item descriptions sources, which can be local paths or URLs. The descriptions can be gathered by HTTP, i.e. it is possible to fetch files from protected sources via authentication headers. Think of GitLab or GitHub and the related tokens. To use secrets etc., please refer to Environment variables.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 identifier: nivio:example
 name: Landscape example
 contact: mail@acme.org
 description: This is an example landscape.
 sources:
   - "./items/wordpress.yml"
   - url: "http://some.server/docker-compose.yml"
     format: docker-compose-v2
   - url: https://gitlab.com/bonndan/nivio-private-demo/raw/docker-compose.yml
     headerTokenName: PRIVATE_TOKEN
     headerTokenValue: ${MY_SECRET_TOKEN_ENV_VAR}

Deleting items

Items not referenced anymore in the descriptions will be deleted automatically on a complete and successful re-index run. If an error occurs fetching the source while indexing, the behaviour of the indexer changes to treat the available data as partial input. This means only inserts and updates will happen and no deletion.

Environment variables

The following environment variables can be set to configure nivio:

DEMO

A non-empty value causes Nivio to start in demo mode with prepared data. Use the value ‘all’ to load more landscapes.

GITHUB_JWT

GitHub JSON Web Token (JWT) to connect to GitHub as a GitHub App.

GITHUB_LOGIN

GitHub user name. Can also be used to connect as organization with OAuth.

GITHUB_OAUTH

GitHUb OAuth Token to connect to GitHub via personal access token.

GITHUB_PASSWORD

GitHub password (for username/password login).

GITLAB_HOST_URL

The full URL to the GitLab API, e.g. http://your.gitlab.server.com/api/v4.

GITLAB_PASSWORD

GitLab OAuth login password (optional).

GITLAB_PERSONAL_ACCESS_TOKEN

Personal token to access the GitLab API at GITLAB_HOST_URL (optional).

GITLAB_USERNAME

GitLab OAuth login username (optional). If used, GITLAB_PASSWORD is also required).

KUBERNETES_MASTER

K8s master URL (optional). All variables from https://github.com/fabric8io/kubernetes-client#configuring-the-client can be used.

NIVIO_AUTH_ALLOWED_ORIGINS

Patterns for allowed origins when the app requires authentication

NIVIO_AUTH_GITHUB_ALIAS_ATTRIBUTE

GitHub user attribute to use as alias

NIVIO_AUTH_GITHUB_CLIENT_ID

GitHub app OAuth2 client id

NIVIO_AUTH_GITHUB_CLIENT_SECRET

GitHub app OAuth2 client secret

NIVIO_AUTH_GITHUB_NAME_ATTRIBUTE

GitHub user attribute to use as name

NIVIO_AUTH_LOGIN_MODE

Authentication mode: none, optional, required

NIVIO_BASE_URL

The base URL of Nivio to be used for frontends if running behind a proxy.

NIVIO_BRANDING_BACKGROUND

Branding background color (hexadecimal only).

NIVIO_BRANDING_FOREGROUND

Branding foreground color (hexadecimal only).

NIVIO_BRANDING_LOGO_URL

A URL pointing to a logo.

NIVIO_BRANDING_MESSAGE

A welcome message on the front page.

NIVIO_BRANDING_SECONDARY

Accent color used for active elements (hexadecimal only).

NIVIO_ICON_FOLDER

A folder containing icons named similar to material design icons

NIVIO_MAIL_HOST

SMTP mail host.

NIVIO_MAIL_PASSWORD

SMTP mail password.

NIVIO_MAIL_PORT

SMTP mail port.

NIVIO_MAIL_USERNAME

SMTP mail username.

PORT

The port Nivio runs on.

SEED

A semicolon-separated list of file paths containing landscape configurations.

SONAR_LOGIN

SonarQube login (username).

SONAR_PASSWORD

SonarQube password.

SONAR_PROXY_HOST

SonarQube proxy host (optional).

SONAR_PROXY_PORT

SonarQube proxy port (optional).

SONAR_SERVER_URL

SonarQube server URL.

Input Sources

Kubernetes cluster inspection

Kubernetes clusters are inspected using Fabric8.io’s Java client. See https://github.com/fabric8io/kubernetes-client#configuring-the-client for configuration. Parsing can be configured via a URL, i.e. the examined namespace can be given (otherwise all namespaces are scanned) and a label for building groups can be named. Both parameters and even the whole URL are optional.

1
2
3
4
5
 identifier: k8s:example
 name: Kubernetes example
 sources:
   - url: http://192.168.99.100?namespace=mynamespace&groupLabel=labelToUseForGrouping
     format: kubernetes

Rancher 1 Cluster Inspection

Rancher clusters can be indexed one project (aka environment in the GUI speak) at a time. Access credentials can be read from environment variables. To exclude internal stacks, like those responsible for internal networking, blacklist them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 identifier: rancher:example
 name: Rancher 1.6 API example
 config:
   groupBlacklist: [".*infra.*"]

 sources:
   - url: "http://rancher-server/v2-beta/"
     projectName: Default
     apiAccessKey: ${API_ACCESS_KEY}
     apiSecretKey: ${API_SECRET_KEY}
     format: rancher1

Nivio proprietary format

Nivio provides its own format which allows to set all model properties manually (see Model and Syntax section).

Reading from CSV

Nivio can parse CSV files regarding rows as landscape items. The order of the columns in the file is important because headers are ignored and not mapped automatically. Instead, each column number, starting at zero, can be assigned to an item property in the mapping configuration. Additionally, the CSV separator char and the number of lines to skip (usually 1 for the header row) can be set.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 sources:
  - url: "./services/test.csv"
    format: csv
    mapping:
      identifier: 1
      name: 0
      description: 2
      providedBy: 3
    separator: ";"
    skipLines: 1

Reading and Mapping from JSON

Any JSON file or URL can be parsed and mapped into a landscape description. Existing structures are mapped to landscape components using JSONPath, a query language to traverse JSON objects and select specific properties.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
identifier: example:customjson
name: Custom JSON example
sources:
  - format: customJSON
    url: /mnt/items.json
    mapping:
      items: "$.items"
      item:
        identifier: "$.id"
        endOfLife: "$.end_of_life.date"
        name: '$.moreThanAName|find "([\\w\\s]*),"'
        nivio.link.homepage: "$.a_named_link"
        nivio.relations.inbound: "$.@dependencies.@upstream|fetch|$.items[*].id"
        nivio.relations.providers: "$.infra|fetch|$.items[*].id"

The folling mapping steps are supported:

  • JsonPath. Simply add the path expression. Note that the root for items is the root of the assigned JSON subnode. For more info on JsonPath, see https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html.
  • fetch an URL, starting with the keyword _fetch_
  • find a subtext using regular expressions. starting with the keyword _find_. Make sure to put lines containing regexes in single quotes and surround the pattern with double quotes (a CSV parser is used in combination with a YAML parser, so this is the combination that works).

Reading from GraphViz dot files

https://www.graphviz.org/ is a graph visualisation software which uses the dot language https://graphviz.org/doc/info/lang.html to describe graphs. It is possible to add arbitrary attributes to nodes and edges, so nivio can use these attributes to enhance items and relations. However, it is necessary to prefix attributes that should be taken into account using the string “nivio_”.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 digraph G {
         main [
             nivio_owner = Marketing,
             nivio_software="Wordpress 2.0",
             nivio_group=FooBar,
             nivio_contact="foo@bar.com"
         ]
         main -> parse -> execute
         main -> init [nivio_format = json, nivio_type=PROVIDER, nivio_description="init the procedure", nivio_frameworks="PHP:7.2,Angular:9"]
         main -> cleanup
         execute -> make_string
         execute -> printf
         init -> make_string
         main -> printf
         execute -> compare
         }

Also remember to put non-ascii words (like email addresses) or sentences into double quotes.

To configure this as input source, add:

1
2
3
 sources:
  - url: "./test/foo.dot"
    format: dot

External data

Nivio can load external data that cannot be used directly to build landscapes, but is still valuable. For example, the number of GitHub issues might be interesting to see on a landscape item that is an open source component. To attach such data to landscape components, use links having special known identifiers like “github” or “sonar”.

This is work in progress. Currently supported link identifiers are:

1
2
3
4
5
6
 items:
   - identifier: nivio
     links:
       github: https://github.com/dedica-team/nivio
       spring.health: http://localhost:8090/actuator/health
       # sonar: http://hihi.huhu not implemented yet

Model and Syntax

Landscape

A landscape is defined as a collection of items which somehow belong together, be it for technical or business reasons. For example, a company department might model ALL its applications in production as one landscape and use grouping or tagging to further separate the applications. A second landscape could be used to model a future layout with a different infrastructure. Both landscapes could have items in common (like a database, load balancer, etc.), so their configuration can be reused.

LandscapeDescription

Name Type Description Remarks Example
assignTemplates Map<array>   optional, defaults to null null
color String   optional, defaults to null null
config LandscapeConfig<LandscapeConfig>   optional, defaults to null null
contact String Primary contact method, preferably an email address. optional, defaults to null null
description String A brief description of the landscape. optional, defaults to null null
groups Map<GroupDescription> Description of item groups (optional, can also be given in sources). optional, defaults to null null
icon String An icon or logo url optional, defaults to null null
identifier String Immutable unique identifier. Maybe use an URN. required, defaults to null null
isPartial Boolean   optional, defaults to null null
items List<ItemDescription> List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. optional, defaults to null null
labels Map   optional, defaults to null null
links Map<Link> Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. optional, defaults to null github: https://github.com/dedica-team/nivio
name String Human readable name. required, defaults to null null
owner String The business owner (person or team), preferably an email address. optional, defaults to null null
partial Boolean marks that the landscape is not complete, but an update optional, defaults to null null
templates Map<ItemDescription> Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items. optional, defaults to null null

SourceReference

This is a reference to a configuration file.

Name Type Description Remarks Example
assignTemplates Map<array> A map with template identifier as key and item identifier matchers as value optional, defaults to null endOfLife: [web, “java6*”]
basicAuthPassword String   optional, defaults to null null
basicAuthUsername String   optional, defaults to null null
deprecation String deprecation info (typically used in OpenAPI specs) optional, defaults to null null
format String The input format. optional, defaults to null null
headerTokenName String   optional, defaults to null null
headerTokenValue String   optional, defaults to null null
href String The link target. required, defaults to null null
hreflang String hateoas language optional, defaults to null null
media String hateoas media type optional, defaults to null null
name String HateOAS / OpenAPI name optional, defaults to null null
rel String hateoas relation type optional, defaults to null null
title String hateoas title optional, defaults to null null
type String   optional, defaults to null null
url String A URL, but can also be a relative path. optional, defaults to null ./a/items.yaml

LandscapeConfig

Configuration of key performance indicators (i.e. status indicators) and layouting tweaks.

Name Type Description Remarks Example
branding Branding<Branding>   optional, defaults to null null
greedy Boolean Flag that enables instant creation items based relation targets that cannot be found in the sources. optional, defaults to null null
groupBlacklist List Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results. optional, defaults to null .*infra.*
kpis Map<KPIConfig> Key performance indicator configs. Each KPI must have a unique identifier. optional, defaults to null null
labelBlacklist List Names or patterns of labels that should be ignored. Used to improve automatic scanning results. optional, defaults to null .*COMPOSITION.*
layoutConfig LayoutConfig<LayoutConfig>   required, defaults to null null

KPIConfig

The configuration of landscape specific key performance indicators that derive status information from landscape components. Usually the KPIs work on labels

Name Type Description Remarks Example
description String Description of the purpose of the KPI optional, defaults to null null
enabled Boolean A flag indicating that the KPI is active. Can be used to disable default KPIs. optional, defaults to null null
label String Key of the label to evaluate required, defaults to null costs
matches Map A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers. optional, defaults to null RED: BAD;err.*
messageTemplate String Template for the displayed message, containing a placeholder for the assessed value '%s optional, defaults to null The current value is: %s
ranges Map A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers. optional, defaults to null GREEN: 0;99.999999

LayoutConfig

Layout configuration for landscapes with unusual number or ratios of items, groups and relations.

Name Type Description Remarks Example
groupLayoutInitialTemp Integer The initial temperature for layouts of groups. required, defaults to 900 900
groupMaxDistanceLimit Integer A maximum distance between groups up to where forces are applied. required, defaults to 1000 1000
groupMinDistanceLimit Integer The minimum distance between groups. required, defaults to 50 50
itemLayoutInitialTemp Integer The initial temperature for layouts of items within groups. required, defaults to 300 300
itemMaxDistanceLimit Integer A maximum distance between items up to where forces are applied. required, defaults to 350 350
itemMinDistanceLimit Integer The minimum distance between items. required, defaults to 100 100

Branding

Map branding (tweaks visuals)

Name Type Description Remarks Example
mapStylesheet String A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map. optional, defaults to null https://acme.com/css/acme.css

GroupDescription

A group of items. Could be used as bounded context, for instance.

Name Type Description Remarks Example
color String The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed. optional, defaults to null 05ffaa
contact String A contact method, preferably email. optional, defaults to null null
contains List A list of item identifiers or SQL-like queries to easily assign items to this group. optional, defaults to null identifier LIKE ‘DB1’
description String A brief description. optional, defaults to null null
environment String   optional, defaults to null null
identifier String A unique identifier for the group (also used as name). Descriptions are merged based on the identifier. required, defaults to null shipping
labels Map   optional, defaults to null null
links Map<Link> Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. optional, defaults to null github: https://github.com/dedica-team/nivio
name String   optional, defaults to null null
owner String The business owner of the group. optional, defaults to null null

ItemDescription

List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.

Name Type Description Remarks Example
address String The technical address of the item (should be an URI). Taken into account when matching relation endpoints. optional, defaults to null null
color String Overrides the group color. Use an HTML hex color code without the leading hash. optional, defaults to null 4400FF
contact String The primary way to contact a responsible person or team. Preferably use an email address. optional, defaults to null johnson@acme.com
description String A brief description. optional, defaults to null null
frameworks Map The parts used to create the item. Usually refers to technical frameworks. optional, defaults to null java: 8
group String The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to its layer. optional, defaults to null shipping
icon String An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work). optional, defaults to null null
identifier String Immutable unique identifier (maybe use an URN). Primary means to identify items in searches. required, defaults to null null
interfaces Set<InterfaceDescription> A collection of low level interfaces. Can be used to describe HTTP API endpoints for instance. optional, defaults to null null
labels Map   optional, defaults to null null
layer String The technical layer optional, defaults to null infrastructure
lifecycle String The lifecycle state of an item. optional, defaults to null null
links Map<Link> Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. optional, defaults to null github: https://github.com/dedica-team/nivio
name String A human readable name/title. The name is considered when items are searched. optional, defaults to null my beautiful service
owner String The business owner of the item. Preferably use an email address. optional, defaults to null johnson@acme.com
providedBy List A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations. optional, defaults to null shipping-mysqldb
status List<map> A list of statuses that works like hardcoded KPIs. optional, defaults to null null
statuses List<map> A list of statuses that works like hardcoded KPIs. optional, defaults to null null
tags List   optional, defaults to null null
type String The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. optional, defaults to null service|database|volume

InterfaceDescription

Describes a low-level interface of an item.

Name Type Description Remarks Example
deprecated Boolean   optional, defaults to null null
description String A brief description. optional, defaults to null null
format String The payload format. optional, defaults to null null
name String   optional, defaults to null null
parameters String   optional, defaults to null null
path String   optional, defaults to null null
payload String   optional, defaults to null null
protection String A description of the interface protection method. optional, defaults to null null
summary String   optional, defaults to null null
url String A URL describing the endpoint. optional, defaults to null null

Item Groups

Groups can have the following attributes:

  • identifier: A unique identifier in the landscape. Provided automatically via the dictionary key, so do not set it.
  • contains Array of references to other items (identifiers and CQN queries).
  • owner Owning party (e.g. marketing).
  • description A short description.
  • team Technical owner.
  • contact Support/notification contact (email). May be addressed in case of errors.
  • color A hex color code for rendering.
  • links A map/dictionary of URLs to more information.

Group configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 groups:
   content:
     description: All services responsible to provide information on the web.
     owner: Joe Armstrong
     team: Team Content
     contact: joe@acme.org
     color: "#345345"
     links:
       wiki: http://wiki.acme.org/teamContent

   infrastructure:
     team: Admins

Item Identification and Referencing

An item can be uniquely identified by its landscape, its group, and its identifier. A fully qualified identifier is composed of these three: mylandscape, agroup, and theitem. Since the group is optional, items with unique identifier can also be addressed using mylandscape and theitem, or just theitem. Nivio tries to resolve the correct item and raises an error if it cannot be found or the result is ambiguous.

Service references are required to describe a provider relation or dataflow.

1
2
3
4
5
6
7
8
 items:
   - identifier: theservice
     group: agroup
     relations:
       - target: anothergroup/anotherservice
         format: json
         type: dataflow
         label: Data Sync

Data Assessment using KPIs

KPIs can be used to evaluate landscape components (typically items, but also groups) based on their properties. The result is a status represented by colors (ordinal):

  • UNKNOWN (order 0): status could not be determined
  • GREEN (order 1): everything OK
  • YELLOW (order 2): ignorable warning
  • ORANGE (order 3): warning
  • RED (order 4): error
  • BROWN (order 5): fubar

Built in KPIs

Scaling

This KPI evaluates the scale label and tries to find bottlenecks where providers for many items are down or not scaled.

  • red if 0 as provider for other items
  • yellow if scaled to 0 without relations
  • orange of scaled to 0 as data sink
  • unknown if no label or not a number
  • green if scaled higher than 1
  • yellow if a bottleneck (more than 1 item depends on it)

Lifecycle

This KPI evaluates the lifecycle label for “official” values.

  • PRODUCTION turns the KPI value to GREEN
  • END_OF_LIFE turns it to ORANGE

Other

  • health (examines the health label on items)
  • condition (K8s condition true/false evaluation)

By default all shipped KPIs (Key Performance Indicators) are disabled. Set enabled to true in the config to enable them.

1
2
3
4
5
6
7
8
 identifier: kpi_example

config:
  kpis:
    lifecycle:
      enabled: true
    scaling:
      enabled: true

Custom KPIs

Custom KPIs can be configured in the landscape config using ranges and/or matchers (regular expressions) and applied to everything having labels. In the example below a KPI monthlyCosts is defined, using ranges on the label costs, and the KPI myEval evaluates a label foo.

  • Both ranges (inclusive lower and upper limits) and matchers are separated by semicolon.
  • The displayed message can be customized by a template. The placeholder for the value is ‘%s’.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 identifier: kpi_example
 name: Using KPIs for data assessment

 config:
   kpis:
     monthlyCosts:
       description: Evaluates the monthly maintenance costs
       label: costs
       messageTemplate: "Monthly costs: $%s"
       ranges:
         GREEN: 0;99.999999
         YELLOW: 100;199.999999
         RED: 200;499.999999
         BROWN: 500;1000000
     myEval:
       description: evaluate the label "foo"
       label: foo
       matches:
         GREEN: "OK;good;nice"
         RED: "BAD;err.*"
     health:
       description: can be overridden

The pet clinic demo uses a custom KPI which evaluates radiation levels. In this simulation a sensor item (see xray group) collects a made up radiation (in mrem) in a label also named radiation. This label is then examined by the custom KPI. See https://github.com/dedica-team/nivio/blob/develop/src/test/resources/example/pet_clinic.yml

Shortcuts and convenience functions

Assigning items to groups

Often lots of items can be read from input data sources, but no information on logical grouping is available. To mitigate that, you can describe groups and use the contains field:

  • To pick items by their identifier, add single strings which are treated as identifiers.
  • Furthermore you can use SQL-like WHERE conditions to assign items to groups. In the following example identifier LIKE 'DB1%' is the query which would match both items.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 items:
   - identifier: DB1-gateway
     shortName: blog1
     layer: ingress

   - identifier: DB1
     software: MariaDB
     version: 10.3.11
     type: database
     layer: infrastructure

 groups:
   infrastructure:
     team: Admins
     contains:
       - DB1
       - "identifier LIKE 'DB1%'"

Using Templates to dynamically assign data

To prevent repetitive configuration of items, i.e. entering the same owner again and again, templates can be used to prefill values. Templates are just item descriptions, except that the identifier is used for referencing and that names are ignored. A template value is only applied if the target value is null.

Multiple templates can be assigned to items too. In this case the first assigned value “wins” and will not be overwritten by templates applied later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 identifier: nivio:example
 name: Landscape example

 sources:
   - url: "./items/docker-compose.yml"
     format: docker-compose-v2
     assignTemplates:
       endOfLife: [web]
       myGroupTemplate: ["*"]

 templates:

   myGroupTemplate:
     group: billing

   endOfLife:
     tags: [eol]

For CQ queries read https://github.com/npgall/cqengine#string-based-queries-sql-and-cqn-dialects.

Using Labels to assign data

You can set labels (string:string) to items which are evaluated as model fields if

  • the key contains nivio. AND
  • the rest of the key equals a field name.

Labels can be set using docker-compose files too. However, docker labels do not allow arrays, so use comma separated strings:

1
2
3
4
5
6
7
 services:
   foo:
     labels:
       nivio.name: A nice name
       nivio.providedBy: "bar, baz"
       nivio.relations: "atarget, anotherTarget"
       nivio.link.repo: "https://github.com/foo/bar"

Remember to escape URLs with double quotes.

Relations between landscape items

Usually environments such as Docker or K8s provide few to none information on the relation between landscape items (e.g. which database a service uses). However, in 12-factor apps there is configuration through environment variables (https://12factor.net/config) and these can be parsed. Nivio provides an experimental feature which regards these variables as DSL. They are read and assigned as item labels, then examined:

  • The key is split using the underscore character.
  • If it contains parts like url, uri, host etc., the label is taken into account as identifier, i.e. Nivio looks for a target having the identifier, name, or address equal to the value.

Labels are examined as follows:

  • In the case of being an URI, the host and name path components are extracted and used as names or identifiers.

To prevent false positives, certain labels can be omitted:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 identifier: some-landscape

 items:
   - identifier: foo
     labels:
       HOST: bar
       SOME_LABEL: mysql://ahost/foobar

   - identifier: bar
     type: database

Output

Searching

Nivio indexes all landscape items in an in-memory search engine called Lucene. You can build sophisticated queries on various item fields (see Model and Syntax). For further information see https://www.lucenetutorial.com/lucene-query-syntax.html

Modifying Item Appearance

Icons by Type

The icon of an item is determined by its item type (e.g. server, database, …) and defaults to a cog symbol.

1
2
3
 items:
   - identifier: bar
     type: database

As type values all items from https://materialdesignicons.com/ can be chosen. Just add the icon name without the “SVG” suffix, like “account”.

1
2
3
 items:
   - identifier: bar
     type: account

Alternatively you can use any icon name on the icon field.

1
2
3
 items:
   - identifier: bar
     icon: flash-circle

Vendor Logos

The icon property can also work with a predefined vendor name, like “redis”, prefixed with vendor:// as scheme.

Vendor icons are work in progress.

1
2
3
 items:
   - identifier: bar
     icon: vendor://redis

To change the appearance of an item to a vendor logo the icon or fill properties can be set. Both properties take a valid URL.

External Images

To include external images in the map, just set the icon property (or fill) to a valid URL.

1
2
3
items:
   - identifier: foo
     icon: http://my.custom/icon.png

Background fill

While icon (see External Images above) is rendered as centered image on the node, fill is used to paint the entire background and is more suitable to be used with images, photos, and so on.

1
2
3
items:
   - identifier: bar
     fill: http://my.custom/background.png

UTF-8 Symbols and shortname as Icons

If NO icon, type, or fill value is set, but a shortname value is given, the value is displayed on the icon. The first example would display FOOBAR on the item and the second an enlarged unicorn symbol (shortnames less than three characters are enlarged).

1
2
3
4
5
items:
   - identifier: bar
     shortname: FOOBAR
   - identifier: pony
     shortname: 🦄

Custom(er) Branding

The appearance of rendered maps can be altered to match corporate identities. When an SVG map is created, Nivio tries to load and include custom CSS from a URL which can be configured in the landscape configuration. Furthermore, a logo can be included. A logo is configured in the landscape config and must be a URL pointing to an includable file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
identifier: branded_landscape
name: branded

config:
  branding:
    mapStylesheet: https://acme.com/css/acme.css
    mapLogo: https://acme.com/images/logo.png

items:
  ...

You can also apply custom colors to the user interface. Set the following environment variables to hex values (e.g. #234234):

Troubleshooting

Behind a proxy

If you deploy Nivio to run under a different path than root (/), make sure to set the environment variables SERVER_SERVLET_CONTEXT_PATH and NIVIO_BASE_URL to the path.

SERVER_SERVLET_CONTEXT_PATH: /my-landscape
NIVIO_BASE_URL: https://foo.com/my-landscape/

Graph Layout Tweaking

In rare cases the layout needs some manual improvements. Internally Nivio uses a forced directed layout, which can be influenced by tweaking some parameters (although mxgraph is not used anymore, for further explanation see https://jgraph.github.io/mxgraph/java/docs/com/mxgraph/layout/mxFastOrganicLayout.html). In order to change the default setting of the LayoutConfig, add a section to the landscape description as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 identifier: nivio:example
 name: Landscape example
 config:
   layoutConfig:
     itemMinDistanceLimit: 60
     itemMaxDistanceLimit: 360
     groupMinDistanceLimit: 140
     groupMaxDistanceLimit: 300
     itemLayoutInitialTemp: 380
     groupLayoutInitialTemp: 1000

References

Similar approaches can be found at our system graph collection.

Nivio has been inspired by pivio and uses similar semantics, but has a different focus.