commit aa0f33ab90551b8ac46290b35ce6b6e0239bbc8c Author: admin Date: Sun Aug 3 21:21:54 2025 +0000 Upload files to "/" diff --git a/aggregation-test.py b/aggregation-test.py new file mode 100644 index 0000000..e835000 --- /dev/null +++ b/aggregation-test.py @@ -0,0 +1,66 @@ +# +# Network paths - See how data is aggregated by changing hours_back and +# hour_range and seeing how Period changes. +# + +import math +from api_fns import * + +count = 0 +metric = 'availablecapacity' + +org_id = '11111' # organization ID +path_id = 222222 # network path ID +hours_back = 24*0 # the number of hours ago the range ends +hour_range = 24*10 # the number of hours in the range + +if (hours_back == 0) & (hour_range == 0): + start = end = None +else: + if (hour_range == 0): + hour_range = 1 + end = math.floor(time.time()-(60*60*hours_back)) + start = (end - math.floor(60*60*hour_range)) + +print('Start time: {} ({})'.format(time.ctime(start), start)) +print('End time: {} ({})'.format(time.ctime(end), end)) +print('Org id: ({})'.format(org_id)) +print('Path id: ({})'.format(path_id)) + +r1 = get_network_path_stats_id(org_id, path_id, start, end, metric) +if r1.status_code == requests.codes.ok: + for network_path_stats in r1.json(): + print(' Network path ({})'.format(network_path_stats['pathId'])) + # pp_json(network_path_stats) + + if network_path_stats['pathId'] == path_id: + # pp_json(network_path_stats) + if network_path_stats['instrumentation'] == "ONE_WAY": + # Single-ended paths have data within 'data' + for test in network_path_stats['data']['availableCapacity']: + count += 1 + print(' Single-ended path -> Start time={}' + + ' Period={} Available Capacity value={} count={}' + .format(time.ctime(test['start']/1000), + test['period'], + math.floor(test['value']), count)) + # pp_json(test) + else: + # Dual-ended paths have data within + # 'dataInbound' and 'dataOutbound' + for test in network_path_stats['dataInbound']['availableCapacity']: + count += 1 + print(' Dual-ended path -> Start time={}' + + ' Period={} Available Capacity value={} count={}' + .format(time.ctime(test['start']/1000), + test['period'], + math.floor(test['value']), count)) + # pp_json(test) + +elif r1.status_code == requests.codes.bad_request: + print_err_json(r1.json()) +else: + print_err(r1) + +print('Start time: {} ({})'.format(time.ctime(start), start)) +print('End time: {} ({})'.format(time.ctime(end), end)) diff --git a/apdex-test.py b/apdex-test.py new file mode 100644 index 0000000..ec7f50c --- /dev/null +++ b/apdex-test.py @@ -0,0 +1,147 @@ +import requests +from requests.auth import HTTPBasicAuth +import json +from credentials import username, password, apm_server +from influxdb import InfluxDBClient +import argparse +import time +import datetime +from api_fns import * +import re + +datato = (int(time.time()))-(1*60) +datafrom = int(datato - (7*60)) + + +def process(influxhost, influxport,debug,myResponse): +# get the organiztion id + r1 = get_org() + tags={} + fields ={} + if r1.status_code == requests.codes.ok: + for organization in r1.json(): + print('organization:', organization ) + #get the web apps for the particular organization + r2 = get_web_app_group(organization['id']) + if r2.status_code == requests.codes.ok: + for group in r2.json(): + #get the monitoring points for the web app + r3 = get_web_path(group['id']) + if r3.status_code == requests.codes.ok: + for web_path in r3.json(): + #for analysis considering only events without any error messages + #if (web_path['status']=='OK' and web_path['statusWithMuted']=='OK' and web_path['errorMsg']=='' ): + + tags['appliance_name'] = web_path['location']['applianceName'] + location = web_path['location']['applianceName'] + + if 'appneta' in location: + for m in re.finditer('-', location): + last_index = m.start() + tags['location'] = location[last_index+1:].upper() + else: + tags['location'] = location + + tags['web_App_id'] = web_path['webPathConfig']['webAppId'] + tags['target_url']=web_path['target']['url'] + milestones = web_path['userFlow']['milestones'] + tags['web_Path_id'] = web_path['id'] + web_AppName = web_path['webPathConfig']['webAppName'] + if '_' in web_AppName and 'WIP' not in web_AppName: + for m in re.finditer('_', web_AppName): + match = m.start() + tags['Web_Application'] = web_AppName[:match] + else: + tags['Web_Application'] = web_AppName + + tags['web_AppName_Region'] = web_path['webPathConfig']['webAppName'] + #fields['Apdex_score'] = web_path['latestMeasurements']['apdexScore']['value'] + #fields['Response_time'] = web_path['latestMeasurements']['responseTime']['value'] + # fields['Total_time_latest'] = web_path['latestMeasurements']['totalTime']['value'] + metrics = 'networktiming,servertiming,browsertiming,apdexscore' + try: + #get breakdown of network, server & browser timing ,apdex score for each milestone + r4 = get_web_path_stats_id(group['id'], web_path['id'], metric=metrics) + if r4.status_code == requests.codes.ok: + for i in range ((len(milestones))): + + tags['Milestone'] = milestones[i] + network_timings = r4.json()['milestones'][i]['networkTiming'] + server_timings = r4.json()['milestones'][i]['serverTiming'] + browser_timings = r4.json()['milestones'][i]['browserTiming'] + apdex_score = r4.json()['milestones'][i]['apdexScore'] + + for i in range((len(network_timings))): + start_time = network_timings[i]['start'] + # s, ms = divmod(start_time, 1000) # (1236472051, 807) + # fields['timestamp'] = '%s.%03d' % (time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(s)), ms) + + #time conversion to format acceptable by InfluxDb + timestamp = datetime.datetime.utcfromtimestamp(start_time/1000).strftime('%Y-%m-%dT%H:%M:%S%Z') + fields['apdexScore'] = apdex_score[i]['value'] + fields['networkTiming'] = network_timings[i]['value'] + fields['serverTiming'] = server_timings[i]['value'] + fields['browserTiming'] = browser_timings[i]['value'] + fields['Total_time_permilestone'] = fields['networkTiming'] + fields['serverTiming'] + fields['browserTiming'] + + if (debug):print(tags) + if (debug):print(fields) + writeinflux ("apdex_responseTime",tags,timestamp,fields,influxhost,influxport) + else: + print_err(r4) + except: + print('Error Message: ', web_path['status'] ) + + # except: + # print('Error message') + + tags={} + fields ={} + + else: + print_err(r3) + else: + print_err(r2) + else: + print_err(r1) + + +def main(influxhost, influxport,debug,myResponse,): + url = "https://"+apm_server+"/api/v3/webApplication?from="+str(datafrom)+"&to="+str(datato)+"&api_key=v3" + myResponse = requests.get(url,auth=HTTPBasicAuth(username, password), verify=True) + process(influxhost,influxport,debug,myResponse) + + +# labels, tags, time, count +def writeinflux(measurement,tags,time,fields,influxhost,influxport): + influxuser = 'CMWrite' + influxpass = 'CMWrite' + databasename = 'ASPM' + client = InfluxDBClient(host=influxhost, port=influxport, username=influxuser, password=influxpass, database=databasename) + json_body = [ + { + "measurement": measurement, + "tags": tags, + "time": time, + "fields": fields + } + ] +# client.write_points(json_body,time_precision='ms') + if client.write_points(json_body): print("Write points: {0}".format(json_body,time_precision='s')) #,time_precision='s' + else: print("ERROR--> Write points: {0}".format(json_body)) + +# Allow command line overrides for host and port influxDB +def parse_args(): + parser = argparse.ArgumentParser( + description='Write WebApplication data from Appneta into InfluxDB database') + parser.add_argument('--host', type=str, required=False, default='itmetricsdb.mathworks.com', + help='hostname of InfluxDB http API') + parser.add_argument('--port', type=int, required=False, default=8086, + help='port of InfluxDB http API') + parser.add_argument('--debug', action='store_true') + return parser.parse_args() + +# grab arguments +if __name__ == '__main__': + args = parse_args() + main(influxhost=args.host, influxport=args.port,debug=args.debug, myResponse={}) \ No newline at end of file diff --git a/api_fns.py b/api_fns.py new file mode 100644 index 0000000..aa3a1de --- /dev/null +++ b/api_fns.py @@ -0,0 +1,305 @@ +# +# Functions to access the AppNeta APM API +# +import requests +import json +import time +from credentials import username, password, apm_server + + +# +# Print error response code and error text returned +# +def print_err(resp): + print('***Response code: {}***'.format(resp.status_code)) + print(resp.text) + + +# +# Print HTTP response code and error text returned with JSON formatted errors +# +def print_err_json(resp_json): + print('***HTTP response: {} - {}***'.format(resp_json['httpStatusCode'], + resp_json['messages'][0])) + # pp_json(resp_json) + + +# +# Pretty print json. Useful to view JSON formatted response data. +# json_obj - JSON object to be printed +# sort - whether to sort the JSON data +# indents - number of spaces for indents +# +def pp_json(json_obj, sort=True, indents=4): + if type(json_obj) is str: + print(json.dumps(json.loads(json_obj), sort_keys=sort, indent=indents)) + else: + print(json.dumps(json_obj, sort_keys=sort, indent=indents)) + return None + + +# +# Get organization info +# (GET /v3/organization) +# - Returns all organizations associated with the current user. +# +def get_org(): + url = "https://{}/api/v3/organization".format(apm_server) + return(requests.get(url, auth=(username, password))) + + +# +# Get appliance (monitoring point) info +# (GET /v3/appliance (with orgId parameter)) +# - Returns appliance info for the specified organization. +# If org_id is "None" then info for all appliances is returned. +# - org_id - organization id +# +def get_appliance(org_id=None): + url = "https://{}/api/v3/appliance".format(apm_server) + if org_id is not None: + url += "?orgId={}".format(org_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get appliance (monitoring point) info for the specific appliance +# (GET /v3/appliance/{id}) +# - Returns appliance info for the specified appliance. +# - appliance_id - appliance id +# +def get_appliance_id(appliance_id): + url = "https://{}/api/v3/appliance/{}".format(apm_server, appliance_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get web app group info (GET /v3/webApplication) +# - Returns web app group info for the specified organization. +# If org_id is "None" then info for all web app groups is returned. +# - org_id - organization id +# +def get_web_app_group(org_id=None): + url = "https://{}/api/v3/webApplication".format(apm_server) + if org_id is not None: + url += "?orgId={}".format(org_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get web app group info for a specified web app group +# (GET /v3/webApplication/{web_app_grp_id}) +# - Returns web app group info for the specified web app group +# - web_app_grp_id - web app group id +# +def get_web_app_group_id(web_app_grp_id): + url = "https://{}/api/v3/webApplication/{}".format( + apm_server, web_app_grp_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get web path info for paths in a web app group +# (GET /v3/webApplication/{web_app_grp_id}/monitor) +# - Returns web path info for the paths in the specified web app group. +# - web_app_grp_id - web app group id +# +def get_web_path(web_app_grp_id): + url = "https://{}/api/v3/webApplication/{}/monitor".format( + apm_server, web_app_grp_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get web path stats (GET /v3/webPath/data) +# - Returns web path stats for the specified organization. +# If org_id is "None" then info for all organizations is returned. +# - org_id - organization id +# - start_time - the start time of the time range in UNIX/epoch time +# - end_time - the end time of the time range in UNIX/epoch time +# If no start or end time, stats for the last hour are returned +# +def get_web_path_stats(org_id=None, start_time=None, end_time=None): + url = "https://{}/api/v3/webPath/data?".format(apm_server) + if org_id is not None: + url += "orgId={}&".format(org_id) + if start_time is not None: + url += "from={}&".format(start_time) + if end_time is not None: + url += "to={}".format(end_time) + return(requests.get(url, auth=(username, password))) + + +# +# Get web path stats for a specific web path over a given time range. +# (GET /v3/webApplication/{web_app_group_id}/monitor/{web_path_id}/data) +# If no time range is specified, data for the last hour is returned. +# - Returns web path stats for the specified web app group / web path +# - web_app_group_id - web app group id +# - web_path_id - web path id +# - start_time - the start time of the time range in UNIX/epoch time +# - end_time - the end time of the time range in UNIX/epoch time +# If no start or end time, stats for the last hour are returned +# - metric - the type of data to return ("networktiming", "servertiming", +# "browsertiming"). +# If no metric is specified, all types are returned. +# +def get_web_path_stats_id(web_app_group_id, web_path_id, start_time=None, + end_time=None, metric=None): + url = "https://{}/api/v3/webApplication/{}/monitor/{}/data?".format( + apm_server, web_app_group_id, web_path_id) + if start_time is not None: + url += "from={}&".format(start_time) + if end_time is not None: + url += "to={}&".format(end_time) + if metric is not None: + url += "metric={}".format(metric) + return(requests.get(url, auth=(username, password))) + + +# +# Get network path info (GET /v3/path) +# - Returns network path info for the specified organization. +# If org_id is "None" then info for all organizations is returned. +# - org_id - organization id +# +def get_network_path(org_id=None): + url = "https://{}/api/v3/path".format(apm_server) + if org_id is not None: + url += "?orgId={}".format(org_id) + return(requests.get(url, auth=(username, password))) + + +# +# Determine the network path ID given an org ID, source MP name, and target +# - Returns the network path ID or 0 if it can't be found +# - org_id - organization id +# - source_mp_name - source MP name to match +# - target - target to match +# +def get_network_path_id(org_id, source_mp_name, target): + r1 = get_network_path(org_id) + if r1.status_code == requests.codes.ok: + for network_path in r1.json(): + # pp_json(network_path) + if (network_path['sourceAppliance'] == source_mp_name and + network_path['target'] == target): + return(network_path['id']) + return(0) + else: + return(0) + + +# +# Get network path status (GET /v3/path/status) +# - Returns network path status for the specified organization. +# If org_id is "None" then info for all organizations is returned. +# - org_id - organization id +# +def get_network_path_status(org_id=None): + url = "https://{}/api/v3/path/status".format(apm_server) + if org_id is not None: + url += "?orgId={}".format(org_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get network path status for a specified path (GET /v3/path/{id}/status) +# - Returns network path status (string) for the specified path. +# path_id - network path id +# +def get_network_path_status_id(path_id): + url = "https://{}/api/v3/path/{}/status".format(apm_server, path_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get network path stats (GET /v3/path/data) +# - Returns network path stats for the specified organization. +# If org_id is "None" then info for all organizations is returned. +# If path_id is "None" then info for all paths is returned. +# - org_id - organization id +# - path_id - path id +# - start_time - the start time of the time range in UNIX/epoch time +# - end_time - the end time of the time range in UNIX/epoch time +# If no start or end time, stats for the last hour are returned +# - metric - the type of data to return ("totalcapacity", +# "utilizedcapacity", "availablecapacity", "latency", +# "datajitter", "dataloss", "voicejitter", "voiceloss", +# "mos", "rtt", "twamprtt", "twampjitter", "twamploss"). +# If no metric is specified, all types are returned. +# +def get_network_path_stats_id(org_id=None, path_id=None, start_time=None, + end_time=None, metric=None): + url = "https://{}/api/v3/path/data?".format(apm_server) + if org_id is not None: + url += "orgId={}&".format(org_id) + if path_id is not None: + url += "pathIds={}&".format(path_id) + if start_time is not None: + url += "from={}&".format(start_time) + if end_time is not None: + url += "to={}&".format(end_time) + if metric is not None: + url += "metric={}".format(metric) + return(requests.get(url, auth=(username, password))) + + +# +# Create a network path +# (POST /v3/path (using an org ID, source MP name, +# and target in request body)) +# - Creates the network path using an org ID, source MP name, and target +# - org_id - organization id +# - source_mp_name - source MP +# - target - target +# +def create_network_path(org_id, source_mp_name, target): + url = "https://{}/api/v3/path".format(apm_server) + headers = { + "Content-Type": "application/json" + } + body = { + "sourceAppliance": source_mp_name, + "target": target, + "orgId": org_id + } + return(requests.post(url, headers=headers, auth=(username, password), + json=body)) + + +# +# Delete a network path (DELETE /v3/path/{id} (with network path ID parameter)) +# - Deletes the network path identified using an org ID, source MP name, +# and target +# - org_id - organization id +# - source_mp_name - source MP name to match +# - target - target to match +# +def delete_network_path(org_id, source_mp_name, target): + network_path_id = get_network_path_id(org_id, source_mp_name, target) + url = "https://{}/api/v3/path/{}".format(apm_server, network_path_id) + return(requests.delete(url, auth=(username, password))) + + +# +# Get saved list info (GET /v3/savedList (with orgId parameter)) +# - Returns saved list info for the specified organization. +# org_id - organization id +# +def get_saved_lists(org_id): + url = "https://{}/api/v3/savedList?orgId={}".format(apm_server, org_id) + return(requests.get(url, auth=(username, password))) + + +# +# Get group info (GET /v3/group (with orgId parameter)) +# - Returns group info for the specified organization. +# If org_id is "None" then info for all groups is returned. +# - org_id - organization id +# +def get_groups(org_id=None): + url = "https://{}/api/v3/group".format(apm_server) + if org_id is not None: + url += "?orgId={}".format(org_id) + return(requests.get(url, auth=(username, password))) diff --git a/app-appliances.py b/app-appliances.py new file mode 100644 index 0000000..d86196e --- /dev/null +++ b/app-appliances.py @@ -0,0 +1,21 @@ +# +# Print monitoring point info (grouped by organization) +# +from api_fns import * + +r1 = get_org() +if r1.status_code == requests.codes.ok: + for organization in r1.json(): + print('Org ({}) name --> {}'.format(organization['id'], + organization['displayName'])) + + r2 = get_appliance(organization['id']) + if r2.status_code == requests.codes.ok: + for appliance in r2.json(): + print(' MP: {}, {}, {}'.format(appliance['id'], + appliance['resolvedIp'], appliance['name'])) + # pp_json(appliance) + else: + print_err(r2) +else: + print_err(r1) diff --git a/appliances.py b/appliances.py new file mode 100644 index 0000000..abcd366 --- /dev/null +++ b/appliances.py @@ -0,0 +1,22 @@ +# +# Print monitoring point info (grouped by organization) +# +from api_fns import * + +r1 = get_org() +if r1.status_code == requests.codes.ok: + for organization in r1.json(): + print('Org ({}) name --> {}'.format(organization['id'], + organization['displayName'])) + + r2 = get_appliance(organization['id']) + if r2.status_code == requests.codes.ok: + for appliance in r2.json(): + appliancelookup[appliance['guid']=appliance['name'] + print(' MP: {}, {}, {}, {}'.format(appliance['id'], + appliance['resolvedIp'], appliance['name'], appliance['guid'])) + # pp_json(appliance) + else: + print_err(r2) +else: + print_err(r1) \ No newline at end of file