SAT9/.resources/d7e3fba185cda2cee2757dfd4954ed57caa2d28029fa9f1fd2773883b6c220b4
2025-04-18 19:44:27 +04:00

223 lines
7.6 KiB
Plaintext

from urllib2_aws4auth import aws_urlopen, Request
from urllib2 import HTTPError
from urllib import urlencode
import json
import system
import boto3
from pprint import pformat
STAGE = 'prod'
STAGE_CONFIG = {
'alpha':{
'region':'us-east-1',
'endpoint': 'https://0wuzuy9rx3.execute-api.us-east-1.amazonaws.com/prod/user-activity-logger'
},
'beta': {
'region':'us-east-1',
'endpoint': 'https://33ymuc1b2a.execute-api.us-east-1.amazonaws.com/prod/user-activity-logger'
},
'prod': {
'region':'us-east-1',
'endpoint': 'https://ahikprejp4.execute-api.us-east-1.amazonaws.com/prod/user-activity-logger'
}
}
REGION = STAGE_CONFIG.get(STAGE, 'alpha').get('region', 'us-east-1')
SERVICE = 'execute-api'
ENDPOINT = STAGE_CONFIG.get(STAGE, 'alpha').get('endpoint', 'https://0wuzuy9rx3.execute-api.us-east-1.amazonaws.com/prod/user-activity-logger')
LOGGER = system.util.getLogger('productMetrics')
def openSession():
CREDS = boto3.Session().get_credentials()
AWS_ACCESS_KEY_ID = CREDS.access_key
AWS_SECRET_ACCESS_KEY = CREDS.secret_key
TOKEN = CREDS.token
OPENER = aws_urlopen(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
REGION,
SERVICE,
session_token=TOKEN,
verify=False)
return OPENER
def formatPayload(payload):
"""Formats the payload based on what API expects to receive in the payload
Also adds in some defaults (nulls) for the optional fields in case they are skipped from the payload
Since defaults are not defined to required fields, will throw an error if they are not provided in the payload
Args:
payload (dict):all the fields that need to be sent to the API
Returns:
dict: dict formatted correctly for the API call
"""
data = {
"project_id": "scada-activity-logger", #key used to log hashed user product metrics in backend, not the name of ignition project.
"stage": payload.get("stage"),
"plugin": "scada_activity_logger",
"payload": {
"username": payload.get("username"),
"session_id": payload.get("session_id"),
"site": payload.get("site"),
"start_time": payload.get("start_time"),
"end_time": payload.get("end_time", None),
"user_UTCoffset": payload.get("user_UTCoffset", None),
"resource_type": payload.get("resource_type"),
"resource": payload.get("resource"),
"current_page": payload.get("current_page"),
"concurrent_users": payload.get("concurrent_users", getConcurrentUsers())
}
}
return data
def getConcurrentUsers():
"""Get the number of concurrent user session for the current project
Returns:
int: number of concurrent users
"""
project_name = system.project.getProjectName()
concurrent_users = len(system.perspective.getSessionInfo())
return concurrent_users
def createActivityPayload(viewObj, resource_type, resource = None, current_page= None):
"""Creates the activity payload for hashed user product metrics
Typically called from view shutdown event script
Uses the info from the view's custom param named activity_logger and session params to build the payload
Args:
viewObj: reference to the view (since custom param activity_logger is created on the view). If calling this function from a component pass self.view, if calling from view event scripts, pass self
resource_type (string): page/session/click
resource (string, optional): The resource that user interacted with. page name if interaction was with a page, feature/button name if it was a user click type interaction. Defaults to None.
current_page (string, optional): Page name that the user is on when the interaction takes place. Defaults to None.
Returns:
dict: payload that needs to be formatted before sending to the API
"""
if viewObj.session.custom.product_metrics.enable and viewObj.session.props.device.type != 'designer':
# since viewObj is a reference to the view, viewObj.session is reference to session
session = viewObj.session
stage = session.props.gateway.address
user = session.props.auth.user.userName
session_id = session.props.id
site = session.custom.fc
start_time = system.date.format(viewObj.custom.activityLogger.start_time, 'yyyy-MM-dd HH:mm:ss')
end_time = None
user_UTCoffset = session.props.device.timezone.utcOffset
concurrent_users = getConcurrentUsers()
if resource_type == 'page':
end_time = system.date.format(system.date.now(), 'yyyy-MM-dd HH:mm:ss')
try:
pageid = viewObj.custom.activityLogger.pageid
resource = pageid if resource == None else resource
current_page = pageid if current_page == None else current_page
except:
pass
if resource_type == 'click':
start_time = system.date.format(system.date.now(), 'yyyy-MM-dd HH:mm:ss')
end_time = None
try:
pageid = viewObj.custom.activityLogger.pageid
# resource = pageid if resource == None else resource
current_page = pageid if current_page == None else current_page
except:
pass
payload = {
"stage": stage,
"username": user,
"session_id": session_id,
"site": site,
"start_time": start_time,
"end_time": end_time,
"resource_type": resource_type,
"resource": resource,
"current_page": current_page,
"user_UTCoffset": user_UTCoffset,
"concurrent_users": concurrent_users
}
activityPayload = formatPayload(payload)
return activityPayload
else:
return None
def callActivityLoggerAPI(activityPayload):
"""Makes a post api call with the provided payload to log hashed user product metrics
Handles converting the payload from dict to json
Args:
activityPayload (dict): Final payload that needs to be sent to the API
Function will convert the payload to json
"""
if activityPayload:
opener = openSession()
params = activityPayload
payload = json.dumps(params)
method = 'POST'
# in the headers the Ignition session username (session.props.auth.user.userName) must be supplied as 'X-Ignition-User'
headers = {
'Content-type': 'application/json',
}
req = Request(url=ENDPOINT, method=method, data=payload, headers=headers)
# open the request and process the read
try:
resp = opener(req)
response = json.loads(resp.read())
error = None
except HTTPError, e:
error = str(e)
response = None
system.perspective.print(error)
LOGGER.info(error)
return {'error': error, 'response':response }
def callLogger(viewObj, resource_type, resource = None, current_page= None):
"""Combines the createActivityPayload and callActivityLoggerAPI to log hashed user product metrics
Typically called from view shutdown event script
Uses the info from the view's custom param named activity_logger and session params to build the payload
"""
activityPayload = createActivityPayload(viewObj, resource_type, resource, current_page)
if activityPayload:
callActivityLoggerAPI(activityPayload)
def testapi():
print STAGE
user = 'ankikarw'
opener = openSession()
params = {
"project_id": "scada-activity-logger",
"stage": "api test alpha",
"plugin": "scada_activity_logger",
"payload": {
"username": "user",
"session_id": "1234567989",
"site": "EWR4",
"start_time": "2023-11-06 10:45:25",
"end_time": "2023-11-06 10:57:18",
"user_UTCoffset": "-8",
"resource_type": "page",
"resource": "home",
"current_page": "home",
"concurrent_users": "5"
}
}
payload = json.dumps(params)
method = 'POST'
headers = {
'Content-type': 'application/json',
}
req = Request(url=ENDPOINT, method=method, data=payload, headers=headers)
# open the request and process the read
try:
resp = opener(req)
response = json.loads(resp.read())
error = None
print response
except HTTPError, e:
error = str(e)
response = None
print error
LOGGER.info(error)
return {'error': error, 'response':response }