rda-python-metrics 1.0.34__tar.gz → 1.0.36__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rda-python-metrics might be problematic. Click here for more details.
- {rda_python_metrics-1.0.34/src/rda_python_metrics.egg-info → rda_python_metrics-1.0.36}/PKG-INFO +1 -1
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/pyproject.toml +3 -1
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillawsusage.py +4 -3
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillglobususage.py +4 -8
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillosdfusage.py +1 -64
- rda_python_metrics-1.0.36/src/rda_python_metrics/viewawsusage.py +321 -0
- rda_python_metrics-1.0.36/src/rda_python_metrics/viewawsusage.usg +190 -0
- rda_python_metrics-1.0.36/src/rda_python_metrics/viewosdfusage.py +321 -0
- rda_python_metrics-1.0.36/src/rda_python_metrics/viewosdfusage.usg +190 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36/src/rda_python_metrics.egg-info}/PKG-INFO +1 -1
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics.egg-info/SOURCES.txt +4 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics.egg-info/entry_points.txt +2 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/LICENSE +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/MANIFEST.in +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/README.md +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/setup.cfg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/PgIPInfo.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/PgView.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/__init__.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillawsusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillcdgusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillcdgusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillcodusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillcodusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillcountry.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillendtime.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillgdexusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillgdexusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillglobususage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillipinfo.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillipinfo.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filloneorder.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filloneorder.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillosdfusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillrdadb.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillrdadb.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filltdsusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filltdsusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filluser.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/filluser.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/logarch.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/logarch.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/pgperson.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/pgsyspath.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/pgusername.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewallusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewallusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewcheckusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewcheckusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewcodusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewcodusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewordusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewordusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewrqstusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewrqstusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewtdsusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewtdsusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewwebfile.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewwebfile.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewwebusage.py +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/viewwebusage.usg +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics.egg-info/dependency_links.txt +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics.egg-info/requires.txt +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics.egg-info/top_level.txt +0 -0
- {rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/tests/test_metrics.py +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "rda_python_metrics"
|
|
9
|
-
version = "1.0.
|
|
9
|
+
version = "1.0.36"
|
|
10
10
|
authors = [
|
|
11
11
|
{ name="Zaihua Ji", email="zji@ucar.edu" },
|
|
12
12
|
]
|
|
@@ -54,9 +54,11 @@ pythonpath = [
|
|
|
54
54
|
"pgperson" = "rda_python_metrics.pgperson:main"
|
|
55
55
|
"pgusername" = "rda_python_metrics.pgusername:main"
|
|
56
56
|
"viewallusage" = "rda_python_metrics.viewallusage:main"
|
|
57
|
+
"viewawsusage" = "rda_python_metrics.viewawsusage:main"
|
|
57
58
|
"viewcheckusage" = "rda_python_metrics.viewcheckusage:main"
|
|
58
59
|
"viewcodusage" = "rda_python_metrics.viewcodusage:main"
|
|
59
60
|
"viewordusage" = "rda_python_metrics.viewordusage:main"
|
|
61
|
+
"viewosdfusage" = "rda_python_metrics.viewosdfusage:main"
|
|
60
62
|
"viewrqstusage" = "rda_python_metrics.viewrqstusage:main"
|
|
61
63
|
"viewtdsusage" = "rda_python_metrics.viewtdsusage:main"
|
|
62
64
|
"viewwebfile" = "rda_python_metrics.viewwebfile:main"
|
{rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillawsusage.py
RENAMED
|
@@ -94,7 +94,7 @@ def get_log_file_names(option, params):
|
|
|
94
94
|
else:
|
|
95
95
|
pdate = PgUtil.format_date(params[0])
|
|
96
96
|
if len(params) > 1:
|
|
97
|
-
edate = PgUtil.format_date(params[1])
|
|
97
|
+
edate = PgUtil.adddate(PgUtil.format_date(params[1]), 0, 0, 1)
|
|
98
98
|
else:
|
|
99
99
|
edate = PgUtil.curdate()
|
|
100
100
|
while pdate < edate:
|
|
@@ -114,13 +114,14 @@ def fill_aws_usages(filenames):
|
|
|
114
114
|
year = cntall = addall = 0
|
|
115
115
|
for pdate in filenames:
|
|
116
116
|
fnames = filenames[pdate]
|
|
117
|
+
fcnt = len(fnames)
|
|
118
|
+
PgLOG.pglog("{}: Gathering AWS usage info from {} log files at {}".format(pdate, fcnt, PgLOG.current_datetime()), PgLOG.LOGWRN)
|
|
117
119
|
records = {}
|
|
118
120
|
cntadd = entcnt = 0
|
|
119
121
|
for logfile in fnames:
|
|
120
122
|
if not op.isfile(logfile):
|
|
121
123
|
PgLOG.pglog("{}: Not exists for Gathering AWS usage".format(logfile), PgLOG.LOGWRN)
|
|
122
124
|
continue
|
|
123
|
-
PgLOG.pglog("Gathering AWS usage info from {} at {}".format(logfile, PgLOG.current_datetime()), PgLOG.LOGWRN)
|
|
124
125
|
aws = PgFile.open_local_file(logfile)
|
|
125
126
|
if not aws: continue
|
|
126
127
|
while True:
|
|
@@ -184,7 +185,7 @@ def add_usage_records(records, year):
|
|
|
184
185
|
cnt = 0
|
|
185
186
|
for key in records:
|
|
186
187
|
record = records[key]
|
|
187
|
-
cond = "date = '{}' AND time = '{}' AND ip = '{}'
|
|
188
|
+
cond = "date = '{}' AND time = '{}' AND ip = '{}'".format(record['date'], record['time'], record['ip'])
|
|
188
189
|
if PgDBI.pgget(USAGE['PGTBL'], '', cond, PgLOG.LGEREX): continue
|
|
189
190
|
if add_to_allusage(year, record):
|
|
190
191
|
cnt += PgDBI.pgadd(USAGE['PGTBL'], record, PgLOG.LOGWRN)
|
{rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillglobususage.py
RENAMED
|
@@ -147,18 +147,14 @@ def fill_globus_usages(fnames, datelimits):
|
|
|
147
147
|
locflag = 'O' if re.match(r'^https://stratus\.', sline) else 'G'
|
|
148
148
|
idx = wfile.find('?')
|
|
149
149
|
if idx > -1: wfile = wfile[:idx]
|
|
150
|
-
|
|
151
|
-
if
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
method = "WGET"
|
|
155
|
-
elif re.match(r'^python', engine, re.I):
|
|
156
|
-
method = "PYTHN"
|
|
150
|
+
moff = engine.find('/')
|
|
151
|
+
if moff > 0:
|
|
152
|
+
if moff > 20: moff = 20
|
|
153
|
+
method = engine[0:moff].upper()
|
|
157
154
|
else:
|
|
158
155
|
method = "WEB"
|
|
159
156
|
|
|
160
157
|
key = "{}:{}:{}".format(ip, dsid, wfile) if stat == '206' else None
|
|
161
|
-
|
|
162
158
|
if record:
|
|
163
159
|
if key == pkey:
|
|
164
160
|
record['size'] += size
|
{rda_python_metrics-1.0.34 → rda_python_metrics-1.0.36}/src/rda_python_metrics/fillosdfusage.py
RENAMED
|
@@ -185,7 +185,7 @@ def add_usage_records(records, year):
|
|
|
185
185
|
cnt = 0
|
|
186
186
|
for key in records:
|
|
187
187
|
record = records[key]
|
|
188
|
-
cond = "date = '{}' AND time = '{}' AND ip = '{}'
|
|
188
|
+
cond = "date = '{}' AND time = '{}' AND ip = '{}'".format(record['date'], record['time'], record['ip'])
|
|
189
189
|
if PgDBI.pgget(USAGE['OSDFTBL'], '', cond, PgLOG.LGEREX): continue
|
|
190
190
|
if add_to_allusage(year, record):
|
|
191
191
|
cnt += PgDBI.pgadd(USAGE['OSDFTBL'], record, PgLOG.LOGWRN)
|
|
@@ -203,69 +203,6 @@ def add_to_allusage(year, pgrec):
|
|
|
203
203
|
|
|
204
204
|
return PgDBI.add_yearly_allusage(year, record)
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
#
|
|
208
|
-
# Fill usage of a single online data file into table dssdb.wusage of DSS PgSQL database
|
|
209
|
-
#
|
|
210
|
-
def add_file_usage(year, logrec):
|
|
211
|
-
|
|
212
|
-
pgrec = get_wfile_wid(logrec['dsid'], logrec['wfile'])
|
|
213
|
-
if not pgrec: return 0
|
|
214
|
-
|
|
215
|
-
table = "{}_{}".format(USAGE['OSDFTBL'], year)
|
|
216
|
-
cond = "wid = {} AND method = '{}' AND date_read = '{}' AND time_read = '{}'".format(pgrec['wid'], logrec['method'], logrec['date'], logrec['time'])
|
|
217
|
-
if PgDBI.pgget(USAGE['OSDFTBL'], "", cond, PgLOG.LOGWRN): return 0
|
|
218
|
-
|
|
219
|
-
wurec = PgIPInfo.get_wuser_record(logrec['ip'], logrec['date'])
|
|
220
|
-
if not wurec: return 0
|
|
221
|
-
record = {'wid' : pgrec['wid'], 'dsid' : pgrec['dsid']}
|
|
222
|
-
record['wuid_read'] = wurec['wuid']
|
|
223
|
-
record['date_read'] = logrec['date']
|
|
224
|
-
record['time_read'] = logrec['time']
|
|
225
|
-
record['size_read'] = logrec['size']
|
|
226
|
-
record['method'] = logrec['method']
|
|
227
|
-
record['locflag'] = logrec['locflag']
|
|
228
|
-
record['ip'] = logrec['ip']
|
|
229
|
-
record['quarter'] = logrec['quarter']
|
|
230
|
-
|
|
231
|
-
if add_to_allusage(year, logrec, wurec):
|
|
232
|
-
return PgDBI.add_yearly_wusage(year, record)
|
|
233
|
-
else:
|
|
234
|
-
return 0
|
|
235
|
-
|
|
236
|
-
def add_to_allusage(year, logrec, wurec):
|
|
237
|
-
|
|
238
|
-
pgrec = {'email' : wurec['email'], 'org_type' : wurec['org_type'],
|
|
239
|
-
'country' : wurec['country'], 'region' : wurec['region']}
|
|
240
|
-
pgrec['dsid'] = logrec['dsid']
|
|
241
|
-
pgrec['date'] = logrec['date']
|
|
242
|
-
pgrec['quarter'] = logrec['quarter']
|
|
243
|
-
pgrec['time'] = logrec['time']
|
|
244
|
-
pgrec['size'] = logrec['size']
|
|
245
|
-
pgrec['method'] = logrec['method']
|
|
246
|
-
pgrec['ip'] = logrec['ip']
|
|
247
|
-
pgrec['source'] = 'P'
|
|
248
|
-
return PgDBI.add_yearly_allusage(year, pgrec)
|
|
249
|
-
|
|
250
|
-
#
|
|
251
|
-
# return wfile.wid upon success, 0 otherwise
|
|
252
|
-
#
|
|
253
|
-
def get_wfile_wid(dsid, wfile):
|
|
254
|
-
|
|
255
|
-
wfcond = "wfile = '{}'".format(wfile)
|
|
256
|
-
pgrec = PgSplit.pgget_wfile(dsid, "*", wfcond)
|
|
257
|
-
if pgrec:
|
|
258
|
-
pgrec['dsid'] = dsid
|
|
259
|
-
else:
|
|
260
|
-
pgrec = PgDBI.pgget("wfile_delete", "*", "{} AND dsid = '{}'".format(wfcond, dsid))
|
|
261
|
-
if not pgrec:
|
|
262
|
-
pgrec = PgDBI.pgget("wmove", "wid, dsid", wfcond)
|
|
263
|
-
if pgrec:
|
|
264
|
-
pgrec = PgSplit.pgget_wfile(pgrec['dsid'], "*", "wid = {}".format(pgrec['wid']))
|
|
265
|
-
if pgrec: pgrec['dsid'] = dsid
|
|
266
|
-
|
|
267
|
-
return pgrec
|
|
268
|
-
|
|
269
206
|
#
|
|
270
207
|
# call main() to start program
|
|
271
208
|
#
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
###############################################################################
|
|
4
|
+
#
|
|
5
|
+
# Title : viewawsusage
|
|
6
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
7
|
+
# Date : 2025-08-13
|
|
8
|
+
# Purpose : python program to view aws usage information
|
|
9
|
+
#
|
|
10
|
+
# Github : https://github.com/NCAR/rda-python-metrics.git
|
|
11
|
+
#
|
|
12
|
+
###############################################################################
|
|
13
|
+
#
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
from rda_python_common import PgLOG
|
|
18
|
+
from rda_python_common import PgUtil
|
|
19
|
+
from rda_python_common import PgDBI
|
|
20
|
+
from . import PgView
|
|
21
|
+
|
|
22
|
+
VUSG = {
|
|
23
|
+
'SNMS' : "ABCDEHIKMNOPQRSTUWY", # all available short field names in %FLDS
|
|
24
|
+
'OPTS' : 'AabcCdDeEhHikLmMnoOqsStTUwyz', # all available options, used for %params
|
|
25
|
+
'NOPT' : 'abhnwz', # stand alone option without inputs
|
|
26
|
+
'ACND' : 'cdeiIkmMoqSty', # available array condition options
|
|
27
|
+
'RCND' : 'DEsT', # available range condition options
|
|
28
|
+
'CNDS' : 'acdDeEiIkmMnoqsStTy', # condition options, ACND, RCND and 'a'
|
|
29
|
+
'ECND' : 'my', # condition options need evaluating
|
|
30
|
+
'SFLD' : 'DEIKNOTUW', # string fields, to be quoted in condition
|
|
31
|
+
'UFLD' : 'NO', # string fields must be in upper case
|
|
32
|
+
'LFLD' : 'EMPT' # string fields must be in lower case
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# keys %FLDS - short field names
|
|
36
|
+
# column 0 - column title showing in usage view
|
|
37
|
+
# column 1 - field name in format as shown in select clauses
|
|
38
|
+
# column 2 - field name shown in where condition query string
|
|
39
|
+
# column 3 - table name that the field belongs to
|
|
40
|
+
# column 4 - output field length, the longer one of data size and comlun title, determine
|
|
41
|
+
# dynamically if it is 0. Negative values indicate right justification
|
|
42
|
+
# column 5 - precision for floating point value if positive and show total value if not zero
|
|
43
|
+
# column 6 - field flag to indicate it is a group, distinct or sum field
|
|
44
|
+
FLDS = {
|
|
45
|
+
# SHRTNM COLUMNNANE FIELDNAME CNDNAME TBLNAM Size Prc Grp/Sum
|
|
46
|
+
'D' : ['DATE', "date", 'date', 'awsusage', 10, 0, 'G'],
|
|
47
|
+
'E' : ['EMAIL', "awsusage.email", 'awsusage.email', 'awsusage', 0, 0, 'G'],
|
|
48
|
+
'I' : ['IP', "ip", 'ip', 'awsusage', 0, 0, 'G'],
|
|
49
|
+
'M' : ['MONTH', PgDBI.fmtym("date"), 'date', 'awsusage', 7, 0, 'G'],
|
|
50
|
+
'N' : ['COUNTRY', "country", 'country', 'awsusage', 0, 0, 'G'],
|
|
51
|
+
'K' : ['REGION', "region", 'region', 'awsusage', 0, 0, 'G'],
|
|
52
|
+
'O' : ['ORGTYPE', "org_type", 'org_type', 'awsusage', 7, 0, 'G'],
|
|
53
|
+
'P' : ['DSOWNER', "specialist", 'specialist', 'dsowner', 8, 0, 'G'],
|
|
54
|
+
'Q' : ['QUARTER', "quarter", 'quarter', 'awsusage', 7, 0, 'G'],
|
|
55
|
+
'R' : ['DSTITLE', "search.datasets.title", 'search.datasets.title', 'search.datasets', 0, 0, 'G'],
|
|
56
|
+
'S' : ['BYTESIZE', "size", 'size', 'awsusage', -14, -1, 'G'],
|
|
57
|
+
'T' : ['DATASET', "awsusage.dsid", 'awsusage.dsid', 'awsusage', 0, 0, 'G'],
|
|
58
|
+
'W' : ['METHOD', "method", 'method', 'awsusage', 0, 0, 'G'],
|
|
59
|
+
'Y' : ['YEAR', PgDBI.fmtyr("date"), 'date', 'awsusage', 4, 0, 'G'],
|
|
60
|
+
'A' : ['DSCOUNT', "awsusage.dsid", 'A', 'awsusage', -7, -1, 'D'],
|
|
61
|
+
'B' : ['MBYTEREAD', "round(sum(size)/(1000000), 4)", 'B', 'awsusage', -14, 3, 'S'],
|
|
62
|
+
'C' : ['#UNIQUSER', "awsusage.email", 'C', 'awsusage', -9, -1, 'D'],
|
|
63
|
+
'U' : ['#UNIQIP', "awsusage.ip", 'U', 'awsusage', -7, -1, 'D'],
|
|
64
|
+
'H' : ['#ACCESS', "sum(fcount)", 'H', 'awsusage', -8, -1, 'S'],
|
|
65
|
+
'X' : ['INDEX', "", 'X', '', -6, 0, ' ']
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# keys %EXPAND - short field names allow zero usage
|
|
69
|
+
# column 0 - expand ID for group of fields
|
|
70
|
+
# column 1 - field name shown in where condition query string
|
|
71
|
+
# column 2 - field name in format as shown in select clauses
|
|
72
|
+
# column 3 - table name that the field belongs to
|
|
73
|
+
EXPAND = {
|
|
74
|
+
# SHRTNM EXPID CNDSTR FIELDNAME TBLNAM
|
|
75
|
+
'D' : ["TIME", "dDmy"],
|
|
76
|
+
'M' : ["TIME", "dDmy"],
|
|
77
|
+
'Q' : ["TIME", "dDmy"],
|
|
78
|
+
'Y' : ["TIME", "dDmy"],
|
|
79
|
+
|
|
80
|
+
'E' : ["USER", "ecko", "email", "wuser", "user"],
|
|
81
|
+
'O' : ["USER", "ecko", "org_type", "wuser", "user"],
|
|
82
|
+
'N' : ["USER", "ecko", "country", "wuser", "user"],
|
|
83
|
+
'K' : ["USER", "ecko", "region", "wuser", "user"],
|
|
84
|
+
|
|
85
|
+
'R' : ["DSID", "StT", "search.datasets.title", "search.datasets"],
|
|
86
|
+
'T' : ["DSID", "StT", "dataset.dsid", "dataset"],
|
|
87
|
+
'P' : ["DSID", "StT", "specialist", "dsowner"],
|
|
88
|
+
|
|
89
|
+
'W' : ["METHOD", "M", "method", "awsusage"]
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# valid options for %params, a hash array of command line parameters
|
|
93
|
+
# a -- 1 to view all usage info available
|
|
94
|
+
# A -- number or records to return
|
|
95
|
+
# c -- array of specified country codes
|
|
96
|
+
# C -- a string of short field names for viewing usages
|
|
97
|
+
# d -- array of specified dates
|
|
98
|
+
# D -- dates range, array of 1 or 2 dates in format of YYYY-MM-DD
|
|
99
|
+
# e -- array of specified email addresses
|
|
100
|
+
# E -- use given date or date range for email notice of data update
|
|
101
|
+
# h -- for give emails, include their histical emails registered before
|
|
102
|
+
# H -- a string of report title to replace the default one
|
|
103
|
+
# i -- array of specified IP addresses
|
|
104
|
+
# I -- use given email IDs for email notice of data update
|
|
105
|
+
# k -- array of specified region names
|
|
106
|
+
# L -- column delimiter for output
|
|
107
|
+
# m -- array of specified months
|
|
108
|
+
# M -- array of specified download methods
|
|
109
|
+
# o -- array of specified orginization types
|
|
110
|
+
# O -- a string of short field names for sorting on
|
|
111
|
+
# q -- array of the specified quarters, normally combined with years
|
|
112
|
+
# s -- size range, arrage of 1 or 2 sizes in unit of MByte
|
|
113
|
+
# S -- array of login names of specialists who owns the datasets
|
|
114
|
+
# t -- array of specified dataset names
|
|
115
|
+
# T -- dataset range, array of 1 or 2 dataset names
|
|
116
|
+
# U -- given unit for file or data sizes
|
|
117
|
+
# w -- generate view without totals
|
|
118
|
+
# y -- array of specified years
|
|
119
|
+
# z -- generate view including entries without usage
|
|
120
|
+
|
|
121
|
+
params = {}
|
|
122
|
+
|
|
123
|
+
# relationship between parameter options and short field names, A option is not
|
|
124
|
+
# related to a field name if it is not in keys %SNS
|
|
125
|
+
SNS = {
|
|
126
|
+
'c' : 'N', 'd' : 'D', 'D' : 'D', 'e' : 'E', 'i' : 'I', 'k' : 'K', 'm' : 'M',
|
|
127
|
+
'M' : 'W', 'o' : 'O', 'q' : 'Q', 's' : 'S', 'S' : 'P', 't' : 'T', 'T' : 'T', 'y' : 'Y'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
tablenames = fieldnames = condition = ''
|
|
131
|
+
sfields = []
|
|
132
|
+
gfields = []
|
|
133
|
+
dfields = []
|
|
134
|
+
pgname = 'viewawsusage'
|
|
135
|
+
|
|
136
|
+
#
|
|
137
|
+
# main function to run this program
|
|
138
|
+
#
|
|
139
|
+
def main():
|
|
140
|
+
|
|
141
|
+
PgDBI.view_dbinfo()
|
|
142
|
+
argv = sys.argv[1:]
|
|
143
|
+
inputs = []
|
|
144
|
+
option = 'C' # default option
|
|
145
|
+
|
|
146
|
+
for arg in argv:
|
|
147
|
+
if re.match(r'^-.*$', arg):
|
|
148
|
+
curopt = arg[1:2]
|
|
149
|
+
if curopt and VUSG['OPTS'].find(curopt) > -1:
|
|
150
|
+
if VUSG['NOPT'].find(option) > -1:
|
|
151
|
+
params[option] = 1
|
|
152
|
+
elif inputs:
|
|
153
|
+
params[option]= inputs # record input array
|
|
154
|
+
inputs = [] # empty input array
|
|
155
|
+
option = curopt # start a new option
|
|
156
|
+
else:
|
|
157
|
+
PgLOG.pglog(arg + ": Unknown Option", PgLOG.LGWNEX)
|
|
158
|
+
else:
|
|
159
|
+
val = arg
|
|
160
|
+
if val != '!':
|
|
161
|
+
if option == 's':
|
|
162
|
+
val = int(val)*1000000 # convert MBytes to Bytes
|
|
163
|
+
elif option in SNS:
|
|
164
|
+
sfld = SNS[option]
|
|
165
|
+
if VUSG['SFLD'].find(sfld) > -1:
|
|
166
|
+
if VUSG['UFLD'].find(sfld) > -1:
|
|
167
|
+
val = arg.upper() # in case not in upper case
|
|
168
|
+
elif VUSG['LFLD'].find(sfld) > -1:
|
|
169
|
+
val = arg.lower() # in case not in lower case
|
|
170
|
+
if option == 'c':
|
|
171
|
+
val = PgView.get_country_name(val)
|
|
172
|
+
elif option == 't' or option == 'T':
|
|
173
|
+
val = PgUtil.format_dataset_id(val) # add 'ds' if only numbers
|
|
174
|
+
val = "'{}'".format(val)
|
|
175
|
+
inputs.append(val)
|
|
176
|
+
|
|
177
|
+
# record the last option
|
|
178
|
+
if VUSG['NOPT'].find(option) > -1:
|
|
179
|
+
params[option] = 1
|
|
180
|
+
elif inputs:
|
|
181
|
+
params[option] = inputs # record input array
|
|
182
|
+
|
|
183
|
+
if not params:
|
|
184
|
+
PgLOG.show_usage(pgname)
|
|
185
|
+
else:
|
|
186
|
+
check_enough_options()
|
|
187
|
+
|
|
188
|
+
if 'o' not in params:
|
|
189
|
+
if 'e' not in params:
|
|
190
|
+
params['o'] = ['!', "'DSS'"] # default to exclude 'DSS' for organization
|
|
191
|
+
elif params['o'][0] == "'ALL'":
|
|
192
|
+
del params['o']
|
|
193
|
+
|
|
194
|
+
usgtable = "awsusage"
|
|
195
|
+
build_query_strings(usgtable) # build tablenames, fieldnames, and conditions
|
|
196
|
+
records = PgDBI.pgmget(tablenames, fieldnames, condition, PgLOG.UCLWEX)
|
|
197
|
+
if not records: PgLOG.pglog("No Usage Found For Given Conditions", PgLOG.LGWNEX)
|
|
198
|
+
totals = None if 'w' in params else {}
|
|
199
|
+
if dfields or totals != None:
|
|
200
|
+
records = PgView.compact_hash_groups(records, gfields, sfields, dfields, totals)
|
|
201
|
+
if 'z' in params: records = expand_records(records)
|
|
202
|
+
ostr = params['O'][0] if 'O' in params else params['C'][0]
|
|
203
|
+
records = PgView.order_records(records, ostr.replace('X', ''))
|
|
204
|
+
PgView.simple_output(params, FLDS, records, totals)
|
|
205
|
+
|
|
206
|
+
PgLOG.pgexit(0)
|
|
207
|
+
|
|
208
|
+
#
|
|
209
|
+
# cehck if enough information entered on command line for generate view/report, exit if not
|
|
210
|
+
#
|
|
211
|
+
def check_enough_options():
|
|
212
|
+
|
|
213
|
+
cols = params['C'][0] if 'C' in params else 'X'
|
|
214
|
+
if cols == 'X': PgLOG.pglog("{}: miss field names '{}'".format(pgname, VUSG['SNMS']), PgLOG.LGWNEX)
|
|
215
|
+
|
|
216
|
+
if cols.find('Q') > -1 and cols.find('Y') < 0: # add Y if Q included
|
|
217
|
+
cols = re.sub('Q', 'YQ', cols)
|
|
218
|
+
params['C'][0] = cols
|
|
219
|
+
|
|
220
|
+
for sn in cols:
|
|
221
|
+
if sn == 'X': continue # do not process INDEX field
|
|
222
|
+
if VUSG['SNMS'].find(sn) < 0:
|
|
223
|
+
PgLOG.pglog("{}: Field {} must be in field names '{}X'".format(pgname, sn, VUSG['SNMS']), PgLOG.LGWNEX)
|
|
224
|
+
if 'z' not in params or sn in EXPAND: continue
|
|
225
|
+
fld = FLDS[sn]
|
|
226
|
+
if fld[6] != 'G': continue
|
|
227
|
+
PgLOG.pglog("{}: cannot show zero usage for unexpandable field {} - {}".formt(pgname, sn, fld[0]), PgLOG.LGWNEX)
|
|
228
|
+
|
|
229
|
+
if 'E' in params or 'I' in params:
|
|
230
|
+
if 'z' in params:
|
|
231
|
+
PgLOG.pglog(pgname + ": option -z and -E/-I can not be present at the same time", PgLOG.LGWNEX)
|
|
232
|
+
elif 't' not in params or len(params['t']) > 1:
|
|
233
|
+
PgLOG.pglog(pgname + ": specify one dataset for viewing usage of notified users", PgLOG.LGWNEX)
|
|
234
|
+
elif 'E' in params and 'I' in params:
|
|
235
|
+
PgLOG.pglog(pgname + ": option -E and -I can not be present at the same time", PgLOG.LGWNEX)
|
|
236
|
+
|
|
237
|
+
for opt in params:
|
|
238
|
+
if VUSG['CNDS'].find(opt) > -1: return
|
|
239
|
+
PgLOG.pglog("{}: miss condition options '{}'".format(pgname, VUSG['CNDS']), PgLOG.LGWNEX)
|
|
240
|
+
|
|
241
|
+
#
|
|
242
|
+
# process parameter options to build aws query strings
|
|
243
|
+
# global variables are used directly and nothing passes in and returns back
|
|
244
|
+
#
|
|
245
|
+
def build_query_strings(usgtable):
|
|
246
|
+
|
|
247
|
+
# initialize query strings
|
|
248
|
+
global condition, fieldnames, tablenames
|
|
249
|
+
joins = groupnames = ''
|
|
250
|
+
tablenames = usgtable
|
|
251
|
+
cols = params['C'][0]
|
|
252
|
+
|
|
253
|
+
if 'U' in params: # reset units for file and read sizes
|
|
254
|
+
if cols.find('B') > -1: FLDS['B'] = PgView.set_data_unit(FLDS['B'], params['U'][0], "sum(size)")
|
|
255
|
+
if cols.find('S') > -1: FLDS['S'] = PgView.set_data_unit(FLDS['S'], params['U'][0], "size")
|
|
256
|
+
|
|
257
|
+
if 'e' in params and 'h' in params: params['e'] = PgView.include_historic_emails(params['e'], 3)
|
|
258
|
+
|
|
259
|
+
for opt in params:
|
|
260
|
+
if opt == 'C': # build field, table and group names
|
|
261
|
+
for sn in cols:
|
|
262
|
+
if sn == 'X': continue # do not process INDEX field
|
|
263
|
+
fld = FLDS[sn]
|
|
264
|
+
if fieldnames: fieldnames += ', '
|
|
265
|
+
fieldnames += "{} {}".format(fld[1], sn) # add to field name string
|
|
266
|
+
(tablenames, joins) = PgView.join_query_tables(fld[3], tablenames, joins, usgtable)
|
|
267
|
+
if fld[6] == 'S':
|
|
268
|
+
sfields.append(sn)
|
|
269
|
+
else:
|
|
270
|
+
if groupnames: groupnames += ', '
|
|
271
|
+
groupnames += sn # add to group name string
|
|
272
|
+
if fld[6] == 'D':
|
|
273
|
+
dfields.append(sn)
|
|
274
|
+
else:
|
|
275
|
+
gfields.append(sn)
|
|
276
|
+
elif opt == 'O':
|
|
277
|
+
continue # order records later
|
|
278
|
+
elif VUSG['CNDS'].find(opt) > -1:
|
|
279
|
+
if VUSG['NOPT'].find(opt) > -1: continue
|
|
280
|
+
sn = SNS[opt]
|
|
281
|
+
fld = FLDS[sn]
|
|
282
|
+
# build having and where conditon strings
|
|
283
|
+
cnd = PgView.get_view_condition(opt, sn, fld, params, VUSG)
|
|
284
|
+
if cnd:
|
|
285
|
+
if condition: condition += ' AND '
|
|
286
|
+
condition += cnd
|
|
287
|
+
(tablenames, joins) = PgView.join_query_tables(fld[3], tablenames, joins, usgtable)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# append joins, group by, order by, and having strings to condition string
|
|
291
|
+
if 'E' in params or 'I' in params:
|
|
292
|
+
(tablenames, joins) = PgView.join_query_tables("emreceive", tablenames, joins, usgtable)
|
|
293
|
+
if joins:
|
|
294
|
+
if condition:
|
|
295
|
+
condition = "{} AND {}".format(joins, condition)
|
|
296
|
+
else:
|
|
297
|
+
condition = joins
|
|
298
|
+
if 'E' in params or 'I' in params:
|
|
299
|
+
condition += PgView.notice_condition(params['E'], None, params['t'][0])
|
|
300
|
+
if groupnames and sfields: condition += " GROUP BY " + groupnames
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def expand_records(records):
|
|
304
|
+
|
|
305
|
+
recs = PgView.expand_query("TIME", records, params, EXPAND)
|
|
306
|
+
|
|
307
|
+
trecs = PgView.expand_query("USER", records, params, EXPAND, VUSG, SNS, FLDS)
|
|
308
|
+
recs = PgUtil.crosshash(recs, trecs)
|
|
309
|
+
|
|
310
|
+
trecs = PgView.expand_query("DSID", records, params, EXPAND, VUSG, SNS, FLDS)
|
|
311
|
+
recs = PgUtil.crosshash(recs, trecs)
|
|
312
|
+
|
|
313
|
+
trecs = PgView.expand_query("METHOD", records, params, EXPAND, VUSG, SNS, FLDS)
|
|
314
|
+
recs = PgUtil.crosshash(recs, trecs)
|
|
315
|
+
|
|
316
|
+
return PgUtil.joinhash(records, recs, 0, 1)
|
|
317
|
+
|
|
318
|
+
#
|
|
319
|
+
# call main() to start program
|
|
320
|
+
#
|
|
321
|
+
if __name__ == "__main__": main()
|