Seismometer message

Examples of use

Creating a new message

Very basic message carrying just a single value:

from seismometer.message import Message

msg = Message(
    aspect = "users logged in",
    location = { "host": os.uname()[1] },
    value = 200,
)
print json.dumps(msg.to_dict(), sort_keys = True)

Message about Apache not working:

from seismometer.message import Message

msg = Message(
    aspect = "process state",
    location = { "host": os.uname()[1], "service": "apache" },
    state = "down", severity = "error",
)
print json.dumps(msg.to_dict(), sort_keys = True)

More verbose message carrying information about disk space on /:

from seismometer.message import Message, Value

msg = Message(
    aspect = "disk space",
    location = { "host": os.uname()[1], "filesystem": "/" },
)
# set value and thresholds at the same time
msg["free"] = Value(200, unit = "MB") \
                  .set_below(512, "warning", "warning") \
                  .set_below(256, "critical", "error")
# value can be set with integer
msg["total"] = 1024
# value can be updated
msg["total"].unit = msg["free"].unit

print json.dumps(msg.to_dict(), sort_keys = True)

Altering an incoming message

Replace total + free with used + free in message about disk space:

from seismometer.message import Message

# pretend that this artificial message came from outside
incoming = {
    "v": 3,
    "time": int(time.time()),
    "location": { "host": os.uname()[1], "filesystem": "/" },
    "event": {
        "name": "disk space",
        "vset": { "free": { "value": 200 }, "total": { "value": 1024 } }
    }
}

msg = Message(message = incoming)
msg["used"] = int(msg["total"]) - int(msg["free"])
# alternatively:
#msg["used"] = msg["total"].value - msg["free"].value
del msg["total"]

print json.dumps(msg.to_dict(), sort_keys = True)

Add a location to a message:

from seismometer.message import Message

# pretend that this artificial message came from outside
incoming = {
    "v": 3,
    "time": int(time.time()),
    "location": { "host": os.uname()[1] },
    "event": {
        "name": "disk space",
        "vset": { "free": { "value": 200 }, "total": { "value": 1024 } }
    }
}

msg = Message(message = incoming)
msg.location["filesystem"] = "/"

print json.dumps(msg.to_dict(), sort_keys = True)

Checking a message for exceeding thresholds

from seismometer.message import Message, Value

msg1 = Message(
    aspect = "dummy",
    location = { "host": os.uname()[1], "item": "1" },
    value = Value(100).set_above(200, "error"),
)
msg2 = Message(
    aspect = "dummy",
    location = { "host": os.uname()[1], "item": "2" },
    value = Value(202).set_above(200, "error"),
)

# simple check on all there is in msg1
result = msg1.exceeds()
if result is None:
    print "msg1 in norm"
else:
    print "msg1 exceeds %s (severity %s)" % (result[0], result[1])

# check for exceeding high thresholds, value "value" only
result = msg2['value'].is_above()
if result is None:
    print "msg2 in norm"
else:
    print "msg2 > %s (severity %s)" % (result[0], result[1])

# check against hardcoded threshold
if msg2['value'] <= 100:
    print "msg2[value] doesn't exceed threshold (or is None)"
else:
    print "msg2[value] > 100"

# check if the value is set
if msg2['value'] == None:
    print "msg2[value] is unset"

Programming interface

Messages are expected to conform to message schema.

seismometer.message.SCHEMA_VERSION = 3

Version of schema this module supports. Equals to 3, meaning the module supports message schema v3.

seismometer.message.is_valid()
Parameters:message – object to check
Returns:True if message is a dictionary with Seismometer structure, False otherwise

Function to tell dictionary with a Seismometer message from other dictionaries and objects.

seismometer.message.is_metric()
Parameters:message – object to check
Returns:True if message is a dictionary with Seismometer structure, False otherwise

Function to tell dictionary with a Seismometer message and carrying a metric (or metrics) from other dictionaries and objects.

seismometer.message.is_state()
Parameters:message – object to check
Returns:True if message is a dictionary with Seismometer structure and carries state, False otherwise

Function to tell dictionary with a Seismometer message and carrying a state from other dictionaries and objects.

Message class

class seismometer.message.Message(message=None, time=None, interval=None, aspect=None, location=None, state=None, severity=None, comment=None, value='NOT_SPECIFIED')

Class representing single message suitable for Seismometer.

An instance supports dict-like interface to access values (event.vset.*). len(instance) returns a number of values in value set. Each value is an instance of Value class. Setting a value to integer, float, or None results in creating new Value. Setting it to Value does not copy the original value.

If a message does not conform to schema, ValueError is thrown.

Parameters:
  • message – message to create representation for
  • time (integer) – unix timestamp of event; defaults to time.time()
  • interval (number of seconds) – interval at which event is generated
  • aspect (string) – monitored aspect’s name
  • location (dictionary(str => str)) – where the monitored aspect is located
  • state (string) – state of the monitored aspect
  • severity ("expected", "warning", or "error") – what type is the aspect’s state
  • comment (string) – comment on monitored aspect’s state
  • value (float, integer, Value, or None) – set value named "value" to this value

Either message or rest of the parameters should be set.

copy()

Return a deep copy of the message instance.

exceeds()
Returns:tuple (threshold,severity) or None

Check if any of the values carried exceed its threshold. If more than one value exceeds a threshold, an arbitrary one is returned.

items()

Retrieve values as (name,instance) pairs.

iteritems()

Retrieve values as (name,instance) pairs (iterator).

keys()

Retrieve names of the values this message carries.

to_dict()

Create a dictionary representing the message.

The result shares nothing with the original message, so can be safely modified after creation.

values()

Retrieve value instances (Value) this message carries.

aspect

Name of the monitored aspect this message refers to. (read-write)

comment

Description of the state readable by user. (read-write-delete)

interval

Interval at which the event is generated. None means the event is not generated on a regular basis. (read-write-delete)

location

Location dictionary(-like). Keys and values are both strings. (read-write)

Individual keys can be added/deleted as with typical dictionary. To reset location wholly a dictionary can be assigned to this attribute.

severity

Severity of the state. (read-write-delete)

Either "expected", "warning", or "error".

state

State carried by the event. (read-write-delete)

Deleting the state deletes also severity.

threshold_kept

What state to assume when all thresholds for values are kept.

Note that setting this attribute doesn’t make state magically appear. It’s informative only.

time

Unix timestamp at which the event occurred. (read-write-delete)

v

Base schema version this message conforms to. (read-only)

Equals to SCHEMA_VERSION.

Auxiliary classes

These classes represent specific data inside of Message.

class seismometer.message.Value(value, name=None, unit=None, type=None)

Value representation for Seismometer message.

Value instance is convertible to integer and float (int(v)) if it doesn’t represent None.

Value instance is comparable (e.g. <= or ==) with numerics, other Value instances and with None. None is always smaller than any numeric.

Parameters:
  • value (integer, float, or None) – value
  • name – name of the value
  • unit – unit of measurement
  • type ("direct", "accumulative", or "differential") – type of change of the value
copy()

Deep copy of the instance.

exceeds()
Returns:name and severity of exceeded threshold or None
Return type:tuple (str, str)

Check which threshold is exceeded (highest from high thresholds or lowest from low).

has_thresholds()

Check if the value has any thresholds.

is_above()
Returns:name and severity of exceeded threshold or None
Return type:2-tuple or None

Check which high threshold is exceded (value > threshold).

is_below()
Returns:name and severity of exceeded threshold or None
Return type:2-tuple or None

Check which low threshold is exceded (value < threshold).

remove_threshold(name, which='both')
Parameters:
  • name – name of threshold to remove
  • which ("above" ("high"), "below" ("low") or "both") – which

Remove threshold (high, low, or both).

set_above(value, name, severity='error')
Parameters:
  • value – value of the threshold
  • name – name of the threshold
  • severity ("warning" or "error") – severity of the threshold
Returns:

self

Add/change high threshold.

set_below(value, name, severity='error')
Parameters:
  • value – value of the threshold
  • name – name of the threshold
  • severity ("warning" or "error") – severity of the threshold
Returns:

self

Add/change low threshold.

thresholds()
Returns:list of thresholds: (name, low, high)
Return type:list of 3-tuples

Return all defined thresholds: low and high. If only threshold low or high for a given name is defined, the other is reported as None.

to_dict()

Dictionary representing the value.

name

Name of the value (read-only).

type

Type of change: direct, accumulative (integral of actual value) or differential (read-wite-delete).

unit

Unit of measurement (read-write-delete).

value

Value (read-write).

class seismometer.message.Location(location)

Dictionary-like object that checks if elements have valid names/types for location.

copy()

Duplicate the instance as a dict.

get(name, default=None)

Return location field without raising an exception on undefined key.

items()

Retrieve location (key,value) pairs.

iteritems()

Retrieve location (key,value) pairs as an iterator.

keys()

Retrieve location keys.

to_dict()

Convert the instance to dict.

values()

Retrieve location values.