root  / icecast tips&tricks  / icecast2 - собираем статистику 

icecast logo

Когда есть динамическая статистика по icecast - это хорошо. Но ещё лучше будет её собрать и обработать.

Например в такую таблицу:

CREATE TABLE `new_streams_stat` (
  `ss_id` int(10) unsigned NOT NULL auto_increment,
  `ss_stream` varchar(255) character set utf8 NOT NULL,
  `ss_today` int(10) unsigned NOT NULL default '0',
  `ss_total` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`ss_id`)
) ENGINE=MyISAM ;

И скриптом по крону собирать туда информацию о слушателях:

<?php
include_once '/path/to/db/script.php';
header("Content-Type: text/html; charset=UTF-8");

$scip = '*****.********.ru'; // Сервер, на котором висит Icecast
$scport = 8000; // Порт

$scfp = fsockopen($scip, $scport, $errno, $errstr, 10);

if (!$scfp) die('Socket error: ' . $errno . ' - ' . $errstr);

fputs($scfp,"GET /status3.xsl HTTP/1.0\r\n User-Agent: Icecast Song Status (Mozilla Compatible)\r\n\r\n");
$info = '';
while(!feof($scfp)) {
  $listeners = fgets($scfp, 1000); // Вот то, что нам надо
  //вывод количества слушателей
  $info .= trim($listeners);
}

fclose($scfp);

$info = explode('!!', $info);
unset($info[0]);

foreach ($info as $value) {
  $exploded = explode('%%', $value);
  $new_info[$exploded[0]] = $exploded;
}

$listeners = 0;
foreach ($new_info as $key => $value) {
  $listeners += $value[1];
  if ($value[1] > 0) {
      $streams[$value[0]] = $value[1];
      $query_add[] = "'" . $value[0] . "'";
  }
}

$streams_list = implode(', ', $query_add);

$query_add = '';
foreach ($streams as $key => $value) {
  $query_add[] = "('$key', $value)";
}
$query_add = implode(', ', $query_add);

$query = "SELECT * FROM `new_streams_stat` WHERE `ss_stream` IN ($streams_list)";
$db = new DB();
$result = $db->db_query($query);

if (mysql_num_rows($result) == 0) {
  // insert new values
  $query = "INSERT INTO `new_streams_stat` (`ss_stream`, `ss_today`) VALUES $query_add";
  $db->db_query($query);
} else {
  // select streams which in list
  $query = "SELECT * FROM `new_streams_stat` WHERE ss_stream IN ($streams_list)";
  $result = $db->db_query($query);
  $db_stat = array();
  while ($row = mysql_fetch_assoc($result)) {
    // check maximum
    if ($row['ss_today'] < $streams[$row['ss_stream']]) $row['ss_today'] = $streams[$row['ss_stream']];
    if ($row['ss_total'] < $streams[$row['ss_stream']]) $row['ss_total'] = $streams[$row['ss_stream']];
    // and make db_stat array
    $db_stat[$row['ss_stream']] = array($row['ss_today'], $row['ss_total']);
    // and unset it from streams
    unset($streams[$row['ss_stream']]);
  }

  foreach ($db_stat as $key => $value) $db_stat_imploded[] = "('$key', " . implode(', ', $value) . ')';
  $db_stat_imploded = implode(', ', $db_stat_imploded);
  foreach ($streams as $key => $value) $streams_imploded[] = "('$key', $value, $value)";
  if (!empty($streams_imploded))
    $streams_imploded = implode(', ', $streams_imploded);
  else
    $streams_imploded = '';

  $query = array();
  $query[] = "CREATE TEMPORARY TABLE `tmp_radio_stat` (`stream` VARCHAR(255), `today` INT, `total` INT)";
  $query[] = 'TRUNCATE `tmp_radio_stat`';
  $query[] = "INSERT INTO `tmp_radio_stat` (`stream`, `today`, `total`) VALUES $db_stat_imploded";
  $query[] = "UPDATE `new_streams_stat`, `tmp_radio_stat` SET `new_streams_stat`.`ss_today`=`tmp_radio_stat`.`today`, 
                                                              `new_streams_stat`.`ss_total`=`tmp_radio_stat`.`total`
              WHERE `new_streams_stat`.`ss_stream`=`tmp_radio_stat`.`stream`";
  if ($streams_imploded != '')
    $query[] = "INSERT INTO `new_streams_stat` (`ss_stream`, `ss_today`, `ss_total`) VALUES $streams_imploded";

  foreach ($query as $value) $db->db_query($value);
}
@mysql_close($db->db_link);

?>

Способ с временной таблицей подсмотрен тут. Есть ещё скрипт по очищению значений `today` дабы статистика по дню сегодняшнему была верной:

<?php
include_once '/path/to/db/script.php';
$query = 'UPDATE `new_streams_stat` SET `ss_today` = 0';
$db = new DB();
$db->db_query($query);

?>

И два правила в crontab чтобы оно срабатывало тогда когда это действительно необходимо:

* * * * *     /full/path/to/php /full/path/to/scripts/cli/icecast_stat_cli.php
0 0 * * *     /full/path/to/php /full/path/to/scripts/cli/icecast_field_clear.php

Первое правило срабатывает раз в минуту, а второе - в полночь каждого дня.

LJ