Fix up README and handle None-values

The results of testing to ensure it handles all the cmdline args
better.

Change-Id: I8b45b1a2335bce16666f404a716f3a440c91c589
This commit is contained in:
Sandy Walsh 2015-02-02 11:32:42 -08:00
parent abba44f40e
commit 6f1edf53eb
3 changed files with 167 additions and 13 deletions

124
README.md
View File

@ -2,3 +2,127 @@ klugman
======= =======
Python library and cmdline tools for accessing Quincy. Python library and cmdline tools for accessing Quincy.
Examples:
```
$ klugman
Usage:
klugman.py [options] <command> [<args>...]
klugman.py (-h | --help)
klugman.py --version
$ klugman -h
Klugman - cmdline and client library for StackTach.v3
Usage:
klugman.py [options] <command> [<args>...]
klugman.py (-h | --help)
klugman.py --version
Options:
-h --help Show this help message
--version Show klugman version
--debug Debug mode
-a, --api_version <api_version>
Which API version to use [default: latest]
--url <url> StackTach.v3 server url [default: http://localhost:8000]
For a list of possible StackTach commands, use:
klugman help
$ klugman help
Klugman - StackTach.v3 client
Usage:
klugman.py [options] streams [<args>...]
klugman.py num-streams [<args>...] [options]
klugman.py [options] archives [<args>...]
Options:
-h, --help show command options
$ klugman num-streams
+----------+-------+
| Property | Value |
+----------+-------+
| count | 19 |
+----------+-------+
$ klugman num-streams --state completed
+----------+-------+
| Property | Value |
+----------+-------+
| count | 4 |
+----------+-------+
$ klugman num-streams --state active
+----------+-------+
| Property | Value |
+----------+-------+
| count | 15 |
+----------+-------+
$ klugman streams -h
usage:
klugman.py streams [options]
options:
--id <id>
get stream with id
--details
return events with each stream
--state <state>
return streams in state
--older_than <datetime>
list streams where first_event < <datetime>
--younger_than <datetime>
list streams where last_event > <datetime>
--trigger_name <name>
list streams with given trigger definition
--distinguishing_traits <dtraits>
list stream with specific distriquishing traits
Stream states:
collecting - collecting events
ready - ready for processing
triggered - being processed
processed - processing completed
error - pipeline processing failed
commit_error - pipeline result commit failed
Distinguishing trait format:
"trait:value;trait:value;..."
$ klugman streams
+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Property | Value |
+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | 17 |
| state | completed |
| name | test_trigger |
| first_event | 2015-01-31 13:21:50.679800 |
| last_event | 2015-01-31 13:36:46.981800 |
| fire_timestamp | 2015-01-30 18:52:03.196602 |
| expire_timestamp | 2015-01-31 14:36:46.981800 |
| distinguishing_traits | {u'instance_id': u'bd8b66f6-745b-45ce-b9c2-43010f8d9cdf', u'timestamp': TimeRange from datetime.datetime(2015, 1, 31, 0, 0) to datetime.datetime(2015, 2, 1, 0, 0)} |
| events | None |
+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
$ klugman streams --distinguishing_traits instance_id:1438620b-e426-4911-81cd-e5f82219a390
...
$ klugman streams --older_than 01-31-2015T13:30
...
$ klugman streams --older_than 01-31-2015T13:30 --state completed
...
```

View File

@ -3,17 +3,29 @@ import timex
import iso8601 import iso8601
def _present(dct, name):
return name in dct and dct[name] is not None and dct[name] != 'None'
def decode_datetime(dct, name): def decode_datetime(dct, name):
if not _present(dct, 'datetime'):
return 'n/a'
return iso8601.parse_date(dct['datetime'], default_timezone=None) return iso8601.parse_date(dct['datetime'], default_timezone=None)
def decode_timerange(dct, name): def decode_timerange(dct, name):
begin = iso8601.parse_date(dct['begin'], default_timezone=None) begin = 'n/a'
end = iso8601.parse_date(dct['end'], default_timezone=None) if _present(dct, 'begin'):
begin = iso8601.parse_date(dct['begin'], default_timezone=None)
end = 'n/a'
if _present(dct, 'end'):
end = iso8601.parse_date(dct['end'], default_timezone=None)
return timex.TimeRange(begin=begin, end=end) return timex.TimeRange(begin=begin, end=end)
def decode_timestamp(dct, name): def decode_timestamp(dct, name):
if not _present(dct, 'timestamp'):
return 'n/a'
timestamp = iso8601.parse_date(dct['timestamp'], default_timezone=None) timestamp = iso8601.parse_date(dct['timestamp'], default_timezone=None)
return timex.Timestamp(timestamp) return timex.Timestamp(timestamp)
@ -24,6 +36,8 @@ DECODE_MAP = {'datetime': decode_datetime,
def object_hook(dct): def object_hook(dct):
if dct is None:
return 'n/a'
if '__type__' in dct: if '__type__' in dct:
name = dct['__type__'] name = dct['__type__']
decoder = DECODE_MAP[name] decoder = DECODE_MAP[name]

View File

@ -17,10 +17,21 @@
import base import base
import json import json
import jsonutil import jsonutil
import sys
from docopt import docopt from docopt import docopt
def check_state(state):
if state and state not in ["active", "firing", "expiring", "error",
"expire_error", "completed",
"retry_fire", "retry_expire"]:
print "Invalid state. %s not one of 'active, firing, " \
"expiring, error, expire_error, completed, " \
"retry_fire or retry_expire" % state
sys.exit(1)
class Streams(object): class Streams(object):
"""usage: """usage:
klugman.py streams [options] klugman.py streams [options]
@ -33,9 +44,9 @@ class Streams(object):
--state <state> --state <state>
return streams in state return streams in state
--older_than <datetime> --older_than <datetime>
list streams older than datetime list streams where first_event < <datetime>
--younger_than <datetime> --younger_than <datetime>
list streams younger than datetime list streams where last_event > <datetime>
--trigger_name <name> --trigger_name <name>
list streams with given trigger definition list streams with given trigger definition
--distinguishing_traits <dtraits> --distinguishing_traits <dtraits>
@ -82,6 +93,7 @@ class Streams(object):
traits = arguments.get('--distinguishing_traits') traits = arguments.get('--distinguishing_traits')
details = arguments.get('--details') details = arguments.get('--details')
check_state(state)
cmd = "streams" cmd = "streams"
if sid: if sid:
cmd = "streams/%s" % sid cmd = "streams/%s" % sid
@ -106,20 +118,22 @@ class NumStreams(object):
return streams in state return streams in state
--older_than <datetime> --older_than <datetime>
list streams older than datetime list streams older than datetime
--older_than <datetime>
list streams where first_event < <datetime>
--younger_than <datetime> --younger_than <datetime>
list streams younger than datetime list streams where last_event > <datetime>
--trigger_name <name>
list streams with given trigger definition
--distinguishing_traits <dtraits> --distinguishing_traits <dtraits>
list stream with specific distriquishing traits list stream with specific distriquishing traits
Stream states: Stream states:
collecting - collecting events active = collecting events
ready - ready for processing firing = about to process events
triggered - being processed expiring = about to expire stream
processed - processing completed error = pipeline processing failed
error - pipeline processing failed expire_error = pipeline expiry failed
commit_error - pipeline result commit failed completed = stream processing completed
retry_fire = re-attempt pipeline firing
retry_expire = re-attempt pipeline expiry
Distinguishing trait format: Distinguishing trait format:
"trait:value;trait:value;..." "trait:value;trait:value;..."
@ -144,6 +158,8 @@ class NumStreams(object):
trigger = arguments.get('--trigger_name') trigger = arguments.get('--trigger_name')
traits = arguments.get('--distinguishing_traits') traits = arguments.get('--distinguishing_traits')
check_state(state)
cmd = "streams/count" cmd = "streams/count"
params = base.remove_empty({'state': state, params = base.remove_empty({'state': state,
'older_than': older, 'older_than': older,