Archives pour la catégorie ‘Zabbix’

zabbix-docker : version 0.2.1

Zabbix-docker est un agent de monitoring Docker pour Zabbix, permettant de récupérer l’ensemble des métriques des containers Docker pour un host voire un cluster (aggrégation des métriques côté serveur Zabbix). Les métriques actuellement supportées sont les suivantes :

  • statut des containers (dont le health check de Docker 1.12)
  • statistiques des containers (RAM, CPU, interfaces réseau et périphériques de stockage)
  • processus en exécution dans les containers
  • évenèments des containers

La version 0.2 apporte en particulier l’exécution par l’API Docker de commandes distantes dans les containers monitorés. Ainsi, en ajoutant vos scripts de collecte des métriques trapper à vos images Docker, les métriques applicatives peuvent être détectées (parsing de la sortie console) et envoyées au serveur Zabbix.

CoreOS : monitoring d’un serveur avec Zabbix

Je viens de publier mes sources nécessaires à la création d’un container Docker avec un agent Zabbix patché par mes soins dans le but de monitorer un serveur CoreOS et ses containers Docker.

URL du dépôt : https://github.com/bhuisgen/docker-zabbix-coreos

zabbix-monitor : moniteur web d’alertes Zabbix

zabbix-monitor

Je publie les sources d’un mini-projet dénommé zabbix-monitor qui pourrait être utile à tout ceux qui monitorent comme moi leurs serveurs avec Zabbix. Comme le nom l’explicite, zabbix-monitor est un moniteur web d’alertes Zabbix.

Caractéristiques :

  • application client-side full JS avec interface responsive pour affichage optimisé sur desktop / tablette / mobile
  • support multi-serveurs possible et paramètres spécifiques par serveur
  • vue des alertes avec filtrage par sevérité
  • vue des derniers évènements détectés
  • vue d’état d’exécution des scénarios web

Dépôt : https://github.com/bhuisgen/zabbix-monitor

Zabbix : patch pour le support des URL longues avec les scénarios Web

zabbix=# ALTER TABLE httpstep ALTER COLUMN url TYPE varchar(2048);
root@zabbix:/usr/share/zabbix # diff -Naur include/schema.inc.php.orig include/schema.inc.php
--- include/schema.inc.php.orig 2014-04-08 15:57:52.336603380 +0200
+++ include/schema.inc.php 2014-04-08 15:58:05.268806754 +0200
@@ -844,7 +844,7 @@
'url' => array(
'null' => false,
'type' => DB::FIELD_TYPE_CHAR,
- 'length' => 255,
+ 'length' => 2048,
'default' => '',
),
'timeout' => array(
root@zabbix:/usr/share/zabbix # diff -Naur include/views/configuration.httpconf.popup.php.orig include/views/configuration.httpconf.popup.php
--- include/views/configuration.httpconf.popup.php.orig	2014-04-08 16:10:49.660807171 +0200
+++ include/views/configuration.httpconf.popup.php	2014-04-08 16:11:25.721372545 +0200
@@ -75,7 +75,7 @@

 	$httpPopupFormList = new CFormList('httpPopupFormList');
 	$httpPopupFormList->addRow(_('Name'), new CTextBox('name', get_request('name', ''), ZBX_TEXTBOX_STANDARD_SIZE, get_request('templated', null), 64));
-	$httpPopupFormList->addRow(_('URL'), new CTextBox('url', get_request('url', ''), ZBX_TEXTBOX_STANDARD_SIZE));
+	$httpPopupFormList->addRow(_('URL'), new CTextBox('url', get_request('url', ''), ZBX_TEXTBOX_STANDARD_SIZE, 'no', 2048));
 	$httpPopupFormList->addRow(_('Post'), new CTextArea('posts', get_request('posts', '')));
 	$httpPopupFormList->addRow(_('Variables'), new CTextArea('variables', get_request('variables', '')));
 	$httpPopupFormList->addRow(_('Timeout'), new CNumericBox('timeout', get_request('timeout', 15), 5));

Zabbix : patch pour l’authentification LDAP par TLS

root@zabbix:/usr/share/zabbix # diff -Naur include/classes/class.cldap.php.orig include/classes/class.cldap.php
--- include/classes/class.cldap.php.orig	2014-03-18 16:08:49.710346146 +0100
+++ include/classes/class.cldap.php	2014-04-08 12:23:00.904298965 +0200
@@ -40,7 +40,7 @@
 			),
 			'referrals' => 0,
 			'version' => 3,
-			'starttls' => null,
+			'starttls' => true,
 			'deref' => null
 		);

Zabbix : partitionnement des tables sous PostgreSQL

Petit résumé sur la configuration du partitionnement des tables Zabbix (version 2.2) avec une base de données PostgreSQL 9.3. Le partionnement des tables est automatique ; il peut être désactivé à tout moment. La suppression des tables est quant à elle à automatiser en cron.

Trigger de gestion du partitionnement journalier

-- Function: trg_daily_partition()

-- DROP FUNCTION trg_daily_partition();

CREATE OR REPLACE FUNCTION trg_daily_partition()
RETURNS trigger AS
$BODY$
DECLARE
tablename text;
partname text;
startdate text;
enddate text;
query text;

BEGIN
tablename := TG_ARGV[0];
partname := tablename || '_' || TO_CHAR(TO_TIMESTAMP(NEW.clock), 'YYYYMMDD');

EXECUTE 'INSERT INTO ' || 'partitions.' || quote_ident(partname) || ' SELECT ($1).*' USING NEW;

RETURN NULL;

EXCEPTION
WHEN undefined_table THEN

startdate := EXTRACT(EPOCH FROM date_trunc('day', TO_TIMESTAMP(NEW.clock)));
enddate := EXTRACT(EPOCH FROM date_trunc('day', TO_TIMESTAMP(NEW.clock) + ('1 day')::interval));

EXECUTE 'CREATE TABLE IF NOT EXISTS ' || 'partitions.' || quote_ident(partname) || ' (CHECK ((clock >= ' || quote_literal(startdate) || ' AND clock < ' || quote_literal(enddate) || '))) INHERITS ( ' || tablename || ' )';
EXECUTE 'CREATE INDEX ' || quote_ident(partname) || '_1 on ' || 'partitions.' || quote_ident(partname) || '(itemid,clock)';

EXECUTE 'INSERT INTO ' || 'partitions.' || quote_ident(partname) || ' SELECT($1).*' USING NEW;

RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

ALTER FUNCTION trg_daily_partition()
OWNER TO zabbix;

Trigger de gestion du partitionnement mensuel

-- Function: trg_monthly_partition()

-- DROP FUNCTION trg_monthly_partition();

CREATE OR REPLACE FUNCTION trg_monthly_partition()
RETURNS trigger AS
$BODY$
DECLARE
tablename text;
partname text;
startdate text;
enddate text;
query text;

BEGIN
tablename := TG_ARGV[0];
partname := tablename || '_' || TO_CHAR(TO_TIMESTAMP(NEW.clock), 'YYYYMM');

EXECUTE 'INSERT INTO ' || 'partitions.' || quote_ident(partname) || ' SELECT ($1).*' USING NEW;

RETURN NULL;

EXCEPTION
WHEN undefined_table THEN

startdate := EXTRACT(EPOCH FROM date_trunc('month', TO_TIMESTAMP(NEW.clock)));
enddate := EXTRACT(EPOCH FROM date_trunc('month', TO_TIMESTAMP(NEW.clock) + ('1 month')::interval));

EXECUTE 'CREATE TABLE IF NOT EXISTS ' || 'partitions.' || quote_ident(partname) || ' (CHECK ((clock >= ' || quote_literal(startdate) || ' AND clock < ' || quote_literal(enddate) || '))) INHERITS ( ' || tablename || ' )';
EXECUTE 'CREATE INDEX ' || quote_ident(partname) || '_1 on ' || 'partitions.' || quote_ident(partname) || '(itemid,clock)';

EXECUTE 'INSERT INTO ' || 'partitions.' || quote_ident(partname) || ' SELECT($1).*' USING NEW;

RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

ALTER FUNCTION trg_monthly_partition()
OWNER TO zabbix;

Création du schéma

CREATE SCHEMA partitions AUTHORIZATION zabbix

Ajout des triggers sur les tables parentes

CREATE TRIGGER partition_trg BEFORE INSERT ON history FOR EACH ROW EXECUTE PROCEDURE trg_daily_partition('history');
CREATE TRIGGER partition_trg BEFORE INSERT ON history_sync FOR EACH ROW EXECUTE PROCEDURE trg_daily_partition('history_sync');
CREATE TRIGGER partition_trg BEFORE INSERT ON history_uint FOR EACH ROW EXECUTE PROCEDURE trg_daily_partition('history_uint');
CREATE TRIGGER partition_trg BEFORE INSERT ON history_str_sync FOR EACH ROW EXECUTE PROCEDURE trg_daily_partition('history_str_sync');
CREATE TRIGGER partition_trg BEFORE INSERT ON history_log FOR EACH ROW EXECUTE PROCEDURE trg_daily_partition('history_log');
CREATE TRIGGER partition_trg BEFORE INSERT ON trends FOR EACH ROW EXECUTE PROCEDURE trg_monthly_partition('trends');
CREATE TRIGGER partition_trg BEFORE INSERT ON trends_uint FOR EACH ROW EXECUTE PROCEDURE trg_monthly_partition('trends_uint');

Fonctions de suppression des partitions

-- Function: delete_daily_partitions(integer)

-- DROP FUNCTION delete_daily_partitions(integer);

CREATE OR REPLACE FUNCTION delete_daily_partitions(max integer)
RETURNS text AS
$BODY$
DECLARE
result RECORD;
tmp text;
tmstp TIMESTAMP;
maxdate DATE;
BEGIN
maxdate := date_trunc('day', NOW() - (max || ' day')::interval);

FOR result IN SELECT * FROM pg_tables WHERE schemaname = 'partitions' LOOP
tmp := SUBSTRING(result.tablename FROM '[0-9_]*$');
IF LENGTH(tmp) <> 9 THEN
CONTINUE;
END IF;

tmstp := TO_TIMESTAMP(tmp, '_YYYYMMDD');
IF tmstp <= maxdate THEN
RAISE NOTICE 'Deleting daily table %', result.tablename;
EXECUTE 'DROP TABLE ' || result.schemaname || '.' || quote_ident(result.tablename);
END IF;
END LOOP;

RETURN 1;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

ALTER FUNCTION delete_daily_partitions(integer)
OWNER TO zabbix;

 

-- Function: delete_monthly_partitions(integer)

-- DROP FUNCTION delete_monthly_partitions(integer);

CREATE OR REPLACE FUNCTION delete_monthly_partitions(max integer)
RETURNS text AS
$BODY$
DECLARE
prefix text;
result RECORD;
tmp text;
tmstp TIMESTAMP;
maxdate DATE;
BEGIN
maxdate := date_trunc('day', NOW() - (max || ' month')::interval);

FOR result IN SELECT * FROM pg_tables WHERE schemaname = 'partitions' LOOP
tmp := SUBSTRING(result.tablename FROM '[0-9_]*$');
IF LENGTH(tmp) <> 7 THEN
CONTINUE;
END IF;

tmstp := TO_TIMESTAMP(tmp, '_YYYYMM');
IF tmstp <= maxdate THEN
RAISE NOTICE 'Deleting monthly table %', result.tablename;
EXECUTE 'DROP TABLE ' || result.schemaname || '.' || quote_ident(result.tablename);
END IF;
END LOOP;

RETURN 'OK';
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

ALTER FUNCTION delete_monthly_partitions(integer)
OWNER TO zabbix;

Exemple d’utilisation :

SELECT delete_daily_partitions(31);
SELECT delete_monthly_partitions(12);

Zabbix : monitoring de Dovecot

Monitoring de l’authentification utilisateur et du nombre d’utilisateurs connectés :

UserParameter=dovecot.auth,doveadm auth -x service=imap -x rip=127.0.0.1 test@noreply.my.domain blablablaaa|grep "auth succeeded"|wc -l
UserParameter=dovecot.who,doveadm who 2>/dev/null|wc -l

Zabbix : monitoring de php-apc

Un petit billet sur le monitoring de PHP-APC avec Zabbix.

Scripts web

Deux scripts PHP sont à placer dans le répertoire de votre serveur Web :

root@www:/var/www# cat apc-stats_mem.php
<?php print(serialize(apc_sma_info())); ?>
root@www:/var/www# cat apc-stats.php
<?php print(serialize(apc_cache_info('',true))); ?>

Script de monitoring Zabbix

Au niveau du monitoring, un nouveau script PHP va se charger de récupérer les valeurs actuelles d’APC :

root@www:/etc/zabbix/scripts# cat apc.php
<?php
$url_stats = "http://localhost/apc-stats.php";
$url_memstats = "http://localhost/apc-stats_mem.php";

$results = file_get_contents($url_stats);
if ($results == "")
   exit(1);

$results = unserialize($results);
$num_hits = $results["num_hits"];
$num_misses = $results["num_misses"];
$hits_ratio = $num_hits / ($num_hits + $num_misses) * 100;
$entries = $results["num_entries"];

$results = file_get_contents($url_memstats);
if ($results == "")
   exit(1);

$results = unserialize($results);
$mem_used = $results["seg_size"] * $results["num_seg"] - $results["avail_mem"];
$mem_available = $results["avail_mem"];

echo("num_hits=$num_hits\n");
echo("num_misses=$num_misses\n");
echo("hits_ratio=$hits_ratio\n");
echo("entries=$entries\n");
echo("mem_used=$mem_used\n");
echo("mem_available=$mem_available\n");
?>

Configuration de l’agent Zabbix

Reste à modifier l’agent Zabbix en y insérant les nouveaux paramètres :

root@www:/etc/zabbix# nano zabbix_agentd.conf
UserParameter=apc.num_hits,/usr/bin/php /etc/zabbix/scripts/apc.php|grep num_hits|cut -d"=" -f2
UserParameter=apc.num_misses,/usr/bin/php /etc/zabbix/scripts/apc.php|grep num_misses|cut -d"=" -f2
UserParameter=apc.hits_ratio,/usr/bin/php /etc/zabbix/scripts/apc.php|grep hits_ratio|cut -d"=" -f2
UserParameter=apc.entries,/usr/bin/php /etc/zabbix/scripts/apc.php|grep entries|cut -d"=" -f2
UserParameter=apc.mem_used,/usr/bin/php /etc/zabbix/scripts/apc.php|grep mem_used|cut -d"=" -f2
UserParameter=apc.mem_available,/usr/bin/php /etc/zabbix/scripts/apc.php|grep mem_available|cut -d"=" -f2

Zabbix : monitoring des IRQ

UserParameter=devint[*],cat /proc/interrupts | grep '$1:' | sed 's/\s/\n/g' | egrep '^[0-9]{1,}$'| awk '{sum+=$1} END {print sum}'

Zabbix : mise en place du partitionnement MySQL

Dans le cas où vous monitorez un nombre important de serveurs et d’items avec Zabbix, le partitionnement des tables SQL est une solution viable afin d’optimiser les performances de votre serveur. Le principe est de scinder horizontalement chaque table en divisant l’ensemble des enregistrements en sous-ensembles plus légers, optimisant ainsi les traitements. Les partitions sont considérées en interne comme de nouvelles tables et bénéficient donc de leurs propres index. Lors des requêtes, MySQL consulte uniquement les partitions nécessaires (un EXPLAIN PARTITION d’une requête confirme ce point). Plusieurs types de partitionnement existent, le plus simple probablement à comprendre étant celui par plage (range).

Dans le cas d’une base de données Zabbix, le partitionnement par range s’effectue au niveau du champ clock des tables. Certaines tables sont à partitionner par jour (history) et d’autres par mois ( trends). Le gain direct consiste en une souplesse de suppression des données, limitées dans ce cas à la suppression des partitions les plus anciennes. Le processus de HouseKeeping de Zabbix, visant à nettoyer toutes les tables par un DELETE sur chaque item, n’est donc plus nécessaire. Gain associé : il est possible d’augmenter la période de rétention des trends.

Voici la procédure de partitionnement des tables Zabbix.

Modification des clés primaires

Le partitionnement par range nécessite certaines modifications au niveaux des clés de certaines tables :

ALTER TABLE `acknowledges` DROP PRIMARY KEY, ADD KEY `acknowledgedid` (`acknowledgeid`);
ALTER TABLE `alerts` DROP PRIMARY KEY, ADD KEY `alertid` (`alertid`);
ALTER TABLE `auditlog` DROP PRIMARY KEY, ADD KEY `auditid` (`auditid`);
ALTER TABLE `events` DROP PRIMARY KEY, ADD KEY `eventid` (`eventid`);
ALTER TABLE `service_alarms` DROP PRIMARY KEY, ADD KEY `servicealarmid` (`servicealarmid`);
ALTER TABLE `history_log` DROP PRIMARY KEY, ADD PRIMARY KEY (`itemid`,`id`,`clock`);
ALTER TABLE `history_log` DROP KEY `history_log_2`;
ALTER TABLE `history_text` DROP PRIMARY KEY, ADD PRIMARY KEY (`itemid`,`id`,`clock`);
ALTER TABLE `history_text` DROP KEY `history_text_2`;

Ajout des partitions sur les tables mensuelles

Les tables mensuelles sont :

  • acknowledges
  • alerts
  • auditlog
  • events
  • service_alarms
  • trends
  • trends_uint

Conservant 12 mois de données, il faut créer pour chaque table 12 partitions + 1 pour le mois suivant le temps de création. A chaque début de mois, une nouvelle partition sera à ajouter (pour le mois suivant) et la plus ancienne est à supprimer.

Sur chacune de ces tables, les partitions sont créées de cette façon (au 31/01/2013) :

ALTER TABLE `acknowledges` PARTITION BY RANGE(clock) (
   PARTITION p201201 VALUES LESS THAN (UNIX_TIMESTAMP("2012-02-01 00:00:00")),
   PARTITION p201202 VALUES LESS THAN (UNIX_TIMESTAMP("2012-03-01 00:00:00")),
   PARTITION p201203 VALUES LESS THAN (UNIX_TIMESTAMP("2012-04-01 00:00:00")),
   PARTITION p201204 VALUES LESS THAN (UNIX_TIMESTAMP("2012-05-01 00:00:00")),
   PARTITION p201205 VALUES LESS THAN (UNIX_TIMESTAMP("2012-06-01 00:00:00")),
   PARTITION p201206 VALUES LESS THAN (UNIX_TIMESTAMP("2012-07-01 00:00:00")),
   PARTITION p201207 VALUES LESS THAN (UNIX_TIMESTAMP("2012-08-01 00:00:00")),
   PARTITION p201208 VALUES LESS THAN (UNIX_TIMESTAMP("2012-09-01 00:00:00")),
   PARTITION p201209 VALUES LESS THAN (UNIX_TIMESTAMP("2012-10-01 00:00:00")),
   PARTITION p201210 VALUES LESS THAN (UNIX_TIMESTAMP("2012-11-01 00:00:00")),
   PARTITION p201211 VALUES LESS THAN (UNIX_TIMESTAMP("2012-12-01 00:00:00")),
   PARTITION p201212 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-01 00:00:00")),
   PARTITION p201301 VALUES LESS THAN (UNIX_TIMESTAMP("2013-02-01 00:00:00"))
);

Ajout des partitions sur les tables journalières

Les tables journalières sont :

  • history
  • history_log
  • history_str
  • history_text
  • history_uint

L’historique étant de 7 jours, chaque table nécessite 7 partitions + 1 pour le jour suivant le temps de création. Chaque jour, une nouvelle partition sera également à ajouter, la plus ancienne à supprimer.

Sur chacune de ces tables, les partitions sont créées de cette façon (au 31/01/2013) :

ALTER TABLE `history` PARTITION BY RANGE(clock) (
   PARTITION p20130124 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-25 00:00:00")),
   PARTITION p20130125 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-26 00:00:00")),
   PARTITION p20130126 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-27 00:00:00")),
   PARTITION p20130127 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-28 00:00:00")),
   PARTITION p20130128 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-29 00:00:00")),
   PARTITION p20130129 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-30 00:00:00")),
   PARTITION p20130130 VALUES LESS THAN (UNIX_TIMESTAMP("2013-01-31 00:00:00")),
   PARTITION p20130131 VALUES LESS THAN (UNIX_TIMESTAMP("2013-02-01 00:00:00"))
);

Automatisation de la rotation des partitions

La rotation des partitions peut être effectuée par des triggers SQL. Ceux-si seront alors appelés par script cron.

DELIMITER //

CREATE PROCEDURE `zabbix`.`cron_monthly` ()
BEGIN
	CALL zabbix.create_monthly_partition("acknowledges");
	CALL zabbix.create_monthly_partition("alerts");
	CALL zabbix.create_monthly_partition("auditlog");
	CALL zabbix.create_monthly_partition("events");
	CALL zabbix.create_monthly_partition("service_alarms");
	CALL zabbix.create_monthly_partition("trends");
	CALL zabbix.create_monthly_partition("trends_uint");
	CALL zabbix.drop_monthly_partition("acknowledges");
	CALL zabbix.drop_monthly_partition("alerts");
	CALL zabbix.drop_monthly_partition("auditlog");
	CALL zabbix.drop_monthly_partition("events");
	CALL zabbix.drop_monthly_partition("service_alarms");
	CALL zabbix.drop_monthly_partition("trends");
	CALL zabbix.drop_monthly_partition("trends_uint");
END //

CREATE PROCEDURE `zabbix`.`cron_daily` ()
BEGIN
	CALL zabbix.create_daily_partition("history");
	CALL zabbix.create_daily_partition("history_log");
	CALL zabbix.create_daily_partition("history_str");
	CALL zabbix.create_daily_partition("history_text");
	CALL zabbix.create_daily_partition("history_uint");
	CALL zabbix.drop_daily_partition("history");
	CALL zabbix.drop_daily_partition("history_log");
	CALL zabbix.drop_daily_partition("history_str");
	CALL zabbix.drop_daily_partition("history_text");
	CALL zabbix.drop_daily_partition("history_uint");
END //

CREATE PROCEDURE `zabbix`.`create_monthly_partition` (TABLENAME VARCHAR(64))
BEGIN
	DECLARE NEXTCLOCK TIMESTAMP;
	DECLARE PARTITIONNAME VARCHAR(16);
	DECLARE CLOCK INT;

	SET NEXTCLOCK = DATE_ADD(NOW(), INTERVAL 1 MONTH);
	SET PARTITIONNAME = DATE_FORMAT(NEXTCLOCK, 'p%Y%m');
	SET CLOCK = UNIX_TIMESTAMP(DATE_FORMAT(DATE_ADD(NEXTCLOCK, INTERVAL 1 MONTH), '%Y-%m-01 00:00:00'));
	CALL zabbix.create_partition(TABLENAME, PARTITIONNAME, CLOCK);
END //

CREATE PROCEDURE `zabbix`.`drop_monthly_partition` (TABLENAME VARCHAR(64))
BEGIN
	DECLARE OLDCLOCK TIMESTAMP;
	DECLARE PARTITIONNAME VARCHAR(16);
	DECLARE CLOCK INT;

    SET @maxdays = 365;
    SET @old = @maxdays+1;
	SET OLDCLOCK = DATE_SUB(NOW(), INTERVAL @old DAY);
	SET PARTITIONNAME = DATE_FORMAT(OLDCLOCK, 'p%Y%m');
	CALL zabbix.drop_partition(TABLENAME, PARTITIONNAME);
END //

CREATE PROCEDURE `zabbix`.`create_daily_partition` (TABLENAME VARCHAR(64))
BEGIN
	DECLARE NEXTCLOCK timestamp;
	DECLARE PARTITIONNAME VARCHAR(16);
	DECLARE CLOCK INT;

	SET NEXTCLOCK = DATE_ADD(NOW(), INTERVAL 1 DAY);
	SET PARTITIONNAME = DATE_FORMAT(NEXTCLOCK, 'p%Y%m%d');
	SET CLOCK = UNIX_TIMESTAMP(DATE_FORMAT(DATE_ADD(NEXTCLOCK, INTERVAL 1 DAY), '%Y-%m-%d 00:00:00'));
	CALL zabbix.create_partition(TABLENAME, PARTITIONNAME, CLOCK);
END //

CREATE PROCEDURE `zabbix`.`drop_daily_partition` (TABLENAME VARCHAR(64))
BEGIN
	DECLARE OLDCLOCK TIMESTAMP;
	DECLARE PARTITIONNAME VARCHAR(16);
	DECLARE CLOCK INT;

    SET @maxdays = 7;
    SET @old = @maxdays+1;
	SET OLDCLOCK = DATE_SUB(NOW(), INTERVAL @old DAY);
	SET PARTITIONNAME = DATE_FORMAT(OLDCLOCK, 'p%Y%m%d');
	CALL zabbix.drop_partition(TABLENAME, PARTITIONNAME);
END //

CREATE PROCEDURE `zabbix`.`create_partition` (TABLENAME VARCHAR(64), PARTITIONNAME VARCHAR(64), CLOCK INT)
BEGIN
	DECLARE RETROWS INT;
	SELECT COUNT(1) INTO RETROWS
		FROM `information_schema`.`partitions`
		WHERE `table_schema` = 'zabbix' AND `table_name` = TABLENAME AND `partition_name` = PARTITIONNAME;

	IF RETROWS = 0 THEN
		SELECT CONCAT("create_partition(", PARTITIONNAME, ",", CLOCK, ")") AS msg;
     	SET @sql = CONCAT('ALTER TABLE `zabbix`.`', TABLENAME, '`', ' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', CLOCK, '));');
		PREPARE STMT FROM @sql;
		EXECUTE STMT;
		DEALLOCATE PREPARE STMT;
	END IF;
END //

CREATE PROCEDURE `zabbix`.`drop_partition` (TABLENAME VARCHAR(64), PARTITIONNAME VARCHAR(64))
BEGIN
	DECLARE RETROWS INT;
	SELECT COUNT(1) INTO RETROWS
		FROM `information_schema`.`partitions`
		WHERE `table_schema` = 'zabbix' AND `table_name` = TABLENAME AND `partition_name` = PARTITIONNAME;

	IF RETROWS = 1 THEN
		SELECT CONCAT( "drop_partition(", TABLENAME, ",", PARTITIONNAME, ")" ) AS msg;
     	SET @sql = CONCAT( 'ALTER TABLE `zabbix`.`', TABLENAME, '`',' DROP PARTITION ', PARTITIONNAME, ';' );
		PREPARE STMT FROM @sql;
		EXECUTE STMT;
		DEALLOCATE PREPARE STMT;
	END IF;
END //

DELIMITER ;

Deux script à planifier en cron vont appeller ces triggers; le premier à chaque début de mois et le second chaque jour :

root@zabbix:~# crontab -l
0 1 1 * * /root/scripts/zabbix_monthly.sh
0 1 * * * /root/scripts/zabbix_daily.sh
root@zabbix:~# cat /root/scripts/zabbix_monthly.sh
#!/bin/sh

mysql -B -h localhost -u root -psecret zabbix -e "CALL cron_monthly();"
root@zabbix:~# cat /root/scripts/zabbix_daily.sh
#!/bin/sh

mysql -B -h localhost -u root -psecret zabbix -e "CALL cron_daily();"

Pour finaliser, le process HouseKeeper de Zabbix est à désactiver (option de configuration DisableHousekeeping).

Haut de page