Git Product home page Git Product logo

python-argusclient's Introduction

argusclient -- A minimal client library for Argus webservice

This is a minimal and thin layer of Python client code on top of the Argus webservices REST API. Most of the library API is 1:1 with that of REST API so it serves to be more of a convenience than an abstraction. This means you still need to be familiar with the underlying REST API to be effective. For more information on the REST API and data model, refer to the Argus - User Guide. Special thanks to Demian Brecht for giving a lot of feedback early and helping to shape the API and the project.

You can also browse the Python API documentation online at: https://salesforce.github.io/python-argusclient/

A quick primer to using argusclient

Below you will find functional and self-explanatory code that shows how to do the following:

  • Import the relevant pieces from argusclient
  • Create the main entry point and establish login session
  • Query for existing namespaces
  • Create a new namespace
  • Collect metrics and annotations
  • Post metrics and annotations
  • Query for existing dashboards
  • Update or Create dashboard
  • Query for existing alerts
  • Delete alert
  • Create an alert along with a trigger and a notification

In addition, also look at the bundled example named splunk_to_argus.py that shows how to extract metrics from Splunk and push them to Argus.

Some package imports and initializations that we use later

import sys, os, time, calendar, getpass, logging, random
import lxml.etree

from argusclient import *
from argusclient.dashboardtags import DASHBOARD, CHART, TITLE, METRIC, FLAGS

logging.basicConfig()
logging.root.setLevel(logging.INFO)
logging.getLogger("requests").setLevel(logging.WARN)

endpoint = "http://localhost:8080/argusws"
user = "hdara"
password = None

tags = { "host": "hdara-wsl" }
fields = { "user": user }
curtm = long(calendar.timegm(time.gmtime()))*1000
ns_name = "hdara-ns"
ns_access_addl_users = ("hdara",)
dashboard_name = "hdara.test.dashboard"
alert_name = "hdara.test.alert"
scope_name = "hdara"
metric_name = "test"
ans = []

Login to the service and establish session

argus = ArgusServiceClient(user,
                           password or getpass.getpass("SSO password for %s: " % user),
                           endpoint=endpoint)
logging.info("Logging in")
argus.login()

Check if a namespace exists and create one if missing

logging.info("Looking up existing namespace with name: %s", ns_name)
nss = dict((ns.qualifier, ns) for ns in argus.namespaces.values())
ns = nss.get(ns_name)
if not ns:
    logging.info("Creating new namespace with name: %s", ns_name)
    ns = argus.namespaces.add(Namespace(ns_name))

Generate some random metrics against hdara-ns:hdara:test and mark the start and end with annotations.

logging.info("Generating some metric and annotation data for the dashboard")
m = Metric(scope_name, metric_name, tags=tags, namespace=ns_name)
for t in xrange(10, 0, -1):
    # Warden requires 1 minute gap between successive data points.
    ts = curtm-t*60*1000
    m.datapoints[ts] = random.randint(50, 100)
    if not ans or t == 1:
        ans.append(Annotation("script", "hdara", "test", ts, ts, "generated", tags=tags, fields=dict(event=ans and "start" or "end", **fields)))

Send metrics and annotations to Argus

logging.info("Adding metrics data to Argus")
am_resp = argus.metrics.add([m]);
if am_resp.error_count():
    logging.error("Errors reported in metric data: errorCount: %s errorMessages: %s", am_resp.error_count(), am_resp.error_messages())
logging.info("Adding annotation data to Argus")
an_resp = argus.annotations.add(ans)
if an_resp.error_count():
    logging.error("Errors reported in annotation data: errorCount: %s errorMessages: %s", an_resp.error_count(), an_resp.error_messages())

Generate dashboard content

mquery = str(MetricQuery(scope_name, metric_name, "sum", tags=tags, stTimeSpec="-1d", enTimeSpec="-0d", namespace=ns_name))
aquery = str(AnnotationQuery(scope_name, metric_name, "generated", tags=tags, stTimeSpec="-1d", enTimeSpec="-0d"))
content = lxml.etree.tostring(DASHBOARD(
    CHART(
        TITLE("hdara.test"),
        METRIC(mquery, name="hdara.test.metric"),
        FLAGS(aquery, name="hdara.test.annotation"),
        name="Chart"
        )
), method="html")
dashbobj.content = content

Update or Create dashboard

logging.info("Looking up existing dashboard with name: %s", dashboard_name)
dashbobj = argus.dashboards.get_user_dashboard(user, dashboard_name, shared=False)
if not dashbobj:
    logging.info("Creating new dashboard with name: %s", dashboard_name)
    dashbobj = Dashboard(dashboard_name, content, shared=True, description="A new dashboard")
    dashbobj = argus.dashboards.add(dashbobj)
else:
    logging.info("Updating dashboard with name: %s id %s", dashboard_name, dashbobj.argus_id)
    dashbobj.content = content
    argus.dashboards.update(dashbobj.argus_id, dashbobj)
logging.info("Dashboard url: %s", os.path.join(os.path.dirname(endpoint), "argus/#/dashboards", str(dashbobj.argus_id)).replace("-ws", "-ui"))

Look for an existing alert and delete it so that we can recreate it

logging.info("Looking up existing alert with name: %s owned by user: %s", alert_name, user)
alertobj = argus.alerts.get_user_alert(user, alert_name, shared=False)
if alertobj:
    logging.info("Deleting existing alert with name: %s id: %s", alert_name, alertobj.argus_id)
    argus.alerts.delete(alertobj.argus_id)

Finally, create alert with a trigger and a notification

logging.info("Creating new alert with alert name: %s", alert_name)
alertobj = argus.alerts.add(Alert(alert_name, mquery, "* */1 * * *",
                                  trigger=Trigger("hdara.test.trigger", Trigger.GREATER_THAN, 100000, 600000),
                                  notification=Notification("hdara.test.notification", Notification.EMAIL, subscriptions=["[email protected]"]),
                                  shared=True))

python-argusclient's People

Contributors

atul-jha-1805 avatar gavalur-sfdc avatar haridsv avatar hdara-sfdc avatar j-ma-sf avatar mankey101 avatar mveeranala avatar pasha-kuznetsov avatar rrajeevan avatar sanjana-sfdc avatar sbob-sfdc avatar smikolai avatar snehabas avatar sundeepsf avatar svc-scm avatar vmeena0418 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

python-argusclient's Issues

HTTP not found on Alert Obj

I faced this in the alert object but I suspect it occurs across all objects.

Issue: Per documentation, the check to see if alert exists only works if the alert exists.
If it doesn't, it throws httplib.NOT_FOUND(404) exception from here. Traceback below.

All actions including Alert creation/modification should be idempotent. So DELETE and PUT is the way to go. We just need a better mechanism for handling the error.
May be instead of raise, just catch the exception and gently let the calling function know? Thoughts?

Exception:

Traceback (most recent call last):
  File "alert.py", line 32, in <module>
    alertobj = argus.alerts.get_user_alert(user, alert_name, shared=False)
  File "client.py", line 473, in get_user_alert
    alerts = self.argus._request("get", "alerts/meta", params=dict(alertname=alertName, ownername=ownerName, shared=shared))
  File "client.py", line 555, in with_retry
    return f(*args, **kwargs)
  File "client.py", line 588, in with_auth_token
    return f(*args, **kwargs)
  File "client.py", line 708, in _request
    return self._request_no_auth(method, path, params, dataObj, encCls, decCls)
  File "client.py", line 730, in _request_no_auth
    res = check_success(resp, decCls)
  File "client.py", line 744, in check_success
    raise ArgusException("Object not found at endpoint: %s message: %s" % (resp.request.url, resp.text))
argusclient.client.ArgusException: Object not found at endpoint: 
https://<argus_url>/argusws/alerts/meta?shared=False&ownername=<owner_name>&alertname=<alert_name> 
message: {"status":404,"message":"Not Found"}

Deleting notifications fails with AttributeError: 'tuple' object has no attribute 'argus_id'

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/Users/pkuznetsov/sfstore/moncfg/moncfg/__main__.py", line 87, in <module>
    main()
  File "/Users/pkuznetsov/sfstore/moncfg/moncfg/__main__.py", line 65, in main
    services[service].push(config)
  File "/Users/pkuznetsov/sfstore/moncfg/moncfg/argus/arguscfg.py", line 124, in push
    self._delete_notification(argus_alert, argus_notification)
  File "/Users/pkuznetsov/sfstore/moncfg/moncfg/argus/arguscfg.py", line 205, in _delete_notification
    self._call_argus(alert.notifications.delete, notification.argus_id)
  File "/Users/pkuznetsov/sfstore/moncfg/moncfg/argus/arguscfg.py", line 260, in _call_argus
    return argus(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/argusclient-0.2dev_r0-py2.7.egg/argusclient/client.py", line 550, in delete
AttributeError: 'tuple' object has no attribute 'argus_id'

Alerts with multiple notifications and triggers is not handled correctly

Currently, most of the code is written such that it works only with a single notification or trigger. When there are multiple notifications or triggers, the interface is buggy as alert.notifications and alert.trigger code gets set to a service object instead of a list and so the client code can't even access them.

argus.alerts.update returns incomplete object

    @mock.patch('requests.Session.put', return_value=MockResponse(json.dumps(alert_D), 200))
    def testUpdateAlert(self, mockPut):
        res = self.argus.alerts.update(testId, Alert.from_dict(alert_D))
        self.assertTrue(isinstance(self.argus.alerts.get(testId), Alert))
        self.assertEquals(self.argus.alerts.get(testId).to_dict(), alert_D)
        self.assertIn((os.path.join(endpoint, "alerts", str(testId)),), tuple(mockPut.call_args))

        // The following fails:
        for method in ['get', 'add', 'update', 'delete']:
            self.assertTrue(hasattr(res.triggers, method), msg='no alert.triggers.{}()'.format(method))
            self.assertTrue(hasattr(res.notifications, method), msg='no alert.notifications.{}()'.format(method))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.