parent
0dfc4dcac4
commit
e77a5ec76f
@ -1,65 +0,0 @@ |
||||
#!/usr/bin/python |
||||
#encoding=utf-8 |
||||
# author: tangwy |
||||
|
||||
import json |
||||
import os,re |
||||
import codecs |
||||
import csv |
||||
import ConfigParser |
||||
from ipaddr import IPRange |
||||
from elasticsearch import Elasticsearch |
||||
|
||||
conf_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'conf') |
||||
ini_path = os.path.join(conf_path, 'conf.ini') |
||||
config = ConfigParser.ConfigParser() |
||||
config.read(ini_path) |
||||
|
||||
ES_HOST = config.get('COMMON', 'es_host') |
||||
ES_PER_COUNT = config.get('COMMON', 'es_per_count') |
||||
ES_INDEX_NAME = config.get('COMMON', 'es_index_name') |
||||
|
||||
CSV_FILE_PATH = config.get('COMMON', 'csv_file_path') |
||||
|
||||
# scroll查询数据 |
||||
def get_es_data(start_time,end_time): |
||||
es = Elasticsearch(ES_HOST) |
||||
msg = es.search(index=ES_INDEX_NAME,scroll="3m",size=ES_PER_COUNT,_source_includes= ["cookies","url","sip","dip"], query={ |
||||
"bool": { |
||||
"filter": { |
||||
"range": { |
||||
"timestamp": { |
||||
"gte": start_time, |
||||
"lte": end_time |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
result = msg['hits']['hits'] |
||||
total = msg['hits']['total'] |
||||
scroll_id = msg['_scroll_id'] |
||||
|
||||
for i in range(0,int(total["value"]/ES_PER_COUNT)+1): |
||||
query_scroll = es.scroll(scroll_id=scroll_id, scroll='3m')["hits"]["hits"] |
||||
result += query_scroll |
||||
return result |
||||
|
||||
# 读取csv文件 获取ip归属地 |
||||
def get_ip_area_relation(csv_file_path): |
||||
iprange_map = {} |
||||
with codecs.open(csv_file_path, mode='r',encoding='utf-8') as file: |
||||
csv_reader = csv.reader(file) |
||||
for row in csv_reader: |
||||
headers = next(csv_reader) |
||||
ip_start = headers[0] |
||||
ip_end = headers[1] |
||||
ip_range = IPRange(ip_start, ip_end) |
||||
ip_area = headers[5] |
||||
print (ip_area) |
||||
for ip in ip_range: |
||||
iprange_map[ip] = ip_area |
||||
return iprange_map |
||||
|
||||
get_ip_area_relation("/tmp/data/ip_area_relation.csv") |
Binary file not shown.
@ -0,0 +1,38 @@ |
||||
{ |
||||
"white_list": { |
||||
"ip": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"account": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"interface": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"menu": [ |
||||
400000, |
||||
400001 |
||||
] |
||||
}, |
||||
"grey_list": { |
||||
"ip": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"account": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"interface": [ |
||||
400000, |
||||
400001 |
||||
], |
||||
"menu": [ |
||||
400000, |
||||
400001 |
||||
] |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
# coding=utf-8 |
||||
""" |
||||
@Author: fu-zhe |
||||
@FileName: user_cron.py |
||||
@DateTime: 2024/5/23 14:19 |
||||
@Description: 用户相关的定时任务 全量获取,对已有数据进行先删除后写入 周期一天 |
||||
""" |
||||
from __future__ import unicode_literals |
||||
|
||||
import collections |
||||
import json |
||||
import time,datetime |
||||
from datetime import datetime, timedelta |
||||
import calendar |
||||
from uebaMetricsAnalysis.utils.ext_logging import logger |
||||
from uebaMetricsAnalysis.utils.base_dataclean import entry |
||||
|
||||
class UserCron: |
||||
def get_index_name(): |
||||
baseIndex ="a_ueba_analyse_" |
||||
# 获取当前日期 |
||||
now = datetime.now() |
||||
|
||||
# 转到上一个月 |
||||
last_month = now - timedelta(days=calendar.monthrange(now.year, now.month)[1]) |
||||
last_month_year = last_month.year |
||||
last_month_month = last_month.month |
||||
|
||||
if last_month_month < 10: |
||||
last_month_month = '0' + str(last_month_month) |
||||
return baseIndex + str(last_month_year) + '_' + str(last_month_month) |
||||
|
||||
def processing(self): |
||||
try: |
||||
#写入的索引 按月创建,注意跨天的场景 |
||||
write_index= self.get_index_name() |
||||
read_index ="bsa_traffic*" |
||||
|
||||
#任务执行时间是每天 凌晨12点 |
||||
#查询的范围 开始时间前一天的0点0分0秒,结束时间是 前一天的23.59.59秒 |
||||
start = datetime.datetime.now() |
||||
end = datetime.datetime.now() |
||||
|
||||
entry(write_index,read_index,start,end) |
||||
logger.info("start processing") |
||||
except Exception ,e: |
||||
logger.error("定时任务执行失败:".format(str(e), traceback.format_exc())) |
||||
raise |
@ -0,0 +1,72 @@ |
||||
# coding=utf-8 |
||||
""" |
||||
@Author: fu-zhe |
||||
@FileName: user_cron.py |
||||
@DateTime: 2024/5/23 14:19 |
||||
@Description: 用户相关的定时任务 全量获取,对已有数据进行先删除后写入 周期一天 |
||||
""" |
||||
from __future__ import unicode_literals |
||||
|
||||
import collections |
||||
import random,string |
||||
import time,datetime |
||||
from datetime import datetime, timedelta |
||||
import calendar |
||||
from uebaMetricsAnalysis.utils.ext_logging import logger |
||||
from commandCyberRange.utils.db2json import DBUtils, DBType |
||||
from uebaMetricsAnalysis.utils.base_dataclean import entry |
||||
|
||||
JOB_STATUS ={ |
||||
"RUNNING":1, |
||||
"FINISH":2, |
||||
"ERROR":3 |
||||
} |
||||
|
||||
|
||||
class UserCron: |
||||
def generate_job_id(): |
||||
timestamp = int(time.time() * 1000) |
||||
random_letters = ''.join(random.choice(string.ascii_letters) for _ in range(7)) |
||||
return str(timestamp) + random_letters |
||||
|
||||
#获取 job的执行时间 开始时间-结束时间 |
||||
def get_job_period(self): |
||||
sql = "select job_id, end_time from ueba_clean_jobs order by end_time desc limit 1" |
||||
fields=["job_id", "end_time"] |
||||
data = DBUtils.transition(fields, sql, DBType.LIST) |
||||
start_time = '' |
||||
end_time = '' |
||||
if len(data)==0: |
||||
start_time = datetime.datetime.now() - timedelta(minutes=5) |
||||
end_time = datetime.datetime.now() |
||||
if len(data)>0: |
||||
start_time = data[0].get('end_time') |
||||
end_time = data[0].get('end_time') + timedelta(minutes=5) |
||||
if end_time > datetime.datetime.now(): |
||||
return None,None |
||||
return start_time,end_time |
||||
|
||||
#每5分钟执行一次 |
||||
def processing(self): |
||||
try: |
||||
logger.info("job:开始执行") |
||||
start,end=self.get_job_period() |
||||
job_id =self.generate_job_id() |
||||
DBUtils.insert_job_record(job_id,start,end,JOB_STATUS.get("RUNNING")) |
||||
logger.info("job:运行参数:{}".format(start,end)) |
||||
if start is None or end is None: |
||||
logger.info("job:结束时间大于服务器时间不执行") |
||||
return |
||||
|
||||
logger.info("job:"+"准备获取es数据") |
||||
entry(start,end) |
||||
logger.info("job:"+"执行完成") |
||||
DBUtils.write_job_status(job_id,JOB_STATUS.get("FINISH"),"") |
||||
except Exception ,e: |
||||
err_info="定时任务执行失败:".format(str(e), traceback.format_exc()) |
||||
logger.error(err_info) |
||||
DBUtils.write_job_status(job_id,JOB_STATUS.get("ERROR"),err_info) |
||||
raise |
||||
|
||||
if __name__ == '__main__': |
||||
UserCron().processing() |
@ -0,0 +1,13 @@ |
||||
[ |
||||
{ |
||||
"task_name": "ueba_corn", |
||||
"task_type": 1, |
||||
"exec_cmd": "python /home/master/ISOP/apps/uebaMetricsAnalysis/corn/ueba_corn.py", |
||||
"task_owner": "uebaMetricsAnalysis", |
||||
"run_mode": 1, |
||||
"duration_args": "*/2 * * * * *", |
||||
"retry_nums": 5, |
||||
"is_enable": 1, |
||||
"task_description": "每天执行一次 清洗数据到es-ueba索引" |
||||
} |
||||
] |
@ -0,0 +1,18 @@ |
||||
#encoding=utf-8 |
||||
import json |
||||
|
||||
from isoc.utils.esUtil import EsUtil |
||||
|
||||
|
||||
def createIndex(): |
||||
map={ |
||||
"field1": "text", |
||||
"field2": "text" |
||||
} |
||||
es_util_instance = EsUtil() |
||||
res = es_util_instance.create_index_simple("bsa_traffic*",3,scroll_search) |
||||
return res |
||||
|
||||
res = createIndex() |
||||
|
||||
print(res) |
@ -0,0 +1,292 @@ |
||||
#encoding=utf-8 |
||||
import json |
||||
import time,datetime |
||||
import traceback |
||||
from datetime import datetime, timedelta |
||||
import calendar |
||||
from esUtil import EsUtil |
||||
import pytz |
||||
|
||||
size = 1000# 可以根据实际情况调整 |
||||
##01 创建索引 |
||||
def createIndex(index): |
||||
map={ |
||||
"data_type":"keyword", |
||||
"req_account":"keyword", |
||||
"req_frequency":"integer", |
||||
"req_jobnum":"keyword", |
||||
"interface_addr":"keyword", |
||||
"req_ip":"ip", |
||||
"menu_name":"keyword", |
||||
"date_time":"date" |
||||
} |
||||
es_util_instance = EsUtil() |
||||
reqs = es_util_instance.is_index_exist(index) |
||||
if reqs =="false": |
||||
try: |
||||
res = es_util_instance.create_index_simple(index,map) |
||||
except Exception,e: |
||||
print e.message |
||||
## IP维度 |
||||
def get_ip_group_data(index,startTime,endTime): |
||||
try: |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"sip": { "terms": {"field": "sip"} }}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
try: |
||||
response = es_util_instance.search(index,query_body) |
||||
except Exception,e: |
||||
print "err" |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
data = { |
||||
"data_type": "ip", |
||||
"req_account": "", |
||||
"req_frequency": bucket['doc_count'], |
||||
"req_jobnum": bucket['key']['trojan_type'] , |
||||
"interface_addr": "", |
||||
"req_ip":bucket['key']['sip'] , |
||||
"menu_name": "", |
||||
"date_time": int(time.time() * 1000) # 当前时间,使用isoformat格式化 |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
except Exception,e: |
||||
print "x_err:"+e.message |
||||
return datas |
||||
|
||||
|
||||
## 账号维度 |
||||
def get_account_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"account": { "terms": {"field": "account"} }}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": "account", |
||||
"req_account": bucket['key']['account'], |
||||
"req_frequency": bucket['doc_count'], |
||||
"req_jobnum": bucket['key']['trojan_type'] , |
||||
"interface_addr": "", |
||||
"req_ip":"0.0.0.0" , |
||||
"menu_name": "", |
||||
"date_time": int(time.time() * 1000) # 当前时间,使用isoformat格式化 |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
## 接口维度 |
||||
def get_interface_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"interface": { "terms": {"field": "interface"} }}, |
||||
{"sip": { "terms": { "field": "sip"}}}, |
||||
{"account": { "terms": { "field": "account"}}}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}}, |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": "interface", |
||||
"req_account": bucket['key']['account'], |
||||
"req_frequency": bucket['doc_count'], |
||||
"req_jobnum": bucket['key']['trojan_type'] , |
||||
"interface_addr": bucket['key']['interface'] , |
||||
"req_ip":bucket['key']['sip'], |
||||
"menu_name": "", |
||||
"date_time": int(time.time() * 1000) # 当前时间,使用isoformat格式化 |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
|
||||
|
||||
## 菜单维度 |
||||
def get_menu_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"worm_family": { "terms": {"field": "worm_family"} }}, |
||||
{"sip": { "terms": { "field": "sip"}}}, |
||||
{"account": { "terms": { "field": "account"}}}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}}, |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": "menu", |
||||
"req_account": bucket['key']['account'], |
||||
"req_frequency": bucket['doc_count'], |
||||
"req_jobnum": bucket['key']['trojan_type'] , |
||||
"interface_addr": "" , |
||||
"req_ip":bucket['key']['sip'], |
||||
"menu_name": bucket['key']['worm_family'], |
||||
"date_time": int(time.time() * 1000) # 当前时间,使用isoformat格式化 |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
##03 数据写入 |
||||
def data_insert(index,data): |
||||
es_util_instance = EsUtil() |
||||
response = es_util_instance.bulk_insert(index,data) |
||||
return response |
||||
|
||||
def clean_data(write_index,read_index,start,end): |
||||
data_ip = get_ip_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_ip)) |
||||
data_account = get_account_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_account)) |
||||
data_interface = get_interface_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_interface)) |
||||
data_menu = get_menu_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_menu)) |
||||
res_data = data_ip+data_account+data_interface+data_menu |
||||
response = data_insert(write_index,res_data) |
||||
print json.dumps(response) |
||||
|
||||
#入口 |
||||
def entry(write_index,read_index,start,end): |
||||
createIndex(write_index) |
||||
clean_data(write_index,read_index,start,end) |
||||
|
||||
|
||||
#前一天的0点0分0秒 |
||||
def get_start_end_time(hour,minute,second): |
||||
# 获取当前日期时间 |
||||
now = datetime.now() |
||||
|
||||
# 计算昨天的日期时间 |
||||
yesterday = now - timedelta(days=1) |
||||
|
||||
# 将时间部分设为 00:00:00 |
||||
yesterday_midnight = yesterday.replace(hour=hour, minute=minute, second=second, microsecond=0) |
||||
|
||||
# 使用 pytz 来获取 UTC 时区对象 |
||||
utc = pytz.utc |
||||
# 将时间对象本地化为 UTC 时区 |
||||
yesterday_midnight_utc = utc.localize(yesterday_midnight) |
||||
|
||||
# 格式化为带时区的字符串(ISO 8601格式) |
||||
formatted_date = yesterday_midnight_utc.strftime("%Y-%m-%dT%H:%M:%SZ") |
||||
return formatted_date |
||||
|
||||
def index(): |
||||
try: |
||||
#写入的索引 按月创建,注意跨天的场景 |
||||
write_index= "b_ueba_2024_07" |
||||
read_index ="bsa_traffic*" |
||||
#任务执行时间是每天 凌晨12点 |
||||
#查询的范围 开始时间前一天的0点0分0秒,结束时间是 前一天的23.59.59秒 |
||||
|
||||
start = "2024-06-02T00:00:00Z"#get_start_end_time(0,0,0) |
||||
end = get_start_end_time(23,59,59) |
||||
print start +":"+ end |
||||
entry(write_index,read_index,start,end) |
||||
except Exception ,e: |
||||
print "定时任务执行失败:"+traceback.format_exc() |
||||
# logger.error("定时任务执行失败:".format(str(e), traceback.format_exc())) |
||||
|
||||
index() |
@ -0,0 +1,227 @@ |
||||
#encoding=utf-8 |
||||
import json |
||||
import time,datetime |
||||
import traceback |
||||
from datetime import datetime, timedelta |
||||
import calendar |
||||
from esUtil import EsUtil |
||||
import pytz |
||||
|
||||
size = 1000# 可以根据实际情况调整 |
||||
|
||||
DATA_TYPE = { |
||||
"IP": 1, |
||||
"ACCOUNT": 2, |
||||
"INTERFACE": 3, |
||||
"MENU": 4, |
||||
} |
||||
|
||||
## IP维度 |
||||
def get_ip_group_data(index,startTime,endTime): |
||||
try: |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"sip": { "terms": {"field": "sip"} }}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
try: |
||||
response = es_util_instance.search(index,query_body) |
||||
except Exception,e: |
||||
print "err" |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
data = { |
||||
"data_type": DATA_TYPE.get("IP"), |
||||
"count": bucket['doc_count'], |
||||
"jobnum": bucket['key']['trojan_type'] , |
||||
"ip":bucket['key']['sip'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
except Exception,e: |
||||
print "x_err:"+e.message |
||||
return datas |
||||
|
||||
## 账号维度 |
||||
def get_account_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"account": { "terms": {"field": "account"} }}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": DATA_TYPE.get("ACCOUNT"), |
||||
"account": bucket['key']['account'], |
||||
"count": bucket['doc_count'], |
||||
"jobnum": bucket['key']['trojan_type'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
## 接口维度 |
||||
def get_interface_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"interface": { "terms": {"field": "interface"} }}, |
||||
{"sip": { "terms": { "field": "sip"}}}, |
||||
{"account": { "terms": { "field": "account"}}}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}}, |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": DATA_TYPE.get("INTERFACE"), |
||||
"account": bucket['key']['account'], |
||||
"count": bucket['doc_count'], |
||||
"jobnum": bucket['key']['trojan_type'] , |
||||
"interface": bucket['key']['interface'] , |
||||
"ip":bucket['key']['sip'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
|
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
|
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
## 菜单维度 |
||||
def get_menu_group_data(index,startTime,endTime): |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"range": {"timestamp": {"gte": startTime,"lte": endTime}} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size": size, |
||||
"sources": [ |
||||
{"worm_family": { "terms": {"field": "worm_family"} }}, |
||||
{"sip": { "terms": { "field": "sip"}}}, |
||||
{"account": { "terms": { "field": "account"}}}, |
||||
{"trojan_type": { "terms": { "field": "trojan_type"}}}, |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas=[] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
for bucket in response["aggregations"]["composite_buckets"]["buckets"]: |
||||
#print(bucket['key']['sip'] + ":" + str(bucket['doc_count'])) |
||||
data = { |
||||
"data_type": DATA_TYPE.get("MENU"), |
||||
"account": bucket['key']['account'], |
||||
"count": bucket['doc_count'], |
||||
"jobnum": bucket['key']['trojan_type'] , |
||||
"ip":bucket['key']['sip'], |
||||
"menu_name": bucket['key']['worm_family'], |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
|
||||
return datas |
||||
|
||||
def clean_data(read_index,start,end): |
||||
data_ip = get_ip_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_ip)) |
||||
data_account = get_account_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_account)) |
||||
data_interface = get_interface_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_interface)) |
||||
data_menu = get_menu_group_data(read_index,start,end) |
||||
print "data_ip:"+str(len(data_menu)) |
||||
res_data = data_ip+data_account+data_interface+data_menu |
||||
|
||||
#todo 读取上一次5分钟的文件,与这5分钟的文件合并 |
||||
#合并完成后 写文件 |
||||
|
||||
#入口 |
||||
def entry(start,end): |
||||
base_index ="bsa_traffic*" |
||||
es_util_instance = EsUtil() |
||||
res=es_util_instance.get_available_index_name(start,end,base_index) |
||||
if len(res)==0: |
||||
return |
||||
index =",".join(res) |
||||
clean_data(index,start,end) |
@ -0,0 +1,15 @@ |
||||
# coding=utf-8 |
||||
""" |
||||
@Author: tangwy |
||||
@FileName: config |
||||
@DateTime: 2024/6/14 14:27 |
||||
@Description: |
||||
""" |
||||
import json,os |
||||
|
||||
def read_json_config(file_path): |
||||
if not os.path.exists(file_path): |
||||
raise IOError("The configuration file does not exist: {}".format(file_path)) |
||||
with open(file_path, 'r') as f: |
||||
config = json.load(f) |
||||
return config |
@ -0,0 +1,281 @@ |
||||
#!/usr/bin/python |
||||
#encoding=utf-8 |
||||
# author: tangwy |
||||
|
||||
import json |
||||
import os,re |
||||
import codecs |
||||
import traceback |
||||
from isoc.utils.esUtil import EsUtil |
||||
from dashboard_data_conversion import ip_summary_data_format, account_summary_data_format, \ |
||||
interface_summary_data_format, menu_summary_data_format |
||||
from ext_logging import logger |
||||
## IP维度 |
||||
def es_get_ip_group_data(index,startTime,endTime): |
||||
page_size = 9000 #可以根据实际情况调整 |
||||
query_body={ |
||||
"query": { |
||||
"bool": { |
||||
"filter": [ |
||||
{ "term": { "data_type": "ip" } }, |
||||
{"range":{ |
||||
"date_time": { |
||||
"gte": startTime, |
||||
"lte": endTime |
||||
} |
||||
}} |
||||
] |
||||
} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size" : page_size, |
||||
"sources": [ |
||||
{ "req_ip": { "terms": { "field": "req_ip" } } }, |
||||
{ "req_jobnum": { "terms": { "field": "req_jobnum" } } } |
||||
] |
||||
}, |
||||
"aggregations": { |
||||
"total_count": { |
||||
"sum": { |
||||
"field": "req_frequency" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas = [] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
buckets = response.get("aggregations", {}).get("composite_buckets", {}).get("buckets", []) |
||||
for bucket in buckets: |
||||
data= { |
||||
"ip":bucket['key']['req_ip'], |
||||
"jobnum":bucket['key']['req_jobnum'], |
||||
"count":bucket['total_count']['value'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
return datas |
||||
|
||||
|
||||
## 账号维度 |
||||
def es_get_account_group_data(index,startTime,endTime): |
||||
page_size = 9000 #可以根据实际情况调整 |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"bool": { |
||||
"filter": [ |
||||
{ "term": { "data_type": "account" } }, |
||||
{"range":{ |
||||
"date_time": { |
||||
"gte": startTime, |
||||
"lte": endTime |
||||
} |
||||
}} |
||||
] |
||||
} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size" : page_size, |
||||
"sources": [ |
||||
{ "req_account": { "terms": { "field": "req_account" } } }, |
||||
{ "req_jobnum": { "terms": { "field": "req_jobnum" } } } |
||||
] |
||||
}, |
||||
"aggregations": { |
||||
"total_count": { |
||||
"sum": { |
||||
"field": "req_frequency" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas = [] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
buckets = response.get("aggregations", {}).get("composite_buckets", {}).get("buckets", []) |
||||
for bucket in buckets: |
||||
data= { |
||||
"account":bucket['key']['req_account'], |
||||
"jobnum":bucket['key']['req_jobnum'], |
||||
"count":bucket['total_count']['value'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
return datas |
||||
|
||||
|
||||
## 菜单维度 |
||||
def es_get_menu_group_data(index,startTime,endTime): |
||||
page_size = 9000 #可以根据实际情况调整 |
||||
query_body={ |
||||
"size": 0, |
||||
"query": { |
||||
"bool": { |
||||
"filter": [ |
||||
{ "term": { "data_type": "menu" } }, |
||||
{"range":{ |
||||
"date_time": { |
||||
"gte": startTime, |
||||
"lte": endTime |
||||
} |
||||
}} |
||||
] |
||||
} |
||||
}, |
||||
"aggs": { |
||||
"composite_buckets": { |
||||
"composite": { |
||||
"size" : page_size, |
||||
"sources": [ |
||||
{ "menu_name": { "terms": { "field": "menu_name" } } }, |
||||
{ "req_account": { "terms": { "field": "req_account" } } }, |
||||
{ "req_ip": { "terms": { "field": "req_ip" } } }, |
||||
{ "req_jobnum": { "terms": { "field": "req_jobnum" } } } |
||||
] |
||||
}, |
||||
"aggregations": { |
||||
"total_count": { |
||||
"sum": { |
||||
"field": "req_frequency" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas = [] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
buckets = response.get("aggregations", {}).get("composite_buckets", {}).get("buckets", []) |
||||
for bucket in buckets: |
||||
data= { |
||||
"menu":bucket['key']['menu_name'], |
||||
"ip":bucket['key']['req_ip'], |
||||
"account":bucket['key']['req_account'], |
||||
"jobnum":bucket['key']['req_jobnum'], |
||||
"count":bucket['total_count']['value'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
return datas |
||||
|
||||
|
||||
## 接口维度 |
||||
def es_get_interface_group_data(index,startTime,endTime): |
||||
page_size = 9999 #可以根据实际情况调整 |
||||
query_body={ |
||||
"query": { |
||||
"bool": { |
||||
"filter": [ |
||||
{ "term": { "data_type": "interface" } }, |
||||
{"range":{ |
||||
"date_time": { |
||||
"gte": startTime, |
||||
"lte": endTime |
||||
} |
||||
}} |
||||
] |
||||
} |
||||
}, |
||||
"aggs": { |
||||
"group_by_menu": { |
||||
"composite": { |
||||
"size" : page_size, |
||||
"sources": [ |
||||
{ "interface_addr": { "terms": { "field": "interface_addr" } } }, |
||||
{ "req_account": { "terms": { "field": "req_account" } } }, |
||||
{ "req_ip": { "terms": { "field": "req_ip" } } }, |
||||
{ "req_jobnum": { "terms": { "field": "req_jobnum" } } } |
||||
] |
||||
}, |
||||
"aggregations": { |
||||
"total_count": { |
||||
"sum": { |
||||
"field": "req_frequency" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
after_key = None |
||||
es_util_instance = EsUtil() |
||||
datas = [] |
||||
while True: |
||||
if after_key: |
||||
query_body["aggs"]["composite_buckets"]["composite"]["after"] = after_key |
||||
response = es_util_instance.search(index,query_body) |
||||
buckets = response.get("aggregations", {}).get("composite_buckets", {}).get("buckets", []) |
||||
for bucket in buckets: |
||||
data= { |
||||
"interface":bucket['key']['interface_addr'], |
||||
"ip":bucket['key']['req_ip'], |
||||
"account":bucket['key']['req_account'], |
||||
"jobnum":bucket['key']['req_jobnum'], |
||||
"count":bucket['total_count']['value'] |
||||
} |
||||
datas.append(data) |
||||
after_key = bucket["key"] |
||||
if not response["aggregations"]["composite_buckets"].get("after_key"): |
||||
break |
||||
after_key = response["aggregations"]["composite_buckets"]["after_key"] |
||||
return datas |
||||
|
||||
def entry(data_type,start,end): |
||||
base_index = 'c_ueba_001' |
||||
# es_util_instance = EsUtil() |
||||
# res=es_util_instance.get_available_index_name(start,end,base_index) |
||||
# if len(res)==0: |
||||
# return |
||||
# index =",".join(res) |
||||
|
||||
index=base_index |
||||
|
||||
try: |
||||
data = {} |
||||
if data_type == "1": |
||||
ip_summary_data = es_get_ip_group_data(index, start, end) |
||||
data = ip_summary_data_format(ip_summary_data) |
||||
if data_type == "2": |
||||
account_summary_data = es_get_account_group_data(index, start, end) |
||||
data = account_summary_data_format(account_summary_data) |
||||
if data_type == "3": |
||||
interface_summary_data = es_get_interface_group_data(index, start, end) |
||||
data = interface_summary_data_format(interface_summary_data) |
||||
if data_type == "4": |
||||
menu_summary_data = es_get_menu_group_data(index, start, end) |
||||
data = menu_summary_data_format(menu_summary_data) |
||||
return data |
||||
except Exception, e: |
||||
logger.error(traceback.format_exc()) |
||||
raise e |
@ -0,0 +1,270 @@ |
||||
# coding=utf-8 |
||||
from __future__ import division |
||||
import json |
||||
from collections import defaultdict |
||||
|
||||
jobnum_region_dict = { |
||||
"10": "省公司", |
||||
"110": "武汉分公司", |
||||
"170": "襄阳分公司", |
||||
"130": "鄂州分公司", |
||||
"260": "孝感分公司", |
||||
"250": "黄冈分公司", |
||||
"120": "黄石分公司", |
||||
"190": "咸宁分公司", |
||||
"200": "荆州分公司", |
||||
"140": "宜昌分公司", |
||||
"150": "恩施分公司", |
||||
"160": "十堰分公司", |
||||
"240": "随州分公司", |
||||
"230": "荆门分公司", |
||||
"1801": "江汉分公司", |
||||
"1802": "潜江分公司", |
||||
"1803": "天门分公司" |
||||
} |
||||
|
||||
|
||||
def keep_digits_filter(code): |
||||
""" |
||||
工号可能有字面,去掉字面,以数字起算 |
||||
""" |
||||
return ''.join(filter(str.isdigit, str(code))) |
||||
|
||||
|
||||
def find_region_by_code(code, region_dict): |
||||
""" |
||||
查询工号对应公司 |
||||
未查询到 返回错误工号 |
||||
""" |
||||
code_str = keep_digits_filter(code) |
||||
# 使用生成器表达式和next函数尝试找到匹配的前缀 |
||||
company = next( |
||||
(region_dict.get(code_str[:i]) for i in range(2, min(len(code_str), 5)) if code_str[:i] in region_dict), |
||||
"错误工号") |
||||
return company |
||||
|
||||
|
||||
def ip_summary_data_format(ip_summary_data): |
||||
""" |
||||
ip维度数据转换方法 |
||||
""" |
||||
result = {"summary": {"ip": []}, "detail": {"ip": {}}} |
||||
grouped_data = defaultdict(lambda: {"reqs": 0, "ips": set()}) |
||||
ip_detail_dict = defaultdict(lambda: defaultdict(lambda: {"req_frequency": 0})) |
||||
# 全部账号元组 |
||||
ips_total = set() |
||||
for ip_data in ip_summary_data: |
||||
company = find_region_by_code(ip_data["jobnum"], jobnum_region_dict) |
||||
count = ip_data["count"] |
||||
ip = ip_data["ip"] |
||||
jobnum = ip_data["jobnum"] |
||||
ip_detail_dict_key = "{}{}".format(ip, jobnum) |
||||
|
||||
# 更新统计数据 |
||||
grouped_data[company]["reqs"] += count |
||||
grouped_data[company]["ips"].add(ip) |
||||
ips_total.add(ip) |
||||
# 构建下钻详情 |
||||
ip_detail_dict[company][ip_detail_dict_key]["req_ip"] = ip |
||||
ip_detail_dict[company][ip_detail_dict_key]["req_jobnum"] = jobnum |
||||
ip_detail_dict[company][ip_detail_dict_key]["req_frequency"] += count |
||||
|
||||
# 统计总请求次数和独立IP数 |
||||
reqs_total = sum(data["reqs"] for data in grouped_data.values()) |
||||
|
||||
# 请求为0抛出 |
||||
if reqs_total == 0: |
||||
return result |
||||
|
||||
# 构建summary部分 |
||||
ip_data_list = [ |
||||
{ |
||||
"company": company, |
||||
"req_frequency": data["reqs"], |
||||
# 本公司的 请求次数/所有公司 请求次数的合计 |
||||
"frequency_rate": round(data["reqs"] / reqs_total, 4), |
||||
"ip_count": len(data["ips"]), |
||||
# 本公司的 ip个数/所有公司 ip个数的合计 |
||||
"ip_rate": round(len(data["ips"]) / len(ips_total), 4), |
||||
# 本公司的 请求次数/本公司 ip个数的合计 |
||||
"ip_avg": data["reqs"] // len(data["ips"]), |
||||
} |
||||
for company, data in grouped_data.items() |
||||
] |
||||
result["summary"]["ip"] = sorted(ip_data_list, key=lambda x: x["req_frequency"], reverse=True) |
||||
|
||||
# 构建detail部分 |
||||
result["detail"]["ip"] = { |
||||
company: sorted(data.values(), key=lambda x: x['req_frequency'], reverse=True) |
||||
for company, data in ip_detail_dict.items() |
||||
} |
||||
|
||||
return result |
||||
|
||||
|
||||
def account_summary_data_format(account_summary_data): |
||||
""" |
||||
账号维度数据转换方法 |
||||
""" |
||||
result = {"summary": {"account": []}, "detail": {"account": {}}} |
||||
grouped_data = defaultdict(lambda: {"reqs": 0, "accounts": set()}) |
||||
account_detail_dict = defaultdict(lambda: defaultdict(lambda: {"req_frequency": 0})) |
||||
accounts_total = set() |
||||
for account_data in account_summary_data: |
||||
company = find_region_by_code(account_data["jobnum"], jobnum_region_dict) |
||||
count = account_data["count"] |
||||
account = account_data["account"] |
||||
jobnum = account_data["jobnum"] |
||||
account_detail_dict_key = "{}{}".format(account, jobnum) |
||||
|
||||
# 更新统计数据 |
||||
grouped_data[company]["reqs"] += count |
||||
grouped_data[company]["accounts"].add(account) |
||||
accounts_total.add(account) |
||||
|
||||
# 更新下钻详情 |
||||
account_detail_dict[company][account_detail_dict_key]["req_account"] = account |
||||
account_detail_dict[company][account_detail_dict_key]["req_jobnum"] = jobnum |
||||
account_detail_dict[company][account_detail_dict_key]["req_frequency"] += count |
||||
|
||||
# 统计总请求次数和独立账号数 |
||||
reqs_total = sum(data["reqs"] for data in grouped_data.values()) |
||||
|
||||
# 请求为0抛出 |
||||
if reqs_total == 0: |
||||
return result |
||||
|
||||
# 构建summary部分 |
||||
account_data_list = [ |
||||
{ |
||||
"company": company, |
||||
"req_frequency": data["reqs"], |
||||
# 本公司的 请求次数/所有公司 请求次数的合计 |
||||
"frequency_rate": round(data["reqs"] / reqs_total, 4), |
||||
"account_count": len(data["accounts"]), |
||||
# 本公司的 账号次数/所有公司 账号次数的合计 |
||||
"account_rate": round(len(data["accounts"]) / len(accounts_total), 4), |
||||
# 本公司的 请求次数/本公司 账号次数的合计 |
||||
"account_avg": data["reqs"] // len(data["accounts"]), |
||||
} |
||||
for company, data in grouped_data.items() |
||||
] |
||||
result["summary"]["account"] = sorted(account_data_list, key=lambda x: x["req_frequency"], reverse=True) |
||||
|
||||
# 构建detail部分 |
||||
result["detail"]["account"] = {company: sorted(data.values(), key=lambda x: x['req_frequency'], reverse=True) |
||||
for company, data in account_detail_dict.items()} |
||||
|
||||
return result |
||||
|
||||
|
||||
def interface_summary_data_format(interface_summary_data): |
||||
""" |
||||
接口维度数据转换方法 |
||||
""" |
||||
result = {"summary": {"interface": []}, "detail": {"interface": {}}} |
||||
grouped_data = defaultdict(lambda: {"reqs": 0}) |
||||
interface_detail_dict = defaultdict(lambda: defaultdict(lambda: {"req_frequency": 0})) |
||||
|
||||
for interface_data in interface_summary_data: |
||||
count = interface_data["count"] |
||||
interface = interface_data["interface"] |
||||
jobnum = interface_data["jobnum"] |
||||
account = interface_data["account"] |
||||
ip = interface_data["ip"] |
||||
interface_detail_dict_key = "{}{}".format(ip, account, jobnum) |
||||
|
||||
# 更新统计数据 |
||||
grouped_data[interface]["reqs"] += count |
||||
# 构建下钻详情 |
||||
interface_detail_dict[interface][interface_detail_dict_key]["interface_addr"] = interface |
||||
interface_detail_dict[interface][interface_detail_dict_key]["req_ip"] = ip |
||||
interface_detail_dict[interface][interface_detail_dict_key]["req_account"] = account |
||||
interface_detail_dict[interface][interface_detail_dict_key]["req_jobnum"] = jobnum |
||||
interface_detail_dict[interface][interface_detail_dict_key]["req_frequency"] += count |
||||
|
||||
# 统计总请求次数 |
||||
reqs_total = sum(data["reqs"] for data in grouped_data.values()) |
||||
|
||||
# 请求为0抛出 |
||||
if reqs_total == 0: |
||||
return result |
||||
|
||||
# 构建summary部分 |
||||
interface_data_list = [ |
||||
{ |
||||
"interface_addr": interface, |
||||
"req_frequency": data["reqs"], |
||||
# 本接口的 请求次数/所有接口 请求次数的合计 |
||||
"frequency_rate": round(data["reqs"] / reqs_total, 4), |
||||
# 本接口的 请求次数/ 20 查询top20接口 |
||||
"frequency_avg": data["reqs"] // 20, |
||||
} |
||||
for company, data in grouped_data.items() |
||||
] |
||||
result["summary"]["interface"] = sorted(interface_data_list, key=lambda x: x["req_frequency"], reverse=True) |
||||
|
||||
# 构建detail部分 |
||||
result["detail"]["interface"] = { |
||||
company: sorted(data.values(), key=lambda x: x["req_frequency"], reverse=True) |
||||
for company, data in interface_detail_dict.items() |
||||
} |
||||
|
||||
return result |
||||
|
||||
|
||||
def menu_summary_data_format(menu_summary_data): |
||||
""" |
||||
菜单维度数据转换方法 |
||||
""" |
||||
result = {"summary": {"menu": []}, "detail": {"menu": {}}} |
||||
grouped_data = defaultdict(lambda: {"reqs": 0, "menu": set()}) |
||||
menu_detail_dict = defaultdict(lambda: defaultdict(lambda: {"req_frequency": 0})) |
||||
menu_total = set() |
||||
|
||||
for menu_data in menu_summary_data: |
||||
count = menu_data["count"] |
||||
menu = menu_data["menu"] |
||||
jobnum = menu_data["jobnum"] |
||||
account = menu_data["account"] |
||||
ip = menu_data["ip"] |
||||
menu_detail_dict_key = "{}{}{}".format(ip, account, jobnum) |
||||
|
||||
# 更新统计数据和独立菜单数 |
||||
grouped_data[menu]["reqs"] += count |
||||
grouped_data[menu]["menu"].add(menu) |
||||
menu_total.add(menu) |
||||
# 构建下钻详情 |
||||
menu_detail_dict[menu][menu_detail_dict_key]["menu_name"] = menu |
||||
menu_detail_dict[menu][menu_detail_dict_key]["req_ip"] = ip |
||||
menu_detail_dict[menu][menu_detail_dict_key]["req_account"] = account |
||||
menu_detail_dict[menu][menu_detail_dict_key]["req_jobnum"] = jobnum |
||||
menu_detail_dict[menu][menu_detail_dict_key]["req_frequency"] += count |
||||
|
||||
# 统计总请求次数 |
||||
reqs_total = sum(data["reqs"] for data in grouped_data.values()) |
||||
|
||||
# 请求为0抛出 |
||||
if reqs_total == 0 or menu_total == 0: |
||||
return result |
||||
|
||||
# 构建summary部分 |
||||
menu_data_list = [ |
||||
{ |
||||
"menu_name": menu, |
||||
"req_frequency": data["reqs"], |
||||
# 本菜单的 请求次数 /所有菜单 请求次数的合计 |
||||
"frequency_rate": round(data["reqs"] / reqs_total, 4), |
||||
# 本菜单的 请求次数 /所有菜单 个数的合计 |
||||
"frequency_avg": data["reqs"] // len(menu_total), |
||||
} |
||||
for company, data in grouped_data.items() |
||||
] |
||||
result["summary"]["menu"] = sorted(menu_data_list, key=lambda x: x["req_frequency"], reverse=True) |
||||
|
||||
# 构建detail部分 |
||||
result["detail"]["menu"] = {company: sorted(data.values(), key=lambda x: x["req_frequency"], reverse=True) |
||||
for company, data in menu_detail_dict.items()} |
||||
|
||||
return result |
||||
|
@ -0,0 +1,218 @@ |
||||
#!/usr/bin/python |
||||
# encoding=utf-8 |
||||
# author: tangwy |
||||
|
||||
import json |
||||
import os, re |
||||
import codecs |
||||
import traceback |
||||
from collections import defaultdict |
||||
|
||||
from isoc.utils.esUtil import EsUtil |
||||
from isoc.utils.dashboard_data_conversion import ip_summary_data_format, account_summary_data_format, \ |
||||
interface_summary_data_format, menu_summary_data_format, calculate_time_difference, summary_data_reqs_format |
||||
from dataInterface.functions import CFunction |
||||
from dataInterface.db.params import CPgSqlParam |
||||
|
||||
from ext_logging import logger |
||||
|
||||
TABLE_NAME = "ueba_logs" |
||||
|
||||
DATA_TYPE = { |
||||
"IP": 1, |
||||
"ACCOUNT": 2, |
||||
"INTERFACE": 3, |
||||
"MENU": 4, |
||||
} |
||||
|
||||
|
||||
def pg_get_ip_group_data(startTime, endTime): |
||||
""" |
||||
IP维度查询 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = [] |
||||
sql = """ select ip, jobnum, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by ip, jobnum""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["IP"]))) |
||||
if res: |
||||
for item in res: |
||||
result.append({ |
||||
"ip": item[0], |
||||
"jobnum": item[2], |
||||
"count": item[3], |
||||
}) |
||||
return result |
||||
|
||||
|
||||
def pg_get_account_group_data(startTime, endTime): |
||||
""" |
||||
账号维度查询 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = [] |
||||
sql = """ select account, jobnum, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by account, jobnum""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["ACCOUNT"]))) |
||||
if res: |
||||
for item in res: |
||||
result.append({ |
||||
"account": item[0], |
||||
"jobnum": item[2], |
||||
"count": item[3], |
||||
}) |
||||
return result |
||||
|
||||
|
||||
def pg_get_interface_group_data(startTime, endTime): |
||||
""" |
||||
接口维度查询 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = [] |
||||
sql = """ select interface, sip, jobnum, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by interface, ip, jobnum""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["INTERFACE"]))) |
||||
if res: |
||||
for item in res: |
||||
result.append({ |
||||
"interface": item[0], |
||||
"ip": item[1], |
||||
"jobnum": item[2], |
||||
"count": item[3], |
||||
}) |
||||
return result |
||||
|
||||
|
||||
def pg_get_menu_group_data(startTime, endTime): |
||||
""" |
||||
菜单维度查询 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = [] |
||||
sql = """ select menu, sip, jobnum, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by menu, ip, jobnum""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["MENU"]))) |
||||
if res: |
||||
for item in res: |
||||
result.append({ |
||||
"menu": item[0], |
||||
"ip": item[1], |
||||
"jobnum": item[2], |
||||
"count": item[3], |
||||
}) |
||||
return result |
||||
|
||||
|
||||
def pg_get_previous_company_count(startTime, endTime, data_type): |
||||
""" |
||||
账号维度查询菜请求次数 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
:param data_type: 公司聚合类型 ACCOUNT or IP , |
||||
""" |
||||
result = defaultdict(int) |
||||
if data_type in DATA_TYPE: |
||||
data_type = DATA_TYPE[data_type] |
||||
sql = """ select jobnum, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by jobnum""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, data_type))) |
||||
if res: |
||||
for item in res: |
||||
company = find_region_by_code(item[0], jobnum_region_dict) |
||||
result[company] += item[1] |
||||
return result |
||||
|
||||
|
||||
def pg_get_previous_interface_count(startTime, endTime): |
||||
""" |
||||
接口维度查询请求总次数 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = defaultdict(int) |
||||
sql = """ select interface, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by interface""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["INTERFACE"]))) |
||||
if res: |
||||
for item in res: |
||||
result[item[0]] += item[1] |
||||
return result |
||||
|
||||
|
||||
def pg_get_previous_menu_count(startTime, endTime): |
||||
""" |
||||
菜单维度查询请求总次数 |
||||
:param startTime: 开始时间, |
||||
:param endTime: 结束时间, |
||||
""" |
||||
result = defaultdict(int) |
||||
sql = """ select menu, sum(count) from {TABLE_NAME} |
||||
where logdate >= %s and logate < %s and data_type = %s |
||||
group by menu""".format(TABLE_NAME=TABLE_NAME) |
||||
res = CFunction.execute(CPgSqlParam(sql, params=(startTime, endTime, DATA_TYPE["MENU"]))) |
||||
if res: |
||||
for item in res: |
||||
result[item[0]] += item[1] |
||||
return result |
||||
|
||||
|
||||
def entry(data_type, start, end): |
||||
# 前一段开始时间 |
||||
previous_time = calculate_time_difference(start, end) |
||||
|
||||
try: |
||||
data = {} |
||||
if data_type == "1": |
||||
ip_summary_data = pg_get_ip_group_data(start, end) |
||||
data = ip_summary_data_format(ip_summary_data) |
||||
|
||||
previous_company_dict = pg_get_previous_company_count(previous_time, start, "IP") |
||||
for d in data["summary"]["account"]: |
||||
d["trend"] = round( |
||||
(d["req_frequency"] - previous_company_dict.get(d["company"], 0)) / previous_company_dict.get( |
||||
d["company"], 0), 4) |
||||
|
||||
if data_type == "2": |
||||
account_summary_data = pg_get_account_group_data(start, end) |
||||
data = account_summary_data_format(account_summary_data) |
||||
|
||||
previous_company_dict = pg_get_previous_company_count(previous_time, start, "ACCOUNT") |
||||
for d in data["summary"]["account"]: |
||||
d["trend"] = round( |
||||
(d["req_frequency"] - previous_company_dict.get(d["company"], 0)) / previous_company_dict.get( |
||||
d["company"], 0), 4) |
||||
|
||||
if data_type == "3": |
||||
interface_summary_data = pg_get_interface_group_data(start, end) |
||||
data = interface_summary_data_format(interface_summary_data) |
||||
|
||||
previous_interface_dict = pg_get_previous_interface_count(previous_time, start) |
||||
for d in data["summary"]["account"]: |
||||
d["trend"] = round( |
||||
(d["req_frequency"] - previous_interface_dict.get(d["company"], 0)) / previous_interface_dict.get( |
||||
d["company"], 0), 4) |
||||
|
||||
if data_type == "4": |
||||
menu_summary_data = pg_get_menu_group_data(start, end) |
||||
data = menu_summary_data_format(menu_summary_data) |
||||
|
||||
previous_menu_dict = pg_get_previous_menu_count(previous_time, start) |
||||
for d in data["summary"]["account"]: |
||||
d["trend"] = round( |
||||
(d["req_frequency"] - previous_menu_dict.get(d["company"], 0)) / previous_menu_dict.get( |
||||
d["company"], 0), 4) |
||||
return data |
||||
except Exception, e: |
||||
logger.error("分析结构获取失败, err: {}, traceback: {}".format(str(e), traceback.format_exc())) |
||||
raise e |
@ -0,0 +1,109 @@ |
||||
# coding=utf-8 |
||||
""" |
||||
@Author: fu-zhe |
||||
@FileName: db2json.py |
||||
@DateTime: 2024/5/15 10:19 |
||||
@Description: 数据库工具查询之后的数据为 list嵌套 需要转换成 前端方便识别的json数据 |
||||
""" |
||||
import json |
||||
import traceback |
||||
|
||||
from dataInterface.functions import CFunction |
||||
from dataInterface.db.params import CPgSqlParam |
||||
from uebaMetricsAnalysis.utils.ext_logging import logger |
||||
|
||||
|
||||
class DBType(object): |
||||
LIST = 'list' |
||||
DICT = 'dict' |
||||
|
||||
JOB_TABLE_NAME = "ueba_clean_jobs" |
||||
ANALYSIS_TABLE_NAME = "ueba_analysis_log" |
||||
|
||||
class DBUtils(object): |
||||
@classmethod |
||||
def transition(cls, filed, sql, data_type): |
||||
""" |
||||
数据转换 将json格式的data转换成前端方便使用的 json |
||||
:param data_type: 转换数据类型 目前有 list dict两种 |
||||
:param filed: list 格式 数据库字段 例如 select id, name from table; filed= ['id','name'] |
||||
:param sql: sql语句 `select * from table` |
||||
:return: [{filed1: value1, filed2: value2,···}, ····] 或 {filed1: value1, filed2: value2,···} |
||||
""" |
||||
data = cls.execute(sql=sql) |
||||
if cls.is_list_of_empty_lists(data): |
||||
return eval(data_type)() |
||||
if data_type == DBType.DICT: |
||||
data = data[0] |
||||
if len(filed) != len(data): |
||||
raise Exception("{}与数据库查询结果长度不一致".format(filed)) |
||||
res = {cls.snake2camel(filed[i]): data[i] for i in range(len(filed))} |
||||
logger.info("res = {}".format(res)) |
||||
return res |
||||
if data_type == DBType.LIST: |
||||
res = [] |
||||
if not data: |
||||
return res |
||||
for item in data: |
||||
if len(item) != len(filed): |
||||
raise Exception("{}与数据库查询结果长度不一致".format(filed)) |
||||
res.append({cls.snake2camel(filed[i]): item[i] for i in range(len(filed))}) |
||||
return res |
||||
|
||||
@classmethod |
||||
def snake2camel(cls, snake_filed): |
||||
""" |
||||
蛇形命名转换小驼峰命名 |
||||
:param snake_filed: 蛇形命名 例如 user_name |
||||
:return: 驼峰命名 user_name ---> userName |
||||
""" |
||||
if not snake_filed or not isinstance(snake_filed, str): |
||||
return snake_filed |
||||
parts = snake_filed.split('_') |
||||
# 转换第一个单词为小写,其余单词首字母大写 |
||||
camel = parts[0] + ''.join(word.capitalize() for word in parts[1:]) |
||||
return camel |
||||
|
||||
@classmethod |
||||
def execute(cls, sql): |
||||
""" |
||||
执行sql语句 |
||||
:param sql: sql语句 |
||||
:return: |
||||
""" |
||||
try: |
||||
sql_list = CPgSqlParam(sql) |
||||
logger.info("execute sql :\n {}\n".format(sql)) |
||||
data = CFunction.execute(sql_list) |
||||
logger.info("execute result : {}".format(data)) |
||||
return json.loads(data) |
||||
except Exception as e: |
||||
logger.error("execute sql error sql: \n {}\n tracback: {}\n".format(sql, traceback.format_exc())) |
||||
raise Exception("查询失败") |
||||
|
||||
@classmethod |
||||
def is_list_of_empty_lists(cls, target_list): |
||||
# 更清晰地检查每个子列表是否为空 |
||||
return all(not sublist or len(sublist) == 0 for sublist in target_list) |
||||
|
||||
@classmethod |
||||
def list_snake2camel(cls, snake_list): |
||||
""" |
||||
将列表中 字典的snake命名变成camel命名格式 |
||||
:param snake_list: list内部都是蛇形命名的dict `[{'user_name':'', 'user_age': ''}]` |
||||
:return: `[{'user_name':'', 'user_age': ''}]` ----> `[{'userName':'', 'userAge':''}]` |
||||
""" |
||||
camel_list = [] |
||||
for snake_dict in snake_list: |
||||
camel_list.append({cls.snake2camel(snake): value for snake, value in snake_dict.items()}) |
||||
return camel_list |
||||
|
||||
@classmethod |
||||
def write_job_status(self,job_id,status,err): |
||||
sql = """update {JOB_TABLE_NAME} set status=%s err=%s |
||||
where job_id=%s """.format(JOB_TABLE_NAME=JOB_TABLE_NAME) |
||||
CFunction.execute(CPgSqlParam(sql, params=(status, err, job_id))) |
||||
@classmethod |
||||
def insert_job_record(self,job_id,start_time,end_time,status): |
||||
sql = """insert into {JOB_TABLE_NAME}(job_id,start_time,end_time,status) values(%s,%s,%s,%s)""".format(JOB_TABLE_NAME=JOB_TABLE_NAME) |
||||
CFunction.execute(CPgSqlParam(sql, params=(job_id,start_time, end_time,status))) |
@ -0,0 +1,415 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# @Time : 2019/6/6 9:48 |
||||
# @Author : panda |
||||
|
||||
import datetime |
||||
import json |
||||
import time |
||||
import traceback |
||||
from elasticsearch import Elasticsearch |
||||
from elasticsearch import helpers |
||||
|
||||
from appsUtils.confutil import ConfUtil |
||||
|
||||
conf_util = ConfUtil() |
||||
es_dict = conf_util.getElasticsearchConf() |
||||
es_host_list = list() |
||||
for ip in es_dict.get('ip').split(','): |
||||
es_host_list.append({'host': ip, 'port': int(es_dict.get('webport'))}) |
||||
# es_host_list = [{'host': '10.67.1.180', 'port': 9200}] |
||||
# 默认type |
||||
TYPE = '_doc' |
||||
# 默认分片数量 |
||||
NUMBER_OF_SHARDS = 5 |
||||
# 默认副本数量 |
||||
NUMBER_OF_REPLICAS = 1 |
||||
|
||||
|
||||
def to_dict(data): |
||||
""" |
||||
将sql 获取的list结果集转化为[{xx=xxx,x=xxx},{}] |
||||
:param data: sql查询的数据 |
||||
:return: |
||||
""" |
||||
res = list() |
||||
columns = data.get('columns') |
||||
for row in data.get('rows'): |
||||
tmp = dict() |
||||
for i in range(0, len(row)): |
||||
tmp[columns[i]['name']] = row[i] |
||||
res.append(tmp) |
||||
return res |
||||
|
||||
|
||||
class EsUtil(object): |
||||
es_client = None |
||||
|
||||
def __init__(self): |
||||
if not EsUtil.es_client: |
||||
EsUtil.es_client = Elasticsearch(es_host_list, |
||||
timeout=60, |
||||
max_retries=10, |
||||
retry_on_timeout=True) |
||||
self.es = EsUtil.es_client |
||||
|
||||
def get_client(self): |
||||
""" |
||||
提供原生的es_Client |
||||
:return: |
||||
""" |
||||
return self.es |
||||
|
||||
def is_index_exist(self, index_name): |
||||
return self.es.indices.exists(index=index_name) |
||||
|
||||
def get_available_index(self, start_time=None, end_time=None, prefix=None, suffix=None): |
||||
results = list() |
||||
index_ = "*" |
||||
start_date = None |
||||
end_date = None |
||||
if prefix: |
||||
index_ = prefix + index_ |
||||
if suffix: |
||||
index_ = index_ + suffix |
||||
res = self.es.cat.indices(index=index_, format="json") |
||||
if start_time: |
||||
start_date = datetime.datetime.fromtimestamp(start_time / 1000).strftime("%Y%m%d") |
||||
|
||||
if end_time: |
||||
end_date = datetime.datetime.fromtimestamp(end_time / 1000).strftime("%Y%m%d") |
||||
|
||||
for ind in res: |
||||
indices = ind.get('index', '').split('-') |
||||
if start_date and len(indices) > 1: |
||||
if indices[-2] < start_date: |
||||
continue |
||||
if end_date and len(indices) > 1: |
||||
if indices[-2] > end_date: |
||||
continue |
||||
results.append(ind) |
||||
return results |
||||
|
||||
def get_available_index_name(self, start_time=None, end_time=None, prefix=None, suffix=None): |
||||
results = list() |
||||
indices = self.get_available_index(start_time, end_time, prefix, suffix) |
||||
if not indices: |
||||
return results |
||||
for index_ in indices: |
||||
results.append(index_.get("index")) |
||||
return results |
||||
|
||||
def search_by_sql(self, sql): |
||||
""" |
||||
sql查询 |
||||
注:keyword类型的字段才能进行分组聚合查询 |
||||
:param sql: |
||||
:return: |
||||
""" |
||||
return to_dict(self.es.xpack.sql.query(body={'query': sql})) |
||||
|
||||
def create_index(self, index_name, field_type_dict, number_of_shards, number_of_replicas): |
||||
""" |
||||
简单的创建索引,暂时支持传入简单的键值对 |
||||
:param index_name 索引名称 |
||||
:param field_type_dict 字段名称,类型字典 |
||||
:param number_of_shards 分片数量 |
||||
:param number_of_replicas 副本数量 |
||||
:return: 创建成功 |
||||
""" |
||||
|
||||
if self.is_index_exist(index_name): |
||||
raise Exception('index [%s] is exist' % index_name) |
||||
body = dict() |
||||
settings = { |
||||
'number_of_shards': number_of_shards, |
||||
'number_of_replicas': number_of_replicas |
||||
} |
||||
mappings = dict() |
||||
index_type = dict() |
||||
properties = dict() |
||||
# print field_type_dict |
||||
for (key, value) in field_type_dict.items(): |
||||
properties[key] = {'type': value} |
||||
index_type['properties'] = properties |
||||
mappings[TYPE] = index_type |
||||
body['settings'] = settings |
||||
body['mappings'] = mappings |
||||
# print json.dumps(body) |
||||
response = self.es.indices.create(index=index_name, body=body) |
||||
return response['acknowledged'] and response['shards_acknowledged'] |
||||
|
||||
def create_index_by_mapping_alias(self, index_name, mappings, alias_name): |
||||
""" |
||||
加入别名和动态mapping |
||||
:param index_name: |
||||
:param mappings: |
||||
:param alias_name: |
||||
:return: |
||||
""" |
||||
if self.is_index_exist(index_name): |
||||
raise Exception('index [%s] is exist' % index_name) |
||||
|
||||
# es.indices.create(index=index_name) |
||||
# es.indices.put_mapping(index=index_name, body=mapping) |
||||
# es.indices.put_alias(index=index_name,name=alias_name) |
||||
|
||||
# 使用一个请求创建 |
||||
request_body = dict() |
||||
request_body['settings'] = { |
||||
'number_of_replicas': NUMBER_OF_REPLICAS, |
||||
'number_of_shards': NUMBER_OF_SHARDS |
||||
} |
||||
if isinstance(mappings, dict): |
||||
request_body['mappings'] = mappings |
||||
else: |
||||
request_body['mappings'] = json.loads(mappings) |
||||
request_body[index_name] = { |
||||
'aliases': { |
||||
alias_name: {} |
||||
} |
||||
} |
||||
response = self.es.indices.create(index=index_name, body=request_body) |
||||
return response['acknowledged'] and response['shards_acknowledged'] |
||||
|
||||
def create_index_simple(self, index_name, field_type_dict): |
||||
""" |
||||
默认五个分片一个副本,或者从配置文件中读取,暂定 |
||||
:param index_name: |
||||
:param field_type_dict: |
||||
:return: |
||||
""" |
||||
return self.create_index(index_name, field_type_dict, NUMBER_OF_SHARDS, NUMBER_OF_REPLICAS) |
||||
|
||||
def create_index_by_body(self, index_name, request_body): |
||||
""" |
||||
自己传入body进行索引的创建 |
||||
:param index_name: |
||||
:param request_body: 用户传入mapping,setting设置{‘mappings’:{'properties‘:{}},'settings':{}} |
||||
:return: 索引是否创建成功 |
||||
""" |
||||
if self.is_index_exist(index_name): |
||||
raise Exception('index [%s] is exist' % index_name) |
||||
response = self.es.indices.create(index=index_name, body=request_body) |
||||
return response['acknowledged'] and response['shards_acknowledged'] |
||||
|
||||
def search(self, index_name, request_body, request_params=dict()): |
||||
""" |
||||
查询接口(原生) |
||||
:param request_params: |
||||
:param index_name: |
||||
:param request_body: |
||||
:return: |
||||
""" |
||||
return self.es.search(index=index_name, body=request_body, params=request_params, request_timeout=60) |
||||
|
||||
def search_by_uri(self, index_name, uri_params): |
||||
""" |
||||
通过uri的方式进行查询 |
||||
demo: test/_search?q=Panda&df=name&from=10&size=10&sort=age:desc&sort=id:desc |
||||
:param index_name:索引名称,可以为空,会在所有的索引中查询 |
||||
:param uri_params: dict类型,类似于 |
||||
{ |
||||
'q': 'Alice', |
||||
'df': "name", |
||||
'from': 3, |
||||
'size': 10, |
||||
'sort': [ |
||||
'age:desc', 'name:desc' |
||||
] |
||||
},详细信息请查询uri语法 |
||||
:return: |
||||
""" |
||||
return self.es.search(index=index_name, params=uri_params) |
||||
|
||||
def scroll_search(self, index_name, scroll, request_body, request_params=dict()): |
||||
""" |
||||
通过快照进行分页查询,并返回第一个快照查询的结果和快照的id,用于继续查询 |
||||
注:此查询只能不停的向后查询,不能返回上一页 |
||||
:param request_params: |
||||
:param index_name 索引名称 |
||||
:param scroll 快照保留的时间 |
||||
:param request_body 查询的请求参数 |
||||
:return: response为查询的数据,scroll_msg返回,并用于获取下一次的快照信息,scroll_size可用于跳出循环后记录开始from |
||||
""" |
||||
response = self.es.search(index=index_name, scroll=scroll, body=request_body, params=request_params, request_timeout=60) |
||||
scroll_msg = {'scroll_id': response.get('_scroll_id'), 'scroll': scroll} |
||||
return scroll_msg, response |
||||
|
||||
def scroll_next(self, scroll_msg, request_params=dict()): |
||||
""" |
||||
传入scroll_search返回的第一个参数,用于获取下一次的快照 |
||||
:param request_params: |
||||
:param scroll_msg: |
||||
:return: |
||||
""" |
||||
response = self.es.scroll(body=scroll_msg, params=request_params) |
||||
scroll_msg = {'scroll_id': response.get('_scroll_id'), 'scroll': scroll_msg.get('scroll')} |
||||
return scroll_msg, response |
||||
|
||||
def delete_index(self, index_name): |
||||
""" |
||||
删除 |
||||
:param index_name: |
||||
:return: |
||||
""" |
||||
return self.es.indices.delete(index=index_name)['acknowledged'] |
||||
|
||||
def delete_index_by_alias(self, alias_name): |
||||
""" |
||||
通过别名删除索引和别名,对别名有特殊需求,索引名称为 别名+标志 |
||||
此方法有风险,可能会删除其他人创建的alias_name*索引 |
||||
谨慎使用 |
||||
:return: |
||||
""" |
||||
index_name = '%s*' % alias_name |
||||
try: |
||||
if self.es.indices.exists_alias(name=alias_name, index=index_name): |
||||
self.es.indices.delete_alias(name=alias_name, index=index_name) |
||||
if self.es.indices.exists(index=index_name): |
||||
self.es.indices.delete(index=index_name) |
||||
except: |
||||
traceback.format_exc() |
||||
return not (self.es.indices.exists_alias(name=alias_name, index=index_name) and self.es.indices.exists( |
||||
index=index_name)) |
||||
|
||||
def index(self, index_name, request_body): |
||||
""" |
||||
单条doc插入 |
||||
:param index_name 索引名称 |
||||
:param request_body 请求数据dict |
||||
{ |
||||
"name": "Alice", |
||||
"address": "武汉", |
||||
"age": 1, |
||||
"birthday": "2019-06-03T18:47:45.999" |
||||
} |
||||
:return: |
||||
""" |
||||
return self.es.index(index=index_name, doc_type=TYPE, body=request_body).get('result') |
||||
|
||||
def bulk_insert(self, index_name, data_list): |
||||
""" |
||||
批量插入 |
||||
:return: |
||||
""" |
||||
actions = list() |
||||
for data in data_list: |
||||
action = { |
||||
"_index": index_name, |
||||
"_type": TYPE, |
||||
'_source': data |
||||
} |
||||
actions.append(action) |
||||
|
||||
return helpers.bulk(self.es, actions) |
||||
|
||||
|
||||
|
||||
def search_after_start(self, index_name, request_body): |
||||
""" |
||||
通过elasticsearch search after 避免深度分页的问题 |
||||
:return: |
||||
""" |
||||
if request_body.get('size') is None and request_body.get('sort') is None: |
||||
raise Exception('request body is not validate') |
||||
response = self.es.search(index=index_name, body=request_body) |
||||
search_after_body = { |
||||
'size': request_body.get('size'), |
||||
'sort': request_body.get('sort'), |
||||
'search_after': request_body.get('hits', {}).get('hits', {}).get('sort') |
||||
} |
||||
return search_after_body, response |
||||
|
||||
def search_after(self, index_name, search_after_body): |
||||
""" |
||||
search_after |
||||
:param index_name: |
||||
:param search_after_body |
||||
:return: |
||||
""" |
||||
response = self.es.search(index=index_name, body=search_after_body) |
||||
|
||||
search_after_body = { |
||||
'size': search_after_body.get('size'), |
||||
'sort': search_after_body.get('sort'), |
||||
'search_after': response.get('hits', {}).get('hits', {}).get('sort') |
||||
} |
||||
return search_after_body, response |
||||
|
||||
def add_field(self, index, mapping): |
||||
""" |
||||
新增索引字段 |
||||
@param index: 索引名称 |
||||
@param mapping: 参数样例 mapping = { |
||||
"properties": { |
||||
field_name: { |
||||
"type": field_type |
||||
} |
||||
} |
||||
} |
||||
@return: |
||||
""" |
||||
|
||||
self.es.indices.put_mapping(index=index, doc_type="_doc",body=mapping,include_type_name=True) |
||||
|
||||
def bulk_update(self, index, query_dsl): |
||||
""" |
||||
批量更新 |
||||
@param index: 索引名称 |
||||
@param query_dsl: 满足更新条件的查询语句 { |
||||
"query":{ |
||||
"bool":{"must":[ |
||||
{ |
||||
"terms":{ |
||||
"log_id":["c6c8eaca-d891-4f0e-b15b-b02f02dbe4df","92f40a7c-e3f1-412d-9a00-72f22b7ebc9b","4257dbe6-369a-42f5-9f14-4406a3eb5c7a"] |
||||
} |
||||
} |
||||
]} |
||||
}, |
||||
"script":{ |
||||
"inline":"ctx._source.dport = params.dport", |
||||
"params":{ |
||||
"dport":50801 |
||||
}, |
||||
"lang":"painless" |
||||
} |
||||
} |
||||
@return: |
||||
""" |
||||
self.es.update_by_query(index=index,body=query_dsl) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
es = EsUtil() |
||||
# print es.is_index_exist('test') |
||||
#es.search('', {}) |
||||
index_name = "internal_isop_log-*" |
||||
# mapping = { |
||||
# "properties": { |
||||
# "is_report": { |
||||
# "type": "boolean" |
||||
# } |
||||
# } |
||||
# } |
||||
# |
||||
# es.add_field(index_name,mapping) |
||||
index = 'internal_isop_incident-*' |
||||
query_dsl ={ |
||||
"query":{ |
||||
"bool":{"must":[ |
||||
{ |
||||
"terms":{ |
||||
"id":[ ["9f00c0be-ba38-4edc-9f39-889a57ef89c4cq", "29a9c4dc-e7d4-432b-aef8-d216401cb9e5cq", "8494a6be-f80e-4983-adee-92cbf7ef5c31cq"]] |
||||
} |
||||
} |
||||
]} |
||||
}, |
||||
"script":{ |
||||
"inline":"ctx._source.is_report = params.is_report", |
||||
"params":{ |
||||
"is_report":True |
||||
}, |
||||
"lang":"painless" |
||||
} |
||||
} |
||||
es.bulk_update(index,query_dsl) |
@ -0,0 +1,90 @@ |
||||
#!/usr/bin/python |
||||
#encoding=utf-8 |
||||
# author: tangwy |
||||
|
||||
import json |
||||
import os,re |
||||
import codecs |
||||
import csv |
||||
import ConfigParser |
||||
from isoc.utils.esUtil import EsUtil |
||||
|
||||
|
||||
print json.dumps(es_host_list) |
||||
# conf_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'conf') |
||||
# ini_path = os.path.join(conf_path, 'conf.ini') |
||||
# config = ConfigParser.ConfigParser() |
||||
# config.read(ini_path) |
||||
|
||||
# ES_HOST = config.get('COMMON', 'es_host') |
||||
# ES_PER_COUNT = config.get('COMMON', 'es_per_count') |
||||
# ES_INDEX_NAME = config.get('COMMON', 'es_index_name') |
||||
# CSV_FILE_PATH = config.get('COMMON', 'csv_file_path') |
||||
|
||||
|
||||
|
||||
def createIndex(): |
||||
es = Elasticsearch(es_host_list) |
||||
es.create(index="urba_analyse_2024_06", ignore=400) |
||||
|
||||
map={ |
||||
"ip1": "text", |
||||
"ip2": "text", |
||||
"ip3": "text", |
||||
"ip4": "text", |
||||
} |
||||
es_instance = EsUtil() |
||||
res = es_instance.create_index_simple("urba_analyse_2024_06") |
||||
return res |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def generate_ip_range(start_ip, end_ip): |
||||
# start_parts = list(map(int, start_ip.split('.'))) |
||||
# end_parts = list(map(int, end_ip.split('.'))) |
||||
# ip_range = [] |
||||
|
||||
# while start_parts < end_parts: |
||||
# ip_range.append('.'.join(map(str, start_parts))) |
||||
# start_parts[3] += 1 |
||||
# for i in range(3, 0, -1): |
||||
# if start_parts[i] == 256: |
||||
# start_parts[i] = 0 |
||||
# start_parts[i-1] += 1 |
||||
|
||||
# ip_range.append('.'.join(map(str, start_parts))) # 添加结束IP地址 |
||||
# return ip_range |
||||
|
||||
# # scroll查询数据 |
||||
# def get_ip_summary_data(start_time,end_time,query_body): |
||||
# es = Elasticsearch(ES_HOST) |
||||
# msg = es.search(index=ES_INDEX_NAME,scroll="3m",size=ES_PER_COUNT,_source_includes= ["cookies","url","sip","dip"], query=query_body) |
||||
|
||||
# result = msg['hits']['hits'] |
||||
# total = msg['hits']['total'] |
||||
# scroll_id = msg['_scroll_id'] |
||||
|
||||
# for i in range(0,int(total["value"]/ES_PER_COUNT)+1): |
||||
# query_scroll = es.scroll(scroll_id=scroll_id, scroll='3m')["hits"]["hits"] |
||||
# result += query_scroll |
||||
# return result |
||||
|
||||
# # 读取csv文件 获取ip归属地 |
||||
# def get_ip_area_relation(csv_file_path): |
||||
# iprange_map = {} |
||||
# with codecs.open(csv_file_path, mode='r',encoding='utf-8') as file: |
||||
# csv_reader = csv.reader(file) |
||||
# for row in csv_reader: |
||||
# headers = next(csv_reader) |
||||
# ip_start = headers[0] |
||||
# ip_end = headers[1] |
||||
# ip_range = generate_ip_range(ip_start, ip_end) |
||||
# ip_area = headers[5] |
||||
# print (ip_area) |
||||
# for ip in ip_range: |
||||
# iprange_map[ip] = ip_area |
||||
# return iprange_map |
||||
|
||||
# get_ip_area_relation("/tmp/data/ip_area_relation.csv") |
@ -0,0 +1,801 @@ |
||||
# coding=utf-8 |
||||
from __future__ import unicode_literals |
||||
|
||||
data = { |
||||
"summary": { |
||||
"ip": [ |
||||
{ |
||||
"company": "宜昌分公司", |
||||
"req_frequency": 517, |
||||
"frequency_rate": 17.1475953565506, |
||||
"ip_count": 8, |
||||
"ip_rate": 0.195121951219512, |
||||
"ip_avg": 2.14344941956882, |
||||
"trend": 0.09 |
||||
}, |
||||
{ |
||||
"company": "随州分公司", |
||||
"req_frequency": 329, |
||||
"frequency_rate": 10.9121061359867, |
||||
"ip_count": 7, |
||||
"ip_rate": 0.170731707317073, |
||||
"ip_avg": 1.55887230514096, |
||||
"trend": 0.1 |
||||
}, |
||||
{ |
||||
"company": "孝感分公司", |
||||
"req_frequency": 399, |
||||
"frequency_rate": 13.2338308457711, |
||||
"ip_count": 7, |
||||
"ip_rate": 0.170731707317073, |
||||
"ip_avg": 1.89054726368159, |
||||
"trend": -0.07 |
||||
}, |
||||
{ |
||||
"company": "黄冈分公司", |
||||
"req_frequency": 495, |
||||
"frequency_rate": 16.4179104477612, |
||||
"ip_count": 9, |
||||
"ip_rate": 0.219512195121951, |
||||
"ip_avg": 1.82421227197347, |
||||
"trend": -0.02 |
||||
}, |
||||
{ |
||||
"company": "省公司", |
||||
"req_frequency": 1275, |
||||
"frequency_rate": 42.2885572139304, |
||||
"ip_count": 10, |
||||
"ip_rate": 0.24390243902439, |
||||
"ip_avg": 4.22885572139304, |
||||
"trend": 0.1 |
||||
} |
||||
], |
||||
"account": [ |
||||
{ |
||||
"company": "宜昌分公司", |
||||
"req_frequency": 134, |
||||
"frequency_rate": 19.7058823529412, |
||||
"account_count": 8, |
||||
"account_rate": 0.242424242424242, |
||||
"account_avg": 2.46323529411765, |
||||
"trend": 0.09 |
||||
}, |
||||
{ |
||||
"company": "随州分公司", |
||||
"req_frequency": 73, |
||||
"frequency_rate": 10.7352941176471, |
||||
"account_count": 7, |
||||
"account_rate": 0.212121212121212, |
||||
"account_avg": 1.53361344537815, |
||||
"trend": 0.1 |
||||
}, |
||||
{ |
||||
"company": "孝感分公司", |
||||
"req_frequency": 225, |
||||
"frequency_rate": 33.0882352941176, |
||||
"account_count": 7, |
||||
"account_rate": 0.212121212121212, |
||||
"account_avg": 4.72689075630252, |
||||
"trend": -0.07 |
||||
}, |
||||
{ |
||||
"company": "黄冈分公司", |
||||
"req_frequency": 166, |
||||
"frequency_rate": 24.4117647058824, |
||||
"account_count": 9, |
||||
"account_rate": 0.272727272727273, |
||||
"account_avg": 2.71241830065359, |
||||
"trend": -0.02 |
||||
}, |
||||
{ |
||||
"company": "省公司", |
||||
"req_frequency": 216, |
||||
"frequency_rate": 31.7647058823529, |
||||
"account_count": 10, |
||||
"account_rate": 0.303030303030303, |
||||
"account_avg": 3.17647058823529, |
||||
"trend": 0.1 |
||||
} |
||||
], |
||||
"interface": [ |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 212, |
||||
"frequency_rate": 0.160727824109174, |
||||
"frequency_avg": 0, |
||||
"trend": 0.07 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 225, |
||||
"frequency_rate": 0.170583775587566, |
||||
"frequency_avg": 0, |
||||
"trend": 0.02 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/update/sysconfig", |
||||
"req_frequency": 882, |
||||
"frequency_rate": 0.66868840030326, |
||||
"frequency_avg": 0, |
||||
"trend": -0.09 |
||||
} |
||||
], |
||||
"menu": [ |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 333, |
||||
"frequency_rate": 0.263449367088608, |
||||
"frequency_avg": 111, |
||||
"trend": 0.09 |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 315, |
||||
"frequency_rate": 0.249208860759494, |
||||
"frequency_avg": 105, |
||||
"trend": -0.01 |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 616, |
||||
"frequency_rate": 0.487341772151899, |
||||
"frequency_avg": 205.333333333333, |
||||
"trend": 0.02 |
||||
} |
||||
] |
||||
}, |
||||
"detail": { |
||||
"ip": { |
||||
"宜昌分公司": [ |
||||
{ |
||||
"req_ip": "192.156.3.11", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 22 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.12", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 12 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.19", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 78 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.20", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 79 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.21", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 80 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.22", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 81 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.23", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 82 |
||||
}, |
||||
{ |
||||
"req_ip": "192.156.3.24", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 83 |
||||
} |
||||
], |
||||
"随州分公司": [ |
||||
{ |
||||
"req_ip": "192.116.3.24", |
||||
"req_jobnum": 54415, |
||||
"req_frequency": 44 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.25", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 45 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.26", |
||||
"req_jobnum": "54411", |
||||
"req_frequency": 46 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.27", |
||||
"req_frequency": 47 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.28", |
||||
"req_frequency": 48 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.29", |
||||
"req_frequency": 49 |
||||
}, |
||||
{ |
||||
"req_ip": "192.116.3.30", |
||||
"req_frequency": 50 |
||||
} |
||||
], |
||||
"孝感分公司": [ |
||||
{ |
||||
"req_ip": "192.126.3.24", |
||||
"req_frequency": 54 |
||||
}, |
||||
{ |
||||
"req_ip": "192.126.3.25", |
||||
"req_frequency": 55 |
||||
}, |
||||
{ |
||||
"req_ip": "192.126.3.26", |
||||
"req_frequency": 56 |
||||
}, |
||||
{ |
||||
"req_ip": "192.126.3.27", |
||||
"req_frequency": 57 |
||||
}, |
||||
{ |
||||
"req_ip": "192.126.3.28", |
||||
"req_frequency": 58 |
||||
}, |
||||
{ |
||||
"req_ip": "192.126.3.29", |
||||
"req_frequency": 59 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.30", |
||||
"req_frequency": 60 |
||||
} |
||||
], |
||||
"黄冈分公司": [ |
||||
{ |
||||
"req_ip": "192.106.3.30", |
||||
"req_frequency": 51 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.31", |
||||
"req_frequency": 52 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.32", |
||||
"req_frequency": 53 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.33", |
||||
"req_frequency": 54 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.34", |
||||
"req_frequency": 55 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.35", |
||||
"req_frequency": 56 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.36", |
||||
"req_frequency": 57 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.37", |
||||
"req_frequency": 58 |
||||
}, |
||||
{ |
||||
"req_ip": "192.106.3.38", |
||||
"req_frequency": 59 |
||||
} |
||||
], |
||||
"省公司": [ |
||||
{ |
||||
"req_ip": "192.146.3.38", |
||||
"req_frequency": 123 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.39", |
||||
"req_frequency": 124 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.40", |
||||
"req_frequency": 125 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.41", |
||||
"req_frequency": 126 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.42", |
||||
"req_frequency": 127 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.43", |
||||
"req_frequency": 128 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.44", |
||||
"req_frequency": 129 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.45", |
||||
"req_frequency": 130 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.46", |
||||
"req_frequency": 131 |
||||
}, |
||||
{ |
||||
"req_ip": "192.146.3.47", |
||||
"req_frequency": 132 |
||||
} |
||||
] |
||||
}, |
||||
"account": { |
||||
"宜昌分公司": [ |
||||
{ |
||||
"req_account": "huqx", |
||||
"req_frequency": 33, |
||||
"req_jobnum": 54412 |
||||
}, |
||||
{ |
||||
"req_account": "zhangsf", |
||||
"req_frequency": 34, |
||||
"req_jobnum": 54413 |
||||
}, |
||||
{ |
||||
"req_account": "zhaoj", |
||||
"req_frequency": 35, |
||||
"req_jobnum": 54414 |
||||
} |
||||
], |
||||
"随州分公司": [ |
||||
{ |
||||
"req_account": "sangdq", |
||||
"req_frequency": 36, |
||||
"req_jobnum": 54415 |
||||
}, |
||||
{ |
||||
"req_account": "hujt", |
||||
"req_frequency": 37, |
||||
"req_jobnum": 54416 |
||||
} |
||||
], |
||||
"孝感分公司": [ |
||||
{ |
||||
"req_account": "zhangs", |
||||
"req_frequency": 98, |
||||
"req_jobnum": 43325 |
||||
}, |
||||
{ |
||||
"req_account": "lin", |
||||
"req_frequency": 43, |
||||
"req_jobnum": 43326 |
||||
}, |
||||
{ |
||||
"req_account": "liuhr", |
||||
"req_frequency": 33, |
||||
"req_jobnum": 43327 |
||||
}, |
||||
{ |
||||
"req_account": "sunxq01", |
||||
"req_frequency": 51, |
||||
"req_jobnum": 43328 |
||||
} |
||||
], |
||||
"黄冈分公司": [ |
||||
{ |
||||
"req_account": "shicl", |
||||
"req_frequency": 47, |
||||
"req_jobnum": 65341 |
||||
}, |
||||
{ |
||||
"req_account": "gongxs", |
||||
"req_frequency": 65, |
||||
"req_jobnum": 65342 |
||||
}, |
||||
{ |
||||
"req_account": "sunzs", |
||||
"req_frequency": 54, |
||||
"req_jobnum": 65343 |
||||
} |
||||
], |
||||
"省公司": [ |
||||
{ |
||||
"req_account": "maoxt", |
||||
"req_frequency": 37, |
||||
"req_jobnum": 98761 |
||||
}, |
||||
{ |
||||
"req_account": "xiaod01", |
||||
"req_frequency": 29, |
||||
"req_jobnum": 98761 |
||||
}, |
||||
{ |
||||
"req_account": "qingsx", |
||||
"req_frequency": 71, |
||||
"req_jobnum": 98761 |
||||
}, |
||||
{ |
||||
"req_account": "guobg", |
||||
"req_frequency": 79, |
||||
"req_jobnum": 98761 |
||||
} |
||||
] |
||||
}, |
||||
"interface": { |
||||
"http://190.89.233.2:8909/getUser": [ |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 23, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "zhangq", |
||||
"req_jobnum": 54411 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 24, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "huqx", |
||||
"req_jobnum": 54412 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 25, |
||||
"req_ip": "192.156.3.13", |
||||
"req_account": "zhangsf", |
||||
"req_jobnum": 54413 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 26, |
||||
"req_ip": "192.156.3.14", |
||||
"req_account": "zhaoj", |
||||
"req_jobnum": 54414 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 27, |
||||
"req_ip": "192.156.3.15", |
||||
"req_account": "sangdq", |
||||
"req_jobnum": 54415 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 28, |
||||
"req_ip": "192.156.3.16", |
||||
"req_account": "hujt", |
||||
"req_jobnum": 54416 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 29, |
||||
"req_ip": "192.156.3.17", |
||||
"req_account": "zhangs", |
||||
"req_jobnum": 43325 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getUser", |
||||
"req_frequency": 30, |
||||
"req_ip": "192.156.3.18", |
||||
"req_account": "lin", |
||||
"req_jobnum": 43326 |
||||
} |
||||
], |
||||
"http://190.89.233.2:8909/getpublicconfig": [ |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 43, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "liuhr", |
||||
"req_jobnum": 43327 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 44, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "sunxq01", |
||||
"req_jobnum": 43328 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 45, |
||||
"req_ip": "192.156.3.18", |
||||
"req_account": "shicl", |
||||
"req_jobnum": 65341 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 46, |
||||
"req_ip": "192.106.3.33", |
||||
"req_account": "gongxs", |
||||
"req_jobnum": 65342 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/getpublicconfig", |
||||
"req_frequency": 47, |
||||
"req_ip": "192.106.3.34", |
||||
"req_account": "sunzs", |
||||
"req_jobnum": 65343 |
||||
} |
||||
], |
||||
"http://190.89.233.2:8909/update/sysconfig": [ |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/update/sysconfig", |
||||
"req_frequency": 34, |
||||
"req_ip": "192.106.3.35", |
||||
"req_account": "zhangsf", |
||||
"req_jobnum": 54415 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/update/sysconfig", |
||||
"req_frequency": 23, |
||||
"req_ip": "192.106.3.36", |
||||
"req_account": "zhaoj", |
||||
"req_jobnum": 54416 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8909/update/sysconfig", |
||||
"req_frequency": 78, |
||||
"req_ip": "192.106.3.37", |
||||
"req_account": "sangdq", |
||||
"req_jobnum": 43325 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8910/update/sysconfig", |
||||
"req_frequency": 79, |
||||
"req_ip": "192.146.3.38", |
||||
"req_account": "hujt", |
||||
"req_jobnum": 43326 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8911/update/sysconfig", |
||||
"req_frequency": 80, |
||||
"req_ip": "192.146.3.39", |
||||
"req_account": "zhangs", |
||||
"req_jobnum": 43327 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8912/update/sysconfig", |
||||
"req_frequency": 81, |
||||
"req_ip": "192.146.3.40", |
||||
"req_account": "lin", |
||||
"req_jobnum": 43328 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8913/update/sysconfig", |
||||
"req_frequency": 82, |
||||
"req_ip": "192.146.3.41", |
||||
"req_account": "liuhr", |
||||
"req_jobnum": 65341 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8914/update/sysconfig", |
||||
"req_frequency": 83, |
||||
"req_ip": "192.146.3.42", |
||||
"req_account": "sunxq01", |
||||
"req_jobnum": 65342 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8915/update/sysconfig", |
||||
"req_frequency": 84, |
||||
"req_ip": "192.146.3.43", |
||||
"req_account": "xiaod01", |
||||
"req_jobnum": 65343 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8916/update/sysconfig", |
||||
"req_frequency": 85, |
||||
"req_ip": "192.146.3.44", |
||||
"req_account": "qingsx", |
||||
"req_jobnum": 98761 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8917/update/sysconfig", |
||||
"req_frequency": 86, |
||||
"req_ip": "192.146.3.45", |
||||
"req_account": "guobg", |
||||
"req_jobnum": 98761 |
||||
}, |
||||
{ |
||||
"interface_addr": "http://190.89.233.2:8918/update/sysconfig", |
||||
"req_frequency": 87, |
||||
"req_ip": "192.146.3.46", |
||||
"req_account": "zhangq", |
||||
"req_jobnum": 98761 |
||||
} |
||||
] |
||||
}, |
||||
"menu": { |
||||
"菜单1": [ |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 53, |
||||
"req_ip": "192.106.3.32", |
||||
"req_account": "lin", |
||||
"req_jobnum": "43326" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 54, |
||||
"req_ip": "192.106.3.33", |
||||
"req_account": "liuhr", |
||||
"req_jobnum": "43327" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 55, |
||||
"req_ip": "192.106.3.34", |
||||
"req_account": "sunxq01", |
||||
"req_jobnum": "43328" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 56, |
||||
"req_ip": "192.106.3.35", |
||||
"req_account": "shicl", |
||||
"req_jobnum": "65341" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 57, |
||||
"req_ip": "192.106.3.36", |
||||
"req_account": "gongxs", |
||||
"req_jobnum": "65342" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单1", |
||||
"req_frequency": 58, |
||||
"req_ip": "192.106.3.37", |
||||
"req_account": "sunzs", |
||||
"req_jobnum": "65343" |
||||
} |
||||
], |
||||
"菜单2": [ |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 31, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "zhangq", |
||||
"req_jobnum": "54411" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 32, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "huqx", |
||||
"req_jobnum": "54412" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 33, |
||||
"req_ip": "192.156.3.13", |
||||
"req_account": "zhangsf", |
||||
"req_jobnum": "54413" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 34, |
||||
"req_ip": "192.156.3.14", |
||||
"req_account": "zhaoj", |
||||
"req_jobnum": "54414" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 35, |
||||
"req_ip": "192.156.3.15", |
||||
"req_account": "sangdq", |
||||
"req_jobnum": "54415" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 36, |
||||
"req_ip": "192.156.3.16", |
||||
"req_account": "hujt", |
||||
"req_jobnum": "54416" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 37, |
||||
"req_ip": "192.156.3.17", |
||||
"req_account": "zhangs", |
||||
"req_jobnum": "43325" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 38, |
||||
"req_ip": "192.156.3.18", |
||||
"req_account": "lin", |
||||
"req_jobnum": "43326" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单2", |
||||
"req_frequency": 39, |
||||
"req_ip": "192.156.3.12", |
||||
"req_account": "liuhr", |
||||
"req_jobnum": "43327" |
||||
} |
||||
], |
||||
"菜单3": [ |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 51, |
||||
"req_ip": "192.106.3.33", |
||||
"req_account": "gongxs", |
||||
"req_jobnum": "65342" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 52, |
||||
"req_ip": "192.106.3.34", |
||||
"req_account": "sunzs", |
||||
"req_jobnum": "65343" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 53, |
||||
"req_ip": "192.106.3.35", |
||||
"req_account": "zhangsf", |
||||
"req_jobnum": "54415" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 54, |
||||
"req_ip": "192.106.3.36", |
||||
"req_account": "zhaoj", |
||||
"req_jobnum": "54416" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 55, |
||||
"req_ip": "192.106.3.37", |
||||
"req_account": "sangdq", |
||||
"req_jobnum": "43325" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 56, |
||||
"req_ip": "192.146.3.38", |
||||
"req_account": "hujt", |
||||
"req_jobnum": "43326" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 57, |
||||
"req_ip": "192.146.3.39", |
||||
"req_account": "zhangs", |
||||
"req_jobnum": "43327" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 58, |
||||
"req_ip": "192.146.3.40", |
||||
"req_account": "lin", |
||||
"req_jobnum": "43328" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 59, |
||||
"req_ip": "192.146.3.41", |
||||
"req_account": "liuhr", |
||||
"req_jobnum": "65341" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 60, |
||||
"req_ip": "192.146.3.42", |
||||
"req_account": "sunxq01", |
||||
"req_jobnum": "65342" |
||||
}, |
||||
{ |
||||
"menu_name": "菜单3", |
||||
"req_frequency": 61, |
||||
"req_ip": "192.146.3.43", |
||||
"req_account": "xiaod01", |
||||
"req_jobnum": "65343" |
||||
} |
||||
] |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue