Configuration Data

Let's start with the configuration data, which contains information about all monitoring agents and the sensor checks assigned to them. There are multiple approaches to organizing and designing database tables. One of the formal methods is to write down all columns as one record and start from there applying all rules from the First Normal Form. When you're done and have one or more tables in the First Normal Form, you proceed by applying the Second Normal Form rules until you get the desired result—ideally database tables in the Third Normal Form.

Although this method works perfectly every time, I find it bit tedious, because with some practice you already know how to organize the tables and going through all the formal steps just creates unnecessary work. I find the following method a lot more effective.

Think about the objects in your model that are static and self-contained. Going back to the configuration data I see two objects there: host and sensor. Now create tables for each such object. I'll start with the table for the host entries, Table 9-1.

Table 9-1. The Host Entries

Field Data Type Description id integer The unique identifier.

name text The name of the host.

address text The IP address or full domain name of the host.

port text The port number on which the client process is running.

As you can see, this table is already in the Third Normal Form and there's absolutely no need to improve anything in it. Each entry is unique, there are no repetition groups in the columns, there's only one primary key field (name), and other fields depend only on that field.

■ Note I need to point out that the ID in this table and other tables is not to be treated as a unique field. When normalizing data, fields must carry sensible information, and arbitrary fields such as hidden IDs or timestamps cannot be treated as informational fields, because they do not constitute the dataset. They are used mostly for reference purposes, because it is faster and more efficient to operate on integer values rather than text or keys of other data types.

Now let's proceed to the sensor definition. This is going to be slightly more complicated, because from the sensor design I already know that each sensor can perform several checks. For example, the disk volume sensor can perform multiple checks, such as total space, used space, used inodes, and so on. You might want to add all fields into one table, so that the sensor-check combination becomes a unique key field. This may be fine for small datasets, but if you want to expand and add more fields, this structure becomes inflexible and you'll need to redesign the tables. As a rule of thumb I recommend splitting any data that has the 'containsmultiple...' attribute. Going back to my example I can declare that each sensor contains multiple checks. Therefore, if you split this information across two tables, in most cases you'll be spot on. Table 9-2 is the table for the sensor entries.

Table 9-2. The Sensor Entries

Field

Data Type

Description

id

integer

The unique identifier

name

text

The name of the sensor

The table for the checks (or the probes as I'm going to call them in this book) is shown in Table 9-3; it contains more information and also references the sensor entries.

Table 9-3. The Probe Entries

Field

Data Type

Description

id

integer

The unique identifier.

name

text

The name of the probe.

parameter

text

The string to be passed to the sensor check command.

warning

float

The default threshold for this particular probe, at the warning level.

error

float

The default threshold for this particular probe, at the error level.

sensor_id

integer

The ID of the sensor record. As I mentioned, in formal notation this

should have been the name of the sensor, but for simplicity and flexibility we use unique row IDs.

should have been the name of the sensor, but for simplicity and flexibility we use unique row IDs.

Now look really carefully at Tables 9-2 and 9-3 and see if you can spot any violations of the normalization form rules. The sensor table is so simple that no doubt it is in the Third Normal Form, but what about the probe table? At first glance it looks fine, but on closer inspection you'll realize that I have repetitive groups, so this table is not even in the First Normal Form! There are two fields that effectively define similar types of information: the threshold fields, warning and error. I must create a new table to hold threshold definitions, including warning, error, and possibly others such as informational and critical if I ever want to add them. That, however, brings another complication—I cannot put any values in that table, because threshold values are specific to each probe. So I will need to define yet another table that ties the probe and the threshold records together and adds the value column. I now have two choices—restructure the table, introduce two new ones, and also face much more complicated code to deal with this, or accept the limitation of the two threshold levels. Because the monitoring system I'm building here is really simple, and I don't require much granularity in thresholds, I go with the second option.

When you're finished defining static components, proceed to the relations. My monitoring system is going to perform probe readings on all monitored hosts, so I need to define this relation. Obviously not all probes apply to all hosts, so I have to create another table that defines probe-to-host mapping. I'm also going to allow threshold overrides on a per-host basis. It is only going to be a placeholder in the table, and the logic of threshold precedence must be implemented at the code level. See Table 9-4.

Table 9-4. Probe-to-Host Mapping

Field

Data Type

Description

id

integer

The unique identifier.

probe_id

integer

The ID of the probe record.

host_id

integer

The ID of the host record on which the probe must be executed.

warning

float

The placeholder for the warning threshold override entry. Must not be a required field, because if left empty the default will be assumed.

error

float

The placeholder for the error threshold override entry. Must not be a required field, because if left empty the default will be assumed.

Was this article helpful?

0 0

Post a comment