diff --git a/src/Plugin/monitoring/SensorPlugin/DatabaseAggregatorSensorPlugin.php b/src/Plugin/monitoring/SensorPlugin/DatabaseAggregatorSensorPlugin.php
index a8ed1c5..b1c35ee 100644
--- a/src/Plugin/monitoring/SensorPlugin/DatabaseAggregatorSensorPlugin.php
+++ b/src/Plugin/monitoring/SensorPlugin/DatabaseAggregatorSensorPlugin.php
@@ -59,13 +59,6 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
   protected $fetchedObject;
 
   /**
-   * The currently active keys for verbose output.
-   *
-   * @var array
-   */
-  protected $currentKeys;
-
-  /**
    * Builds simple aggregate query over one db table.
    *
    * @return \Drupal\Core\Database\Query\Select
@@ -232,7 +225,7 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
   }
 
   /**
-   * Adds UI for variables table and conditions.
+   * Adds UI for variables table, conditions and keys.
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
     $form = parent::buildConfigurationForm($form, $form_state);
@@ -240,7 +233,7 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
     $settings = $this->sensorConfig->getSettings();
     $form['table'] = array(
       '#type' => 'textfield',
-      '#default_value' => $this->sensorConfig->getSetting('table'),
+      '#default_value' => $settings['table'],
       '#maxlength' => 255,
       '#title' => t('Table'),
       '#required' => TRUE,
@@ -270,30 +263,8 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
       ),
     );
 
-    // Fill the sensors table with form elements for each sensor.
-    $form['output_table'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Verbose Output configuration'),
-      '#prefix' => '<div id="selected-output">',
-      '#suffix' => '</div>',
-      '#tree' => FALSE,
-    );
-    // Fill the keys text field with keys.
-    $form['output_table']['keys'] = array(
-      '#type' => 'textarea',
-      '#tree' => FALSE,
-      '#default_value' => implode("\n", $this->sensorConfig->getSetting('keys')),
-      '#maxlength' => 255,
-      '#title' => t('Keys'),
-      '#required' => TRUE,
-    );
-
-
     // Fill the conditions table with keys and values for each condition.
-    $conditions = $this->sensorConfig->getSetting('conditions');
-    if (empty($conditions)) {
-      $conditions = [];
-    }
+    $conditions = $settings['conditions'];
 
     if (!$form_state->has('conditions_rows')) {
       $form_state->set('conditions_rows', count($conditions) + 1);
@@ -339,7 +310,7 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
     // Select element for available conditions.
     $form['conditions_table']['condition_add_button'] = array(
       '#type' => 'submit',
-      '#value' => t('Add more conditions'),
+      '#value' => t('Add another condition'),
       '#ajax' => array(
         'wrapper' => 'selected-conditions',
         'callback' => array($this, 'conditionsReplace'),
@@ -348,6 +319,56 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
       '#submit' => array(array($this, 'addConditionSubmit')),
     );
 
+    // Add a fieldset to filter verbose output by keys.
+    $form['output_table'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Keys'),
+      '#prefix' => '<div id="selected-output">',
+      '#suffix' => '</div>',
+      '#tree' => FALSE,
+    );
+    // Add a table for the keys.
+    $form['output_table']['keys'] = array(
+      '#type' => 'table',
+      '#tree' => TRUE,
+      '#header' => array(
+        'field' => t('Configure verbose output'),
+      ),
+      '#title' => t('Keys'),
+      '#empty' => t(
+        'Add keys to display in the verbose output.'
+      ),
+    );
+
+    // Fill the keys table with keys from the settings.
+    $keys = $settings['keys'];
+
+    if (!$form_state->has('keys_rows')) {
+      $form_state->set('keys_rows', count($keys) + 1);
+    }
+    for ($i = 0; $i < $form_state->get('keys_rows'); $i++) {
+      $form['output_table']['keys'][$i] = array(
+        'key' => array(
+          '#type' => 'textfield',
+          '#default_value' => isset($keys[$i]) ? $keys[$i] : '',
+          '#title' => t('Key'),
+          '#title_display' => 'invisible',
+          '#size' => 20,
+        ),
+      );
+    }
+    // Select element for available fields.
+    $form['output_table']['keys_add_button'] = array(
+      '#type' => 'submit',
+      '#value' => t('Add another key'),
+      '#ajax' => array(
+        'wrapper' => 'selected-output',
+        'callback' => array($this, 'keysReplace'),
+        'method' => 'replace',
+      ),
+      '#submit' => array(array($this, 'addKeySubmit')),
+    );
+
     return $form;
   }
 
@@ -398,24 +419,13 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
         $settings['conditions'][] = $condition;
       }
     }
-
-    // Update the verbose output keys.
-    try {
-      $this->currentKeys = $this->sensorConfig->getSetting('keys');
-      $keys = array_filter(explode("\n", $form_state->getValue('keys')));
-      $keys = array_map('trim', $keys);
-      $settings['keys'] = $keys;
-
-      $this->sensorConfig->set('settings', $settings);
-      $this->getQuery()->execute();
-    }
-    catch (DatabaseExceptionWrapper $e) {
-      $settings = $this->sensorConfig->getSettings();
-      $settings['keys'] = $this->currentKeys;
-      $this->sensorConfig->set('settings', $settings);
-      drupal_set_message('Verbose output configuration is invalid, keys were not saved.', 'error');
-      drupal_set_message($e->getMessage(), 'warning');
+    $settings['keys'] = [];
+    foreach ($form_state->getValue('keys') as $delta => $key) {
+      if (!empty($key)) {
+        $settings['keys'][] = $key;
+      }
     }
+    $this->sensorConfig->set('settings', $settings);
   }
 
   /**
@@ -434,7 +444,7 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
   }
 
   /**
-   * Adds sensor to entity when 'Add field' button is pressed.
+   * Add row to table when pressing 'Add another condition' and rebuild.
    *
    * @param array $form
    *   The form structure array.
@@ -450,6 +460,36 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
   }
 
   /**
+   * Returns the updated 'output_table' fieldset for replacement by ajax.
+   *
+   * @param array $form
+   *   The updated form structure array.
+   * @param FormStateInterface $form_state
+   *   The form state structure.
+   *
+   * @return array
+   *   The updated form component for the selected fields.
+   */
+  public function keysReplace(array $form, FormStateInterface $form_state) {
+    return $form['plugin_container']['settings']['output_table'];
+  }
+
+  /**
+   * Adds another field to the keys table when pressing 'Add another key'.
+   *
+   * @param array $form
+   *   The form structure array.
+   * @param FormStateInterface $form_state
+   *   The form state structure.
+   */
+  public function addKeySubmit(array $form, FormStateInterface $form_state) {
+    $form_state->setRebuild();
+
+    $form_state->set('keys_rows', $form_state->get('keys_rows') + 1);
+    drupal_set_message(t('Field added.'), 'status');
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
@@ -457,6 +497,11 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
 
     /** @var \Drupal\Core\Database\Connection $database */
     $database = $this->getService('database');
+    $table = $form_state->getValue(array('settings', 'table'));
+    if (!$database->schema()->tableExists($table)) {
+      $form_state->setErrorByName('settings][table', t('The table %table does not exist in the database %database', ['%table' => $table, '%database' => $database->getConnectionOptions()['database']]));
+      return;
+    }
     $field_name = $form_state->getValue(array(
       'settings',
       'aggregation',
@@ -464,12 +509,23 @@ class DatabaseAggregatorSensorPlugin extends DatabaseAggregatorSensorPluginBase
     ));
     if (!empty($field_name)) {
       // @todo instead of validate, switch to a form select.
-      $table = $form_state->getValue(array('settings', 'table'));
       if (!$database->schema()->fieldExists($table, $field_name)) {
         $form_state->setErrorByName('settings][aggregation][time_interval_field',
-          t('The specified time interval field %name does not exist.', array('%name' => $field_name)));
+          t('The specified time interval field %name does not exist in table %table.', array('%name' => $field_name, $table)));
+      }
+    }
+    $keys = $form_state->getValue('keys');
+    $new_keys = [];
+    foreach ($keys as $delta => $key) {
+      $key_name = $key['key'];
+      if (!empty($key_name)) {
+        if (!$database->schema()->fieldExists($table, $key_name)) {
+          $form_state->setErrorByName('keys][' . $delta . '][key', t('The specified key %name does not exist in table %table.', ['%name' => $key_name, '%table' => $table]));
+        }
+        $new_keys[] = (array_pop($keys[$delta]));
       }
     }
+    $form_state->setValue('keys', $new_keys);
   }
 
 }
