Support dimensions in gse metrics
diff --git a/_modules/heka_alarming.py b/_modules/heka_alarming.py
index fe5b3b4..d87ed73 100644
--- a/_modules/heka_alarming.py
+++ b/_modules/heka_alarming.py
@@ -46,14 +46,14 @@
return ' && '.join(matchers)
-def dimensions(alarm):
+def dimensions(alarm_or_alarm_cluster):
"""
Return a dict alarm dimensions. Each dimension is validated, and an
Exception is raised if a dimension is invalid.
Valid characters are a-z, 0-9, _, - and /.
"""
- dimensions = alarm.get('dimension', {})
+ dimensions = alarm_or_alarm_cluster.get('dimension', {})
for name, value in dimensions.items():
if name in _disallowed_dimensions:
raise Exception(
diff --git a/heka/files/lua/common/gse.lua b/heka/files/lua/common/gse.lua
index 2e86695..d1a01a6 100644
--- a/heka/files/lua/common/gse.lua
+++ b/heka/files/lua/common/gse.lua
@@ -125,7 +125,7 @@
-- compute the cluster metric and inject it into the Heka pipeline
-- the metric's value is computed using the status of its members
-function inject_cluster_metric(cluster_name, to_alerting)
+function inject_cluster_metric(cluster_name, dimensions, to_alerting)
local payload
local status, alarms = resolve_status(cluster_name)
@@ -156,6 +156,11 @@
}
}
+ for name, value in pairs(dimensions) do
+ table.insert(msg.Fields.tag_fields, name)
+ msg.Fields[name] = value
+ end
+
lma.inject_tags(msg)
lma.safe_inject_message(msg)
end
diff --git a/heka/files/lua/filters/gse_cluster_filter.lua b/heka/files/lua/filters/gse_cluster_filter.lua
index 58f5b62..e8a83f5 100644
--- a/heka/files/lua/filters/gse_cluster_filter.lua
+++ b/heka/files/lua/filters/gse_cluster_filter.lua
@@ -24,6 +24,7 @@
local interval_in_ns = interval * 1e9
local max_inject = (read_config('max_inject') or 10) + 0
local warm_up_period = ((read_config('warm_up_period') or 0) + 0) * 1e9
+local dimensions_json = read_config('dimensions') or ''
local activate_alerting = read_config('activate_alerting') or true
local is_active = false
@@ -42,6 +43,11 @@
attributes.group_by, policy)
end
+local ok, dimensions = pcall(cjson.decode, dimensions_json)
+if not ok then
+ error(string.format('dimensions JSON is invalid (%s)', dimensions_json))
+end
+
function process_message()
local name = read_message('Fields[name]')
local hostname = read_message('Fields[hostname]')
@@ -101,7 +107,7 @@
local injected = 0
for i, cluster_name in ipairs(gse.get_ordered_clusters()) do
if last_index == nil or i > last_index then
- gse.inject_cluster_metric(cluster_name, activate_alerting)
+ gse.inject_cluster_metric(cluster_name, dimensions, activate_alerting)
last_index = i
injected = injected + 1
diff --git a/heka/files/toml/filter/gse_alarm_cluster.toml b/heka/files/toml/filter/gse_alarm_cluster.toml
index 375674a..72b1923 100644
--- a/heka/files/toml/filter/gse_alarm_cluster.toml
+++ b/heka/files/toml/filter/gse_alarm_cluster.toml
@@ -8,6 +8,7 @@
[gse_{{ alarm_cluster_name }}_filter.config]
topology_file = "gse_{{ alarm_cluster_name|replace('-', '_') }}_topology"
+dimensions = '{{ salt['heka_alarming.dimensions'](alarm_cluster)|json }}'
activate_alerting = {{ alarm_cluster.alerting|default(True)|lower }}
{%- if alarm_cluster.interval is defined %}
interval = {{ alarm_cluster.interval }}
diff --git a/tests/lua/test_gse.lua b/tests/lua/test_gse.lua
index 899e15e..be892f5 100644
--- a/tests/lua/test_gse.lua
+++ b/tests/lua/test_gse.lua
@@ -184,33 +184,36 @@
end
function TestGse:test_inject_cluster_metric_for_nova()
- gse.inject_cluster_metric('nova', true)
+ gse.inject_cluster_metric('nova', {key = "val"}, true)
local metric = last_injected_msg
assertEquals(metric.Type, 'gse_metric')
assertEquals(metric.Fields.member, 'nova')
assertEquals(metric.Fields.name, 'cluster_status')
assertEquals(metric.Fields.value, consts.OKAY)
+ assertEquals(metric.Fields.key, 'val')
assertEquals(metric.Payload, '{"alarms":[]}')
end
function TestGse:test_inject_cluster_metric_for_glance()
- gse.inject_cluster_metric('glance', true)
+ gse.inject_cluster_metric('glance', {key = "val"}, true)
local metric = last_injected_msg
assertEquals(metric.Type, 'gse_metric')
assertEquals(metric.Fields.member, 'glance')
assertEquals(metric.Fields.name, 'cluster_status')
assertEquals(metric.Fields.value, consts.DOWN)
+ assertEquals(metric.Fields.key, 'val')
assert(metric.Payload:match("glance%-registry endpoints are down"))
assert(metric.Payload:match("glance%-api endpoint is down on node%-1"))
end
function TestGse:test_inject_cluster_metric_for_heat()
- gse.inject_cluster_metric('heat', true)
+ gse.inject_cluster_metric('heat', {key = "val"}, true)
local metric = last_injected_msg
assertEquals(metric.Type, 'gse_metric')
assertEquals(metric.Fields.member, 'heat')
assertEquals(metric.Fields.name, 'cluster_status')
assertEquals(metric.Fields.value, consts.WARN)
+ assertEquals(metric.Fields.key, 'val')
assert(metric.Payload:match("5xx errors detected"))
assert(metric.Payload:match("1 RabbitMQ node out of 3 is down"))
end