rda-python-metrics 3.0.8__tar.gz → 3.0.10__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.
- {rda_python_metrics-3.0.8/src/rda_python_metrics.egg-info → rda_python_metrics-3.0.10}/PKG-INFO +1 -1
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/pyproject.toml +1 -1
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcodusage.py +43 -12
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcodusage.usg +14 -3
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillglobususage.py +34 -12
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillrdadb.py +75 -2
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillrdadb.usg +19 -1
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/pg_ipinfo.py +19 -11
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10/src/rda_python_metrics.egg-info}/PKG-INFO +1 -1
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/LICENSE +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/MANIFEST.in +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/README.md +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/setup.cfg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/PgIPInfo.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/PgView.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/__init__.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_awsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_cdgusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_codusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_country.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_endtime.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_globususage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_ipinfo.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_oneorder.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_osdfusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_rdadb.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_tdsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillawsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillawsusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcdgusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcdgusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcountry.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillendtime.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillgdexusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillgdexusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillglobususage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillipinfo.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillipinfo.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filloneorder.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filloneorder.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillosdfusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillosdfusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filltdsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filltdsusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillzenodousage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillzenodousage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/log_arch.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/logarch.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/logarch.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/pg_view.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/pgsyspath.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_allusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_awsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_checkusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_codusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_ordusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_osdfusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_rqstusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_tdsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_webfile.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_webusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewallusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewallusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewawsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewawsusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcheckusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcheckusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcodusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcodusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewordusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewordusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewosdfusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewosdfusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewrqstusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewrqstusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewtdsusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewtdsusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebfile.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebfile.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebusage.py +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebusage.usg +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/SOURCES.txt +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/dependency_links.txt +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/entry_points.txt +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/requires.txt +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/top_level.txt +0 -0
- {rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/tests/test_metrics.py +0 -0
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcodusage.py
RENAMED
|
@@ -28,14 +28,18 @@ class FillCODUsage(PgIPInfo):
|
|
|
28
28
|
self.NDAYS = 0x08 # get COD data usages in recent number of days
|
|
29
29
|
self.FILES = 0x10 # get given file names
|
|
30
30
|
self.GTALL = 0x20 # get all data files of read
|
|
31
|
-
self.
|
|
31
|
+
self.DATES = 0x40 # get COD data usages for given dates
|
|
32
|
+
self.PERID = 0x80 # get COD data usages between two dates
|
|
33
|
+
self.MASKS = (self.MONTH|self.YEARS|self.NDAYS|self.FILES|self.DATES|self.PERID)
|
|
32
34
|
self.USAGE = {
|
|
33
35
|
'OPTION' : 0,
|
|
34
36
|
'PGTBL' : "codusage",
|
|
35
37
|
'WEBLOG' : "/var/log/httpd",
|
|
36
38
|
}
|
|
37
39
|
self.USERS = {} # cache user info for aid
|
|
38
|
-
self.datelimit = ''
|
|
40
|
+
self.datelimit = '' # earliest log entry date to keep
|
|
41
|
+
self.endlimit = '' # latest log entry date to keep
|
|
42
|
+
self.filldates = None # the exact log entry dates to keep, for -d
|
|
39
43
|
self.params = [] # array of input values
|
|
40
44
|
|
|
41
45
|
def read_parameters(self):
|
|
@@ -44,14 +48,18 @@ class FillCODUsage(PgIPInfo):
|
|
|
44
48
|
for arg in argv:
|
|
45
49
|
if arg == "-b":
|
|
46
50
|
self.PGLOG['BCKGRND'] = 1
|
|
47
|
-
elif re.match(r'^-[
|
|
51
|
+
elif re.match(r'^-[adfmNpy]$', arg) and self.USAGE['OPTION'] == 0:
|
|
48
52
|
if arg == "-a":
|
|
49
53
|
self.USAGE['OPTION'] = self.GTALL
|
|
50
54
|
self.params = ['']
|
|
55
|
+
elif arg == "-d":
|
|
56
|
+
self.USAGE['OPTION'] = self.DATES
|
|
51
57
|
elif arg == "-f":
|
|
52
58
|
self.USAGE['OPTION'] = self.FILES
|
|
53
59
|
elif arg == "-m":
|
|
54
60
|
self.USAGE['OPTION'] = self.MONTH
|
|
61
|
+
elif arg == "-p":
|
|
62
|
+
self.USAGE['OPTION'] = self.PERID
|
|
55
63
|
elif arg == "-y":
|
|
56
64
|
self.USAGE['OPTION'] = self.YEARS
|
|
57
65
|
elif arg == "-N":
|
|
@@ -69,17 +77,40 @@ class FillCODUsage(PgIPInfo):
|
|
|
69
77
|
def start_actions(self):
|
|
70
78
|
"""Function to start actions."""
|
|
71
79
|
if self.USAGE['OPTION']&self.NDAYS:
|
|
72
|
-
|
|
73
|
-
self.datelimit
|
|
74
|
-
|
|
75
|
-
self.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
self.datelimit = self.adddate(self.curdate(), 0, 0, -int(self.params[0]))
|
|
81
|
+
self.set_month_params(self.datelimit, self.curdate())
|
|
82
|
+
elif self.USAGE['OPTION']&self.DATES:
|
|
83
|
+
dates = sorted(self.format_date(dt) for dt in self.params)
|
|
84
|
+
self.filldates = set(dates)
|
|
85
|
+
self.set_month_params(dates[0], dates[-1])
|
|
86
|
+
elif self.USAGE['OPTION']&self.PERID:
|
|
87
|
+
self.datelimit = self.format_date(self.params[0])
|
|
88
|
+
self.endlimit = self.format_date(self.params[1]) if len(self.params) > 1 else self.curdate()
|
|
89
|
+
self.set_month_params(self.datelimit, self.endlimit)
|
|
80
90
|
self.fill_cod_usages(self.USAGE['OPTION'], self.params)
|
|
81
91
|
self.pglog(None, self.LOGWRN|self.SNDEML) # send email out if any
|
|
82
92
|
|
|
93
|
+
def set_month_params(self, bdate, edate):
|
|
94
|
+
"""Replace the inputs with the months holding bdate through edate.
|
|
95
|
+
|
|
96
|
+
One COD log file holds a whole month, so a request made in dates is served
|
|
97
|
+
by reading those months and narrowing the entries in skip_log_date().
|
|
98
|
+
"""
|
|
99
|
+
self.USAGE['OPTION'] = self.MONTH
|
|
100
|
+
self.params = []
|
|
101
|
+
curdate = edate
|
|
102
|
+
while curdate >= bdate:
|
|
103
|
+
(year, month, day) = curdate.split('-')
|
|
104
|
+
self.params.append("{}-{}".format(year, month))
|
|
105
|
+
curdate = self.adddate(curdate, 0, 0, -int(day))
|
|
106
|
+
|
|
107
|
+
def skip_log_date(self, cdate):
|
|
108
|
+
"""Tell whether a log entry date falls outside what was asked for."""
|
|
109
|
+
if self.filldates is not None: return cdate not in self.filldates
|
|
110
|
+
if self.datelimit and cdate < self.datelimit: return True
|
|
111
|
+
if self.endlimit and cdate > self.endlimit: return True
|
|
112
|
+
return False
|
|
113
|
+
|
|
83
114
|
def fill_cod_usages(self, option, inputs):
|
|
84
115
|
"""Fill COD usages into table dssdb.codusage of DSS PostgreSQL database from cod access logs."""
|
|
85
116
|
cntall = cntadd = 0
|
|
@@ -128,7 +159,7 @@ class FillCODUsage(PgIPInfo):
|
|
|
128
159
|
cntadd += self.add_usage_records(records, cdate)
|
|
129
160
|
records = {}
|
|
130
161
|
pdate = cdate
|
|
131
|
-
if self.
|
|
162
|
+
if self.skip_log_date(cdate): continue
|
|
132
163
|
if aid in records:
|
|
133
164
|
records[aid]['size'] += size
|
|
134
165
|
records[aid]['count'] += 1
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcodusage.usg
RENAMED
|
@@ -5,13 +5,18 @@
|
|
|
5
5
|
into the 'codusage' table in PostgreSQL database 'rdadb'.
|
|
6
6
|
|
|
7
7
|
USAGE:
|
|
8
|
-
fillcodusage [-b] (-a | -f LogFileNames | -m MonthList |
|
|
9
|
-
-N NumberDays | -y YearList)
|
|
8
|
+
fillcodusage [-b] (-a | -d LogEntryDates | -f LogFileNames | -m MonthList |
|
|
9
|
+
-N NumberDays | -p BeginDate [EndDate] | -y YearList)
|
|
10
10
|
|
|
11
|
-
OPTIONS (choose exactly one of -a, -f, -m, -N, or -y):
|
|
11
|
+
OPTIONS (choose exactly one of -a, -d, -f, -m, -N, -p, or -y):
|
|
12
12
|
|
|
13
13
|
-a Process all available log files.
|
|
14
14
|
|
|
15
|
+
-d LogEntryDates
|
|
16
|
+
Process the given dates. Date format: YYYY-MM-DD (e.g. 2024-01-15).
|
|
17
|
+
A log file holds a whole month, so the months holding these dates are
|
|
18
|
+
read and only entries falling on the given dates are recorded.
|
|
19
|
+
|
|
15
20
|
-f LogFileNames
|
|
16
21
|
Process the given log file names directly.
|
|
17
22
|
|
|
@@ -22,6 +27,11 @@
|
|
|
22
27
|
-N NumberDays
|
|
23
28
|
Process log files covering the most recent NumberDays days.
|
|
24
29
|
|
|
30
|
+
-p BeginDate [EndDate]
|
|
31
|
+
Process log entries between BeginDate and EndDate, inclusive.
|
|
32
|
+
EndDate defaults to today if omitted. As with -d, whole months are
|
|
33
|
+
read and the entries outside the range are skipped.
|
|
34
|
+
|
|
25
35
|
-y YearList
|
|
26
36
|
Process log files for the given years.
|
|
27
37
|
Year format: YYYY (e.g. 2024).
|
|
@@ -30,3 +40,4 @@
|
|
|
30
40
|
|
|
31
41
|
EXAMPLE:
|
|
32
42
|
fillcodusage -m 2024-01 2024-02
|
|
43
|
+
fillcodusage -d 2024-01-15 2024-02-03
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillglobususage.py
RENAMED
|
@@ -28,9 +28,11 @@ class FillGlobusUsage(PgIPInfo, PgSplit, PgFile):
|
|
|
28
28
|
'PGTBL' : "wusage",
|
|
29
29
|
'GBSDIR' : self.PGLOG["GDEXWORK"] + "/logs/gridftp/",
|
|
30
30
|
'GBSLOG' : "access_log_gridftp0{}_{}",
|
|
31
|
+
'GBSDAYS' : 7, # a log file is named for its first date and holds a week
|
|
31
32
|
}
|
|
32
33
|
self.logfiles = []
|
|
33
34
|
self.datelimits = [None, None]
|
|
35
|
+
self.filldates = None # the exact log entry dates to keep, for -d
|
|
34
36
|
self.params = [] # array of input values
|
|
35
37
|
self.option = self.cmdstr = None
|
|
36
38
|
|
|
@@ -73,11 +75,12 @@ class FillGlobusUsage(PgIPInfo, PgSplit, PgFile):
|
|
|
73
75
|
if self.option == 'f':
|
|
74
76
|
self.logfiles = self.params
|
|
75
77
|
elif self.option == 'd':
|
|
76
|
-
for
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
# a log file is named for its first date and holds a week, so the file
|
|
79
|
+
# covering a date is found by looking back, not by its own name
|
|
80
|
+
self.filldates = {self.format_date(pdate) for pdate in self.params}
|
|
81
|
+
for pdate in sorted(self.filldates):
|
|
82
|
+
for fname in self.get_covering_logfiles(pdate):
|
|
83
|
+
if fname not in self.logfiles: self.logfiles.append(fname)
|
|
81
84
|
else:
|
|
82
85
|
if self.option == 'N':
|
|
83
86
|
edate = self.curdate()
|
|
@@ -88,13 +91,33 @@ class FillGlobusUsage(PgIPInfo, PgSplit, PgFile):
|
|
|
88
91
|
edate = self.datelimits[1] = self.params[1]
|
|
89
92
|
else:
|
|
90
93
|
edate = self.curdate()
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
# start a week early so the file covering the first dates is picked up;
|
|
95
|
+
# its entries before datelimits[0] are skipped as they are read
|
|
96
|
+
gdate = self.adddate(pdate, 0, 0, -self.USAGE['GBSDAYS'])
|
|
97
|
+
while gdate <= edate:
|
|
98
|
+
fdate = self.format_date(gdate, 'MMDDYYYY')
|
|
93
99
|
fname = self.USAGE['GBSLOG'].format('?', fdate)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
for gname in sorted(glob.glob(fname)):
|
|
101
|
+
if gname not in self.logfiles: self.logfiles.append(gname)
|
|
102
|
+
gdate = self.adddate(gdate, 0, 0, 1)
|
|
97
103
|
|
|
104
|
+
def get_covering_logfiles(self, pdate):
|
|
105
|
+
"""Get the log files holding pdate, searching back over a week of names."""
|
|
106
|
+
gdate = pdate
|
|
107
|
+
for i in range(self.USAGE['GBSDAYS']):
|
|
108
|
+
fname = self.USAGE['GBSLOG'].format('?', self.format_date(gdate, 'MMDDYYYY'))
|
|
109
|
+
fnames = sorted(glob.glob(fname))
|
|
110
|
+
if fnames: return fnames
|
|
111
|
+
gdate = self.adddate(gdate, 0, 0, -1)
|
|
112
|
+
return []
|
|
113
|
+
|
|
114
|
+
def skip_log_date(self, date):
|
|
115
|
+
"""Tell whether a log entry date falls outside what was asked for."""
|
|
116
|
+
if self.filldates is not None: return date not in self.filldates
|
|
117
|
+
if self.datelimits[0] and date < self.datelimits[0]: return True
|
|
118
|
+
if self.datelimits[1] and date > self.datelimits[1]: return True
|
|
119
|
+
return False
|
|
120
|
+
|
|
98
121
|
def fill_globus_usages(self):
|
|
99
122
|
"""Fill Globus usages into table dssdb.globususage of DSS PostgreSQL database from globus access logs."""
|
|
100
123
|
cntall = addall = 0
|
|
@@ -130,8 +153,7 @@ class FillGlobusUsage(PgIPInfo, PgSplit, PgFile):
|
|
|
130
153
|
sline = ms.group(7)
|
|
131
154
|
engine = ms.group(8)
|
|
132
155
|
(year, quarter, date, time) = self.get_record_date_time(ms.group(2))
|
|
133
|
-
if self.
|
|
134
|
-
if self.datelimits[1] and date > self.datelimits[1]: continue
|
|
156
|
+
if self.skip_log_date(date): continue
|
|
135
157
|
locflag = 'O' if re.match(r'^https://stratus\.', sline) else 'G'
|
|
136
158
|
idx = wfile.find('?')
|
|
137
159
|
if idx > -1: wfile = wfile[:idx]
|
|
@@ -32,15 +32,26 @@ class FillRDADB(PgUtil, PgDBI):
|
|
|
32
32
|
'OPTION' : 0,
|
|
33
33
|
'OPTVAL' : '',
|
|
34
34
|
'DOMAIL' : 1,
|
|
35
|
-
'BCKGRND' : ''
|
|
35
|
+
'BCKGRND' : '',
|
|
36
|
+
'BACKDAYS' : 0 # days to reach back for missed dates, set by -B
|
|
37
|
+
}
|
|
38
|
+
# the usage table and its date field, per command to reprocess with -d
|
|
39
|
+
self.BACKFILL = {
|
|
40
|
+
'fillosdfusage' : ('osdfusage', 'date'),
|
|
41
|
+
'fillawsusage' : ('awsusage', 'date'),
|
|
42
|
+
'fillglobususage' : ('wusage', 'date_read'),
|
|
43
|
+
'fillcodusage' : ('codusage', 'date')
|
|
36
44
|
}
|
|
37
45
|
self.params = [] # array of input values
|
|
38
46
|
|
|
39
47
|
def read_parameters(self):
|
|
40
48
|
"""Function to read parameters."""
|
|
41
49
|
argv = sys.argv[1:]
|
|
50
|
+
backopt = 0 # the value after -B is the number of days to reach back
|
|
42
51
|
for arg in argv:
|
|
43
|
-
if arg == "-
|
|
52
|
+
if arg == "-B":
|
|
53
|
+
backopt = 1
|
|
54
|
+
elif arg == "-b":
|
|
44
55
|
self.PGLOG['BCKGRND'] = "-b"
|
|
45
56
|
self.RDADB['BCKGRND'] = " -b"
|
|
46
57
|
elif arg == "-n":
|
|
@@ -60,12 +71,20 @@ class FillRDADB(PgUtil, PgDBI):
|
|
|
60
71
|
self.RDADB['OPTION'] |= self.NDAYS
|
|
61
72
|
elif re.match(r'^-.*', arg):
|
|
62
73
|
self.pglog(arg + ": Invalid Option", self.LGWNEX)
|
|
74
|
+
elif backopt:
|
|
75
|
+
if not re.match(r'^\d+$', arg):
|
|
76
|
+
self.pglog(arg + ": Number of days back must be a whole number", self.LGWNEX)
|
|
77
|
+
self.RDADB['BACKDAYS'] = int(arg)
|
|
78
|
+
backopt = 0
|
|
63
79
|
elif self.RDADB['OPTION']&self.MASKS:
|
|
64
80
|
self.params.append(arg)
|
|
65
81
|
else:
|
|
66
82
|
self.pglog(arg + ": Invalid Parameter", self.LGWNEX)
|
|
83
|
+
if backopt: self.pglog("-B: Miss number of days to reach back", self.LGWNEX)
|
|
67
84
|
if not self.RDADB['OPTION'] or (self.RDADB['OPTION']&self.MASKS and not self.params):
|
|
68
85
|
self.show_usage('fillrdadb')
|
|
86
|
+
if self.RDADB['BACKDAYS'] and not self.RDADB['OPTION']&self.NDAYS:
|
|
87
|
+
self.pglog("-B: Ignored, reaching back for missed dates needs -N", self.LOGWRN)
|
|
69
88
|
self.cmdlog("fillrdadb {}".format(' '.join(argv)))
|
|
70
89
|
|
|
71
90
|
def start_actions(self):
|
|
@@ -88,9 +107,63 @@ class FillRDADB(PgUtil, PgDBI):
|
|
|
88
107
|
self.pgsystem("fillawsusage {} {}".format(self.RDADB['BCKGRND'], filecond), self.LGWNEM, 5)
|
|
89
108
|
# fill available OSDF web data usages
|
|
90
109
|
self.pgsystem("fillosdfusage {} {}".format(self.RDADB['BCKGRND'], filecond), self.LGWNEM, 5)
|
|
110
|
+
# the -N window is the only thing that reaches a log file again, so one
|
|
111
|
+
# published after its date leaves the window is never asked for; -B catches those
|
|
112
|
+
if self.RDADB['BACKDAYS'] and self.RDADB['OPTION']&self.NDAYS:
|
|
113
|
+
self.backfill_missed_dates(int(self.params[0]))
|
|
91
114
|
if self.RDADB['DOMAIL']: self.send_email_notice()
|
|
92
115
|
self.pglog("End Filling RDADB info at {}".format(self.current_datetime()), self.LGWNEM)
|
|
93
116
|
|
|
117
|
+
def backfill_missed_dates(self, ndays):
|
|
118
|
+
"""Reprocess the dates before the -N window that still hold no usage record.
|
|
119
|
+
|
|
120
|
+
Only runs when -B gave a number of days to reach back. A log file is
|
|
121
|
+
sometimes published after its date has slid out of the -N window, and
|
|
122
|
+
nothing fetches it again, so the date stays empty however often the job
|
|
123
|
+
runs. Asking each usage table which dates it is missing keeps those dates
|
|
124
|
+
being retried until their log shows up, as far back as -B allows.
|
|
125
|
+
|
|
126
|
+
A date whose log holds no usable entry simply keeps being offered until it
|
|
127
|
+
ages out past BACKDAYS. That is deliberate: the obvious alternative, taking
|
|
128
|
+
an already processed log as proof of coverage, would silently write off the
|
|
129
|
+
dates left empty by a run that died partway.
|
|
130
|
+
"""
|
|
131
|
+
edate = self.adddate(self.curdate(), 0, 0, -ndays)
|
|
132
|
+
bdate = self.adddate(self.curdate(), 0, 0, -self.RDADB['BACKDAYS'])
|
|
133
|
+
if bdate >= edate: return
|
|
134
|
+
for cmd in self.BACKFILL:
|
|
135
|
+
(tbname, datefld) = self.BACKFILL[cmd]
|
|
136
|
+
dates = self.get_unfilled_dates(tbname, datefld, bdate, edate)
|
|
137
|
+
if not dates: continue
|
|
138
|
+
self.pglog("{}: {} date(s) between {} and {} hold no usage, reprocessing".format(
|
|
139
|
+
cmd, len(dates), bdate, edate), self.LOGWRN)
|
|
140
|
+
self.pgsystem("{} {} -d {}".format(cmd, self.RDADB['BCKGRND'], ' '.join(dates)), self.LGWNEM, 5)
|
|
141
|
+
|
|
142
|
+
def get_unfilled_dates(self, tbname, datefld, bdate, edate):
|
|
143
|
+
"""Get the dates in [bdate, edate) holding no record in a usage table."""
|
|
144
|
+
filled = set()
|
|
145
|
+
for table in self.get_usage_tables(tbname, bdate, edate):
|
|
146
|
+
cnd = "{} >= '{}' AND {} < '{}'".format(datefld, bdate, datefld, edate)
|
|
147
|
+
pgrecs = self.pgmget(table, 'DISTINCT ' + datefld, cnd, self.LOGWRN)
|
|
148
|
+
if pgrecs and datefld in pgrecs:
|
|
149
|
+
filled.update(str(d) for d in pgrecs[datefld])
|
|
150
|
+
dates = []
|
|
151
|
+
pdate = bdate
|
|
152
|
+
while pdate < edate:
|
|
153
|
+
if pdate not in filled: dates.append(pdate)
|
|
154
|
+
pdate = self.adddate(pdate, 0, 0, 1)
|
|
155
|
+
return dates
|
|
156
|
+
|
|
157
|
+
def get_usage_tables(self, tbname, bdate, edate):
|
|
158
|
+
"""Get the existing table names for a usage table, one per year if split."""
|
|
159
|
+
tables = []
|
|
160
|
+
for year in range(int(bdate[0:4]), int(edate[0:4]) + 1):
|
|
161
|
+
table = "{}_{}".format(tbname, year)
|
|
162
|
+
if self.pgget('information_schema.tables', 'table_name',
|
|
163
|
+
"table_name = '{}'".format(table), self.LOGWRN):
|
|
164
|
+
tables.append(table)
|
|
165
|
+
return tables if tables else [tbname]
|
|
166
|
+
|
|
94
167
|
def clean_unused_files(self):
|
|
95
168
|
"""Clean unused MSS and Web files."""
|
|
96
169
|
self.pglog("Check and clean deleted Web files that never been used at {}".format(self.current_datetime()), self.LOGWRN)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
fillcodusage, fillglobususage, fillawsusage, fillosdfusage.
|
|
7
7
|
|
|
8
8
|
USAGE:
|
|
9
|
-
fillrdadb [-b] [-n]
|
|
9
|
+
fillrdadb [-b] [-n] [-B NumberDaysBack]
|
|
10
10
|
(-c | -d DateList | -m MonthList | -N NumberDays | -y YearList)
|
|
11
11
|
|
|
12
12
|
OPTIONS (choose exactly one of -c, -d, -m, -N, or -y):
|
|
@@ -32,5 +32,23 @@
|
|
|
32
32
|
|
|
33
33
|
-n Do not send email notification when filling is complete.
|
|
34
34
|
|
|
35
|
+
-B NumberDaysBack
|
|
36
|
+
After the -N pass, reprocess any date between NumberDaysBack days ago
|
|
37
|
+
and the start of the -N window that still holds no usage record.
|
|
38
|
+
|
|
39
|
+
A log file is sometimes published after its date has slid out of the
|
|
40
|
+
-N window, and nothing reaches for it again, so that date stays empty
|
|
41
|
+
however often the job runs. Each usage table is asked which dates it
|
|
42
|
+
is missing, and only those dates are reprocessed, so a late log is
|
|
43
|
+
picked up however late it arrives.
|
|
44
|
+
|
|
45
|
+
A date whose log holds no usable entry keeps being offered until it
|
|
46
|
+
ages past NumberDaysBack. That is deliberate: treating an already
|
|
47
|
+
processed log as proof of coverage would silently write off the dates
|
|
48
|
+
left empty by a run that died partway.
|
|
49
|
+
|
|
50
|
+
Needs -N, and is ignored with a warning otherwise.
|
|
51
|
+
|
|
35
52
|
EXAMPLE:
|
|
36
53
|
fillrdadb -N 7
|
|
54
|
+
fillrdadb -N 14 -B 60 # weekly fill, reaching back two months
|
|
@@ -102,7 +102,7 @@ class PgIPInfo(PgUtil, PgDBI):
|
|
|
102
102
|
|
|
103
103
|
def get_country_record_code(self, cname, kname = None):
|
|
104
104
|
"""Get country code from name."""
|
|
105
|
-
name = cname
|
|
105
|
+
name = cname.get(kname) if kname else cname
|
|
106
106
|
name = name.replace(' ', '.').upper() if name else 'UNITED.STATES'
|
|
107
107
|
if name == 'CHINA': name = 'P.R.CHINA'
|
|
108
108
|
return name
|
|
@@ -241,16 +241,24 @@ class PgIPInfo(PgUtil, PgDBI):
|
|
|
241
241
|
self.IPRECS[ip] = self.pgget('ipinfo', '*', f"ip = '{self.GIP}'", self.LGEREX)
|
|
242
242
|
return self.IPRECS[ip]
|
|
243
243
|
record = {'ip' : ip, 'stat_flag' : 'A', 'hostname' : ip, 'org_type' : '-'}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
244
|
+
try:
|
|
245
|
+
self.get_ip_hostname(ip, iprec, record)
|
|
246
|
+
# latitude and longitude are derived from 'loc', which a sparse ipinfo
|
|
247
|
+
# answer leaves out altogether, as it does timezone and country name
|
|
248
|
+
record['lat'] = float(iprec['latitude']) if iprec.get('latitude') else 0
|
|
249
|
+
record['lon'] = float(iprec['longitude']) if iprec.get('longitude') else 0
|
|
250
|
+
if 'org' in iprec: record['org_name'] = iprec['org']
|
|
251
|
+
record['country'] = self.get_country_record_code(iprec, 'country_name')
|
|
252
|
+
record['region'] = self.convert_chars(iprec['region']) if 'region' in iprec else None
|
|
253
|
+
if 'city' in iprec: record['city'] = self.convert_chars(iprec['city'])
|
|
254
|
+
if 'postal' in iprec: record['postal'] = iprec['postal']
|
|
255
|
+
record['timezone'] = iprec.get('timezone')
|
|
256
|
+
record['ipinfo'] = json.dumps(iprec)
|
|
257
|
+
except (KeyError, TypeError, ValueError) as e:
|
|
258
|
+
# an ipinfo answer shaped differently again must not end the whole run;
|
|
259
|
+
# returning None lets set_ipinfo() fall back to the local geoip2 database
|
|
260
|
+
self.pglog("ipinfo: {} - unusable record ({}: {}), use geoip2".format(ip, type(e).__name__, e), self.LOGWRN)
|
|
261
|
+
return None
|
|
254
262
|
return record
|
|
255
263
|
|
|
256
264
|
def set_geoip2_database(self):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_awsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_cdgusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_codusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_country.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_endtime.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_globususage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_ipinfo.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_oneorder.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_osdfusage.py
RENAMED
|
File without changes
|
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fill_tdsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillawsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillawsusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcdgusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcdgusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillcountry.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillendtime.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillgdexusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillgdexusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillglobususage.usg
RENAMED
|
File without changes
|
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillipinfo.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filloneorder.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filloneorder.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillosdfusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillosdfusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filltdsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/filltdsusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillzenodousage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/fillzenodousage.usg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_allusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_awsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_checkusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_codusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_ordusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_osdfusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_rqstusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_tdsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_webfile.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/view_webusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewallusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewallusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewawsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewawsusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcheckusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcheckusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcodusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewcodusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewordusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewordusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewosdfusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewosdfusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewrqstusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewrqstusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewtdsusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewtdsusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebfile.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebfile.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebusage.py
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics/viewwebusage.usg
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/requires.txt
RENAMED
|
File without changes
|
{rda_python_metrics-3.0.8 → rda_python_metrics-3.0.10}/src/rda_python_metrics.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|