* $query = $graphiteweb->select(); * * * Filtering * --------- * * $query->from('base.$host.$service.$metric') * ->where('host', 'www1') * ->where('service', 'ping'); * * */ class GraphiteQuery { protected $web; protected $search; protected $searchPattern; /** * Construct a new query * * @param GraphiteWeb $web Graphite webapp instance */ public function __construct(GraphiteWeb $web) { $this->web = $web; } /** * Set the base pattern for your query * * @return self */ public function from($base, $pattern = null) { if (is_array($base)) { $key = key($base); if ($pattern === null) { $this->search = current($base); } else { $this->search = $this->replace($pattern, $key, current($base)); } } else { // TODO: well... patterns might also work for non-aliases $base's $this->search = $base; } $this->searchPattern = $this->search; return $this; } /** * Add a filter * * @param string $colum Virtual column we are going to filter for * @param string $search Search string * * @return self */ public function where($column, $search) { $this->search = $this->replace($this->search, $column, $search); return $this; } /** * TODO: rename to getCharts */ public function getImages(GraphTemplate $template) { $charts = array(); foreach ($this->listMetrics() as $metric) { $vars = GraphiteUtil::extractVars($metric, $this->getSearchPattern()); $charts[] = new GraphiteChart($this->web, $template, $metric, $vars); } return $charts; } /** * List all metrics fitting this query * */ public function listMetrics($filterString = null) { if ($filterString === null) { $filterString = $this->toFilterString(); } $metrics = $this->web->listMetrics($filterString); asort($metrics); return $metrics; } /** * Retrieve a distinct list of values fitting a given placeholder in our * search pattern * * Example * ------- * This example retrieves all distinct services available on any host * belonging to our customer "Icinga". * * * $icingaHosts = $graphite * ->select() * ->from('base.$customer.$host.$service.$metric') * ->where('customer', 'icinga') * ->listMetrics('service'); * * * @param string $placeholder The placeholder we are interested in * * @return array */ public function listDistinct($placeholder) { $search = $this->getSearchPattern(); $totalLength = strlen($search); $varLength = strlen($placeholder) + 1; $pos = 0; $found = false; while (false !== ($pos = strpos($search, '$' . $placeholder, $pos + 1))) { if ($pos + $varLength === $totalLength) { $found = $search; break; } if ($search[$pos + $varLength] === '.') { $found = substr($search, 0, $pos + $varLength); break; } } if ($found === false) { return array(); } $pattern = $this->replaceRemainingVariables($found); $metrics = $this->listMetrics($pattern); $distinct = array(); foreach ($metrics as & $metric) { $parts = explode('.', $metric); $value = end($parts); $distinct[$value] = $value; } ksort($distinct); return $distinct; } /** * Get our search pattern * * TODO: example * * @return string */ public function getSearchPattern() { return $this->searchPattern; } protected function replace($string, $key, $replacement) { return preg_replace( '/\$' . preg_quote($key) . '(\.|$)/', $replacement . '\1', $string ); } /** * Replace all variables ($some_thing) with an asterisk * * TODO: I'd opt for \w instead of [^\.] */ protected function replaceRemainingVariables($string) { return preg_replace('/\$[^\.]+(\.|$)/', '*\1', $string); } /** * Create a filter string allowing us to filter metrics */ protected function toFilterString() { return $this->replaceRemainingVariables($this->search); } }