Skip to content

Commit

Permalink
Fix issue MemoryGauge is not resetting values for processes that have…
Browse files Browse the repository at this point in the history
… missing values in the future samples sent to statsd
  • Loading branch information
Petrica Martinescu committed Aug 6, 2016
1 parent b38186e commit 1af7869
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 68 deletions.
84 changes: 83 additions & 1 deletion Gauge/ProcessesGauge.php
Expand Up @@ -11,6 +11,7 @@
use Petrica\StatsdSystem\Model\Process\Process;
use Petrica\StatsdSystem\Model\Process\TopProcessParser;
use Petrica\StatsdSystem\Model\TopCommand;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

class ProcessesGauge implements GaugeInterface
{
Expand All @@ -23,6 +24,13 @@ class ProcessesGauge implements GaugeInterface
*/
protected $command;

/**
* This is the cache namespace
*
* @var string
*/
protected $namespace;

/**
* ProcessesGauge constructor.
*
Expand All @@ -37,6 +45,8 @@ public function __construct($cpuAbove = 5.0, $memoryAbove = 1.0)
$this->memoryAbove = $memoryAbove;

$this->command = new TopCommand();

$this->namespace = 'statsd.localhost';
}

/**
Expand All @@ -60,7 +70,9 @@ public function getCollection()
$memory = $this->aggregateMemory($processes);
$memory = $this->filterAbove($memory, $this->memoryAbove);

$collection = new ValuesCollection();
// Get previous values saved
$collection = $this->retrieveCollection();
$this->resetValues($collection);

foreach ($cpu as $name => $value) {
$collection->add($name . '.cpu.value', $value);
Expand All @@ -70,6 +82,11 @@ public function getCollection()
$collection->add($name . '.memory.value', $value);
}

// Persist collection to a temporary storage
$copyCollection = new ValuesCollection($collection->getValues());
$this->removeEmpty($copyCollection);
$this->persistCollection($copyCollection);

return $collection;
}

Expand Down Expand Up @@ -152,4 +169,69 @@ protected function getCommand()
return $this->command;
}

/**
* Persist collection values to a temporary storage
* key is the command string value
*
* @param $collection
*/
protected function persistCollection($collection)
{
$cache = new FilesystemAdapter($this->namespace);
$item = $cache->getItem('collection');
$item->set($collection);
$cache->save($item);
}

/**\
* Retrieve a new collection of a previous collection
*
* @return mixed|ValuesCollection
*/
protected function retrieveCollection()
{
$cache = new FilesystemAdapter($this->namespace);
$item = $cache->getItem('collection');

$collection = null;
if ($item->isHit()) {
$collection = $item->get('collection');
}

if (empty($collection) || !$collection instanceof ValuesCollection) {
$collection = new ValuesCollection();
}

return $collection;
}

/**
* Reset collection values to 0
*
* These are in fact previous collection values that needs to be sent to statsd as 0
*
* @param $collection
*/
protected function resetValues($collection) {
foreach ($collection as $key => $value) {
$collection[$key] = 0;
}

return $collection;
}

/**
* Remove empty values from collection
*
* @param $collection
*/
protected function removeEmpty($collection) {
foreach ($collection as $key => $value) {
if (empty($value)) {
unset($collection[$key]);
}
}

return $collection;
}
}
3 changes: 3 additions & 0 deletions Gauge/RemoteProcessesGauge.php
Expand Up @@ -42,5 +42,8 @@ public function __construct($sshString, $sshPort = null, $sshIdentityFile = null
$this->sshPort = $sshPort;

$this->command = new RemoteTopCommand($this->sshString, $this->sshPort, $this->sshIdentityFile);


$this->namespace = preg_replace('/[^-+_.A-Za-z0-9]*/i', '', 'statsd.' . $this->sshString . '.' . $this->sshPort);
}
}
64 changes: 0 additions & 64 deletions Tests/Gauge/PorcessesGaugeTest.php

This file was deleted.

137 changes: 137 additions & 0 deletions Tests/Gauge/ProcessesGaugeTest.php
@@ -0,0 +1,137 @@
<?php
/**
* Created by PhpStorm.
* User: Petrica
* Date: 5/29/2016
* Time: 13:10
*/
namespace Petrica\StatsdSystem\Tests\Gauge;

use Petrica\StatsdSystem\Collection\ValuesCollection;
use Petrica\StatsdSystem\Gauge\ProcessesGauge;
use Petrica\StatsdSystem\Gauge\RemoteProcessesGauge;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

class ProcessesGaugeTest extends \PHPUnit_Framework_TestCase
{
public function testGetGauge()
{
$gauge = $this->getMockBuilder('Petrica\StatsdSystem\Gauge\ProcessesGauge')
->setMethods(array(
'getCommand'
))
->getMock();

$command = $this->getMockBuilder('Petrica\StatsdSystem\Model\TopCommand')
->setMethods(array(
'run'
))
->getMock();

$command->method('run')
->willReturn(array(
array(),
array(),
array(),
array(),
array(),
array(),
array(),
array(
'1', 'root', '0', '0', '0', '0', '0', '0', '10.5', '5.5', '0:0', 'process_name'
),
array(
'2', 'root', '0', '0', '0', '0', '0', '0', '3.5', '1.5', '0:0', 'process_name'
),
array(
'3', 'root', '0', '0', '0', '0', '0', '0', '2', '0.5', '0:0', 'process_name_exclude'
),
array(
'4', 'root', '0', '0', '0', '0', '0', '0', '5', '2.5', '0:0', 'other_process'
)
));

$gauge->method('getCommand')
->willReturn($command);

$cache = new FilesystemAdapter('statsd.localhost');
$item = $cache->getItem('collection');

$cacheCollection = new ValuesCollection();
$cacheCollection->add('test_cache', 5);

$item->set($cacheCollection);
$cache->save($item);

$collection = $gauge->getCollection();

$expected = new ValuesCollection();
$expected->add('process_name.cpu.value', 14);
$expected->add('other_process.cpu.value', 5);
$expected->add('process_name.memory.value', 7);
$expected->add('other_process.memory.value', 2.5);
$expected->add('test_cache', 0);

$this->assertEquals($expected, $collection);

$cache->clear();
}

/**
* Test cache system
*/
public function testPersistCollection()
{
$gauge = new ProcessesGauge();

$class = new \ReflectionClass('Petrica\StatsdSystem\Gauge\ProcessesGauge');
$persistMethod = $class->getMethod('persistCollection');
$persistMethod->setAccessible(true);

$class = new \ReflectionClass('Petrica\StatsdSystem\Gauge\ProcessesGauge');
$retrieveCollection = $class->getMethod('retrieveCollection');
$retrieveCollection->setAccessible(true);

$collection = new ValuesCollection();
$collection->add('test_1', 1);
$collection->add('test_2', 2);

$persistMethod->invokeArgs($gauge, array($collection));

$retreive = $retrieveCollection->invoke($gauge);

$cache = new FilesystemAdapter('statsd.localhost');
$cache->clear();

$this->assertEquals($collection, $retreive);
}

/**
* Test remote cache system
*/
public function testPersistRemoteCollection()
{
$gauge = new RemoteProcessesGauge('root@127.0.0.1', 22);

$class = new \ReflectionClass('Petrica\StatsdSystem\Gauge\ProcessesGauge');
$persistMethod = $class->getMethod('persistCollection');
$persistMethod->setAccessible(true);

$class = new \ReflectionClass('Petrica\StatsdSystem\Gauge\ProcessesGauge');
$retrieveCollection = $class->getMethod('retrieveCollection');
$retrieveCollection->setAccessible(true);

$collection = new ValuesCollection();
$collection->add('test_1', 1);
$collection->add('test_2', 2);

$persistMethod->invokeArgs($gauge, array($collection));

$retreive = $retrieveCollection->invoke($gauge);

$cache = new FilesystemAdapter('statsd.127.0.0.1.22');
$cache->clear();

$this->assertEquals($collection, $retreive);
}
}
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -23,7 +23,8 @@
"symfony/console": "^3.0",
"symfony/yaml": "^3.0",
"symfony/config": "^3.0",
"tivie/command": "*"
"tivie/command": "*",
"symfony/cache": "^3.1"
},
"require-dev": {
"phpunit/phpunit": ">= 4.8.0",
Expand Down

0 comments on commit 1af7869

Please sign in to comment.