-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
214 additions
and
6 deletions.
There are no files selected for viewing
109 changes: 109 additions & 0 deletions
109
src/python/WMCore/MicroService/MSPileup/MSPileupMonitoring.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
""" | ||
File : MSPileupMonitoring.py | ||
Author : Valentin Kuznetsov <vkuznet AT gmail dot com> | ||
Description: MSPileupMonitoring provides bridge between MSPileup | ||
service and CMS Monitoring infrastructure | ||
""" | ||
|
||
# system modules | ||
import time | ||
|
||
# WMCore modules | ||
from WMCore.MicroService.Tools.Common import getMSLogger | ||
|
||
# CMSMonitoring modules | ||
from CMSMonitoring.StompAMQ7 import StompAMQ7 as StompAMQ | ||
|
||
|
||
def flatDocuments(doc): | ||
""" | ||
Helper function to flat out MSPileup document | ||
:param doc: input MSPileup document | ||
:return: generator of MSPileup documents flatten from original one | ||
""" | ||
docs = flatKey(doc, 'campaigns') | ||
docs = (f for d in docs for f in flatKey(d, 'currentRSEs')) | ||
docs = (f for d in docs for f in flatKey(d, 'expectedRSEs')) | ||
for doc in docs: | ||
yield doc | ||
|
||
|
||
def flatKey(doc, key): | ||
""" | ||
Helper function to flat out values of given key in a document | ||
:param doc: input MSPileup document | ||
:param key: document key to use | ||
:return: generator of MSPileup documents flatten from original one and given key | ||
""" | ||
for item in doc[key]: | ||
ndoc = dict(doc) | ||
# convert plural to singular key name, e.g. campaigns -> campaign | ||
nkey = key[:-1] | ||
ndoc[nkey] = item | ||
del ndoc[key] | ||
yield ndoc | ||
|
||
|
||
class MSPileupMonitoring(): | ||
""" | ||
MSPileupMonitoring represents MSPileup monitoring class | ||
""" | ||
|
||
def __init__(self, msConfig=None): | ||
""" | ||
Constructor for MSPileupMonitoring | ||
""" | ||
self.userAMQ = msConfig.get('user_amq', None) | ||
self.passAMQ = msConfig.get('pass_amq', None) | ||
self.postToAMQ = msConfig.get('post_to_amq', False) | ||
self.topicAMQ = msConfig.get('topic_amq', None) | ||
self.docTypeAMQ = msConfig.get('doc_type_amg', 'cms-ms-pileup') | ||
self.hostPortAMQ = msConfig.get('host_port_amq', None) | ||
self.producer = msConfig.get('producer', 'cms-ms-pileup') | ||
self.logger = msConfig.get('logger', getMSLogger(False)) | ||
|
||
def uploadToAMQ(self, docs, producer=None): | ||
""" | ||
_uploadToAMQ_ | ||
Sends data to AMQ, which ends up in elastic search. | ||
:param docs: list of documents/dicts to be posted | ||
:param producer: service name that's providing this info | ||
:return: {} or {"success": ndocs, "failures": nfailures} | ||
""" | ||
if not docs: | ||
self.logger.info("There are no documents to send to AMQ") | ||
return {} | ||
if not self.userAMQ or not self.passAMQ: | ||
self.logger.info("MSPileupMonitoring has no AMQ credentials, will skip the upload to MONIT") | ||
return {} | ||
|
||
producer = producer or self.producer | ||
ts = int(time.time()) | ||
notifications = [] | ||
|
||
self.logger.debug("Sending %d to AMQ", len(docs)) | ||
try: | ||
stompSvc = StompAMQ(username=self.userAMQ, | ||
password=self.passAMQ, | ||
producer=producer, | ||
topic=self.topicAMQ, | ||
validation_schema=None, | ||
host_and_ports=self.hostPortAMQ, | ||
logger=self.logger) | ||
|
||
for doc in docs: | ||
singleNotif, _, _ = stompSvc.make_notification(payload=doc, doc_type=self.docTypeAMQ, | ||
ts=ts, data_subfield="payload") | ||
notifications.append(singleNotif) | ||
|
||
failures = stompSvc.send(notifications) | ||
msg = "%i out of %i documents successfully sent to AMQ" % (len(notifications) - len(failures), | ||
len(notifications)) | ||
self.logger.info(msg) | ||
return {"success": len(notifications)-len(failures), "failures": len(failures)} | ||
except Exception as ex: | ||
self.logger.exception("Failed to send data to StompAMQ. Error %s", str(ex)) | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
test/python/WMCore_t/MicroService_t/MSPileup_t/MSPileupMonitoring_t.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" | ||
Unit tests for MSPileupMonitoring.py module | ||
Author: Valentin Kuznetsov <vkuznet [AT] gmail [DOT] com> | ||
""" | ||
|
||
# system modules | ||
import unittest | ||
|
||
# WMCore modules | ||
from WMCore.MicroService.MSPileup.MSPileupMonitoring import flatDocuments, flatKey | ||
|
||
|
||
class MSPileupMonitoringTest(unittest.TestCase): | ||
"Unit test for MSPileupMonitoring module" | ||
|
||
def setUp(self): | ||
rses = ['rse1', 'rse2'] | ||
campaigns = ['c1', 'c2'] | ||
ruleIds = ['1', '2'] | ||
self.doc = { | ||
'pileupName': '/klsjdfklsd/klsjdflksdj/PREMIX', | ||
'pileupType': 'classic', | ||
'expectedRSEs': rses, | ||
'currentRSEs': rses, | ||
'fullReplicas': 1, | ||
'campaigns': campaigns, | ||
'containerFraction': 0.0, | ||
'replicationGrouping': "ALL", | ||
'active': True, | ||
'pileupSize': 0, | ||
'ruleIds': ruleIds} | ||
|
||
def testFlatKey(self): | ||
"test flatKey functions" | ||
doc = dict(self.doc) | ||
docs = list(flatKey(doc, 'campaigns')) | ||
self.assertEqual(len(docs), 2) | ||
key = 'campaigns' | ||
nkey = key[:-1] # new single key, e.g. campaigns -> campaign | ||
self.assertEqual(key in docs[0], False) | ||
self.assertEqual(docs[0][nkey], self.doc[key][0]) | ||
|
||
def testFlatDocuments(self): | ||
"test flatDocuments function" | ||
doc = dict(self.doc) | ||
docs = list(flatDocuments(doc)) | ||
self.assertEqual(len(docs), 8) | ||
listKeys = ['campaigns', 'currentRSEs', 'expectedRSEs'] | ||
for doc in docs: | ||
for key in listKeys: | ||
vals = self.doc[key] # original key vaules | ||
nkey = key[:-1] # key without s, e.g. campaigns -> campaign | ||
self.assertEqual(key in doc, False) # original key should be gone | ||
val = doc[nkey] # new value for single key | ||
self.assertEqual(val in vals, True) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters