130 lines
5.1 KiB
Python
130 lines
5.1 KiB
Python
# -*- encoding: utf-8 -*-
|
|
#
|
|
# Copyright © 2017 Red Hat
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
import os
|
|
|
|
from oslo_config import cfg
|
|
|
|
from gnocchi import storage
|
|
from gnocchi.storage import _carbonara
|
|
from gnocchi.storage.common import redis
|
|
|
|
|
|
OPTS = [
|
|
cfg.StrOpt('redis_url',
|
|
default='redis://localhost:6379/',
|
|
help='Redis URL'),
|
|
]
|
|
|
|
|
|
class RedisStorage(_carbonara.CarbonaraBasedStorage):
|
|
WRITE_FULL = True
|
|
|
|
STORAGE_PREFIX = "timeseries"
|
|
|
|
def __init__(self, conf, incoming):
|
|
super(RedisStorage, self).__init__(conf, incoming)
|
|
self._client = redis.get_client(conf)
|
|
|
|
def _build_metric_dir(self, metric):
|
|
return os.path.join(self.STORAGE_PREFIX, str(metric.id))
|
|
|
|
def _build_unaggregated_timeserie_path(self, metric, version=3):
|
|
return os.path.join(
|
|
self._build_metric_dir(metric),
|
|
'none' + ("_v%s" % version if version else ""))
|
|
|
|
def _build_metric_path(self, metric, aggregation):
|
|
return os.path.join(self._build_metric_dir(metric),
|
|
"agg_" + aggregation)
|
|
|
|
def _build_metric_path_for_split(self, metric, aggregation,
|
|
timestamp_key, granularity, version=3):
|
|
path = os.path.join(self._build_metric_path(metric, aggregation),
|
|
timestamp_key + "_" + str(granularity))
|
|
return path + '_v%s' % version if version else path
|
|
|
|
def _create_metric(self, metric):
|
|
path = self._build_metric_dir(metric)
|
|
ret = self._client.set(path.encode("utf-8"), "created", nx=True)
|
|
if ret is None:
|
|
raise storage.MetricAlreadyExists(metric)
|
|
|
|
def _store_unaggregated_timeserie(self, metric, data, version=3):
|
|
path = self._build_unaggregated_timeserie_path(metric, version)
|
|
self._client.set(path.encode("utf8"), data)
|
|
|
|
def _get_unaggregated_timeserie(self, metric, version=3):
|
|
path = self._build_unaggregated_timeserie_path(metric, version)
|
|
data = self._client.get(path.encode("utf8"))
|
|
if data is None:
|
|
raise storage.MetricDoesNotExist(metric)
|
|
return data
|
|
|
|
def _delete_unaggregated_timeserie(self, metric, version=3):
|
|
path = self._build_unaggregated_timeserie_path(metric, version)
|
|
data = self._client.get(path.encode("utf8"))
|
|
if data is None:
|
|
raise storage.MetricDoesNotExist(metric)
|
|
self._client.delete(path.encode("utf8"))
|
|
|
|
def _list_split_keys_for_metric(self, metric, aggregation, granularity,
|
|
version=None):
|
|
path = self._build_metric_dir(metric)
|
|
if self._client.get(path.encode("utf8")) is None:
|
|
raise storage.MetricDoesNotExist(metric)
|
|
match = os.path.join(self._build_metric_path(metric, aggregation),
|
|
"*")
|
|
split_keys = set()
|
|
for key in self._client.scan_iter(match=match.encode("utf8")):
|
|
key = key.decode("utf8")
|
|
key = key.split(os.path.sep)[-1]
|
|
meta = key.split("_")
|
|
if meta[1] == str(granularity) and self._version_check(key,
|
|
version):
|
|
split_keys.add(meta[0])
|
|
return split_keys
|
|
|
|
def _delete_metric_measures(self, metric, timestamp_key, aggregation,
|
|
granularity, version=3):
|
|
path = self._build_metric_path_for_split(
|
|
metric, aggregation, timestamp_key, granularity, version)
|
|
self._client.delete(path.encode("utf8"))
|
|
|
|
def _store_metric_measures(self, metric, timestamp_key, aggregation,
|
|
granularity, data, offset=None, version=3):
|
|
path = self._build_metric_path_for_split(metric, aggregation,
|
|
timestamp_key, granularity,
|
|
version)
|
|
self._client.set(path.encode("utf8"), data)
|
|
|
|
def _delete_metric(self, metric):
|
|
path = self._build_metric_dir(metric)
|
|
self._client.delete(path.encode("utf8"))
|
|
|
|
# Carbonara API
|
|
|
|
def _get_measures(self, metric, timestamp_key, aggregation, granularity,
|
|
version=3):
|
|
path = self._build_metric_path_for_split(
|
|
metric, aggregation, timestamp_key, granularity, version)
|
|
data = self._client.get(path.encode("utf8"))
|
|
if data is None:
|
|
fpath = self._build_metric_dir(metric)
|
|
if self._client.get(fpath.encode("utf8")) is None:
|
|
raise storage.MetricDoesNotExist(metric)
|
|
raise storage.AggregationDoesNotExist(metric, aggregation)
|
|
return data
|