rda-python-metrics 2.0.5__py3-none-any.whl → 3.0.2__py3-none-any.whl

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.
Files changed (81) hide show
  1. rda_python_metrics/PgView.py +3 -3
  2. rda_python_metrics/__init__.py +28 -0
  3. rda_python_metrics/fill_awsusage.py +1 -1
  4. rda_python_metrics/fill_cdgusage.py +2 -2
  5. rda_python_metrics/fill_globususage.py +1 -1
  6. rda_python_metrics/fill_osdfusage.py +1 -1
  7. rda_python_metrics/fill_rdadb.py +1 -1
  8. rda_python_metrics/fill_tdsusage.py +1 -1
  9. rda_python_metrics/fillawsusage.py +11 -9
  10. rda_python_metrics/fillawsusage.usg +20 -9
  11. rda_python_metrics/fillcdgusage.py +17 -15
  12. rda_python_metrics/fillcdgusage.usg +25 -10
  13. rda_python_metrics/fillcodusage.py +11 -9
  14. rda_python_metrics/fillcodusage.usg +22 -11
  15. rda_python_metrics/fillcountry.py +8 -6
  16. rda_python_metrics/fillendtime.py +7 -5
  17. rda_python_metrics/fillgdexusage.py +972 -979
  18. rda_python_metrics/fillgdexusage.usg +25 -10
  19. rda_python_metrics/fillglobususage.py +14 -12
  20. rda_python_metrics/fillglobususage.usg +23 -11
  21. rda_python_metrics/fillipinfo.py +15 -15
  22. rda_python_metrics/fillipinfo.usg +29 -11
  23. rda_python_metrics/filloneorder.py +9 -7
  24. rda_python_metrics/filloneorder.usg +38 -40
  25. rda_python_metrics/fillosdfusage.py +11 -9
  26. rda_python_metrics/fillosdfusage.usg +20 -10
  27. rda_python_metrics/fillrdadb.py +9 -7
  28. rda_python_metrics/fillrdadb.usg +24 -20
  29. rda_python_metrics/filltdsusage.py +42 -39
  30. rda_python_metrics/filltdsusage.usg +20 -9
  31. rda_python_metrics/filluser.py +8 -6
  32. rda_python_metrics/filluser.usg +16 -8
  33. rda_python_metrics/fillzenodousage.py +382 -393
  34. rda_python_metrics/log_arch.py +2 -2
  35. rda_python_metrics/logarch.py +5 -2
  36. rda_python_metrics/logarch.usg +22 -17
  37. rda_python_metrics/pg_ipinfo.py +29 -28
  38. rda_python_metrics/pg_person.py +1 -1
  39. rda_python_metrics/pg_username.py +1 -1
  40. rda_python_metrics/pg_view.py +25 -30
  41. rda_python_metrics/pgperson.py +4 -4
  42. rda_python_metrics/pgsyspath.py +1 -1
  43. rda_python_metrics/pgusername.py +2 -2
  44. rda_python_metrics/view_allusage.py +9 -9
  45. rda_python_metrics/view_awsusage.py +13 -13
  46. rda_python_metrics/view_checkusage.py +10 -10
  47. rda_python_metrics/view_codusage.py +8 -8
  48. rda_python_metrics/view_ordusage.py +14 -14
  49. rda_python_metrics/view_osdfusage.py +13 -13
  50. rda_python_metrics/view_rqstusage.py +9 -9
  51. rda_python_metrics/view_tdsusage.py +13 -13
  52. rda_python_metrics/view_webfile.py +11 -13
  53. rda_python_metrics/view_webusage.py +11 -11
  54. rda_python_metrics/viewallusage.py +21 -16
  55. rda_python_metrics/viewallusage.usg +149 -214
  56. rda_python_metrics/viewawsusage.py +25 -20
  57. rda_python_metrics/viewawsusage.usg +122 -189
  58. rda_python_metrics/viewcheckusage.py +18 -17
  59. rda_python_metrics/viewcheckusage.usg +104 -158
  60. rda_python_metrics/viewcodusage.py +160 -155
  61. rda_python_metrics/viewcodusage.usg +122 -186
  62. rda_python_metrics/viewordusage.py +21 -20
  63. rda_python_metrics/viewordusage.usg +130 -222
  64. rda_python_metrics/viewosdfusage.py +27 -22
  65. rda_python_metrics/viewosdfusage.usg +122 -189
  66. rda_python_metrics/viewrqstusage.py +24 -19
  67. rda_python_metrics/viewrqstusage.usg +141 -216
  68. rda_python_metrics/viewtdsusage.py +25 -20
  69. rda_python_metrics/viewtdsusage.usg +126 -193
  70. rda_python_metrics/viewwebfile.py +17 -18
  71. rda_python_metrics/viewwebfile.usg +142 -211
  72. rda_python_metrics/viewwebusage.py +19 -18
  73. rda_python_metrics/viewwebusage.usg +140 -210
  74. rda_python_metrics-3.0.2.dist-info/METADATA +185 -0
  75. rda_python_metrics-3.0.2.dist-info/RECORD +86 -0
  76. {rda_python_metrics-2.0.5.dist-info → rda_python_metrics-3.0.2.dist-info}/WHEEL +1 -1
  77. {rda_python_metrics-2.0.5.dist-info → rda_python_metrics-3.0.2.dist-info}/entry_points.txt +1 -1
  78. rda_python_metrics-2.0.5.dist-info/METADATA +0 -23
  79. rda_python_metrics-2.0.5.dist-info/RECORD +0 -86
  80. {rda_python_metrics-2.0.5.dist-info → rda_python_metrics-3.0.2.dist-info}/licenses/LICENSE +0 -0
  81. {rda_python_metrics-2.0.5.dist-info → rda_python_metrics-3.0.2.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  # Date : 09/24/2020
7
7
  # 2025-03-27 transferred to package rda_python_metrics from
8
8
  # https://github.com/NCAR/rda-database.git
9
- # Purpose : python library module to help rountinely updates of new data
9
+ # Purpose : python library module to help routinely updates of new data
10
10
  # for one or multiple datasets
11
11
  #
12
12
  # Github : https://github.com/NCAR/rda-python-metrics.git
@@ -32,7 +32,7 @@ def simple_output(params, flds, records, totals = None):
32
32
  sep = params['L'][0] if 'L' in params else ' '
33
33
  slen = len(sep)
34
34
 
35
- # get total line length, dynamically evaluating column lengthes if column 4 in %FLDS is zero
35
+ # get total line length, dynamically evaluating column lengths if column 4 in %FLDS is zero
36
36
  rcnt = linelen = 0
37
37
  if 'A' in params: rcnt = int(params['A'][0])
38
38
  for i in range(ccnt):
@@ -390,7 +390,7 @@ def join_query_tables(tblname, tablenames = '', joins = '', tbljoin = ''):
390
390
  return (tablenames, joins)
391
391
 
392
392
  #
393
- # expand reocrds via query action
393
+ # expand records via query action
394
394
  #
395
395
  def expand_query(expid, records, params, expand, vusg = None, sns = None, flds = None):
396
396
 
@@ -1 +1,29 @@
1
+ """rda_python_metrics: RDA metrics, usage, and accounting utility package.
1
2
 
3
+ This package exposes two parallel APIs:
4
+
5
+ 1. Legacy module-based API (back-compat). Import the capitalized
6
+ submodules and call their module-level functions, e.g.::
7
+
8
+ from rda_python_metrics import PgIPInfo, PgView
9
+
10
+ 2. Class-based API (preferred for new code). Import the class from the
11
+ lower-case module and either instantiate or subclass it, e.g.::
12
+
13
+ from rda_python_metrics.pg_ipinfo import PgIPInfo
14
+ from rda_python_metrics.pg_view import PgView
15
+
16
+ The legacy submodules are eagerly imported below so that
17
+ ``from rda_python_metrics import PgIPInfo`` continues to return the
18
+ module object that existing callers expect.
19
+ """
20
+
21
+ from . import PgIPInfo, PgView
22
+
23
+ __version__ = "2.0.6"
24
+
25
+ __all__ = [
26
+ "PgIPInfo",
27
+ "PgView",
28
+ "__version__",
29
+ ]
@@ -10,7 +10,7 @@
10
10
  # Purpose : python program to retrieve info from AWS logs
11
11
  # and fill table wusages in PgSQL database dssdb.
12
12
  #
13
- # Github : https://github.com/NCAR/rda-pythn-metrics.git
13
+ # Github : https://github.com/NCAR/rda-python-metrics.git
14
14
  #
15
15
  ###############################################################################
16
16
  #
@@ -6,7 +6,7 @@
6
6
  # Author : Zaihua Ji, zji@ucar.edu
7
7
  # Date : 2025-04-14
8
8
  # Purpose : python program to retrieve info from GDEX Postgres database for GDS
9
- # file accesses and backup fill table tdsusage in PostgreSQL database dssdb.
9
+ # file accesses and backup fill table tdsusage in PostgreSQL database rdadb.
10
10
  #
11
11
  # Github : https://github.com/NCAR/rda-python-metrics.git
12
12
  #
@@ -173,7 +173,7 @@ def get_dataset_ids(dsnames):
173
173
  return dsids
174
174
 
175
175
  #
176
- # get cdgids recursivley
176
+ # get cdgids recursively
177
177
  #
178
178
  def recursive_dataset_ids(pcdgid, cdgids):
179
179
 
@@ -10,7 +10,7 @@
10
10
  # Purpose : python program to retrieve info from Globus logs
11
11
  # and fill table wusages in PgSQL database dssdb.
12
12
  #
13
- # Github : https://github.com/NCAR/rda-pythn-metrics.git
13
+ # Github : https://github.com/NCAR/rda-python-metrics.git
14
14
  #
15
15
  ###############################################################################
16
16
  #
@@ -8,7 +8,7 @@
8
8
  # Purpose : python program to retrieve info from weekly OSDF logs
9
9
  # and fill table wusages in PgSQL database dssdb.
10
10
  #
11
- # Github : https://github.com/NCAR/rda-pythn-metrics.git
11
+ # Github : https://github.com/NCAR/rda-python-metrics.git
12
12
  #
13
13
  ###############################################################################
14
14
  #
@@ -10,7 +10,7 @@
10
10
  # Purpose : python program to retrieve info from data logs, and fill tables
11
11
  # in PostgreSQL database.schema rdadb.dssdb
12
12
  #
13
- # Github : https://github.com/NCAR/rda-pythn-metrics.git
13
+ # Github : https://github.com/NCAR/rda-python-metrics.git
14
14
  #
15
15
  ###############################################################################
16
16
  #
@@ -8,7 +8,7 @@
8
8
  # 2025-03-26 transferred to package rda_python_metrics from
9
9
  # https://github.com/NCAR/rda-database.git
10
10
  # Purpose : python program to retrieve info from TDS logs
11
- # and fill table tdsusage in PostgreSQL database dssdb.
11
+ # and fill table tdsusage in PostgreSQL database rdadb.
12
12
  #
13
13
  # Github : https://github.com/NCAR/rda-python-metrics.git
14
14
  #
@@ -8,7 +8,7 @@
8
8
  # 2025-12-16 converted to class FillAWSUsage
9
9
  # Purpose : python program to retrieve info from AWS logs
10
10
  # and fill table wusages in PgSQL database dssdb.
11
- # Github : https://github.com/NCAR/rda-pythn-metrics.git
11
+ # Github : https://github.com/NCAR/rda-python-metrics.git
12
12
  ###############################################################################
13
13
  import sys
14
14
  import re
@@ -19,6 +19,8 @@ from .pg_ipinfo import PgIPInfo
19
19
 
20
20
  class FillAWSUsage(PgIPInfo, PgFile):
21
21
 
22
+ """Retrieve info from AWS logs and fill table wusage in PostgreSQL database rdadb."""
23
+
22
24
  def __init__(self):
23
25
  super().__init__()
24
26
  self.USAGE = {
@@ -31,8 +33,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
31
33
  self.option = self.cmdstr = None
32
34
  self.params = [] # array of input values
33
35
 
34
- # function to read parameters
35
36
  def read_parameters(self):
37
+ """Function to read parameters."""
36
38
  argv = sys.argv[1:]
37
39
  for arg in argv:
38
40
  ms = re.match(r'^-(b|d|p|N)$', arg)
@@ -55,8 +57,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
55
57
  self.cmdstr = "fillawsusage {}".format(' '.join(argv))
56
58
  self.cmdlog(self.cmdstr)
57
59
 
58
- # function to start actions
59
60
  def start_actions(self):
61
+ """Function to start actions."""
60
62
  self.change_local_directory(self.USAGE['AWSDIR'])
61
63
  filenames = self.get_log_file_names()
62
64
  if filenames:
@@ -65,8 +67,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
65
67
  self.pglog("No log file found for given command: " + self.cmdstr, self.LOGWRN)
66
68
  self.pglog(None, self.LOGWRN)
67
69
 
68
- # get the log file dates
69
70
  def get_log_file_names(self):
71
+ """Get the log file dates."""
70
72
  filenames = {}
71
73
  if self.option == 'd':
72
74
  for dt in self.params:
@@ -93,8 +95,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
93
95
  pdate = self.adddate(pdate, 0, 0, 1)
94
96
  return filenames
95
97
 
96
- # Fill AWS usages into table dssdb.awsusage of DSS PgSQL database from aws access logs
97
98
  def fill_aws_usages(self, filenames):
99
+ """Fill AWS usages into table dssdb.awsusage of DSS PgSQL database from aws access logs."""
98
100
  year = cntall = addall = 0
99
101
  for pdate in filenames:
100
102
  fnames = filenames[pdate]
@@ -147,8 +149,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
147
149
  if addall > cntadd:
148
150
  self.pglog("{} AWS usage records added for {} entries at {}".format(addall, cntall, self.current_datetime()), self.LOGWRN)
149
151
 
150
- # get date and time from record
151
152
  def get_record_date_time(self, ctime):
153
+ """Get date and time from record."""
152
154
  ms = re.search(r'^(\d+)/(\w+)/(\d+):(\d+:\d+:\d+)$', ctime)
153
155
  if ms:
154
156
  d = int(ms.group(1))
@@ -160,8 +162,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
160
162
  else:
161
163
  self.pglog(ctime + ": Invalid date/time format", self.LGEREX)
162
164
 
163
- # add usage records for year
164
165
  def add_usage_records(self, records, year):
166
+ """Add usage records for year."""
165
167
  cnt = 0
166
168
  for key in records:
167
169
  record = records[key]
@@ -171,8 +173,8 @@ class FillAWSUsage(PgIPInfo, PgFile):
171
173
  cnt += self.pgadd(self.USAGE['PGTBL'], record, self.LOGWRN)
172
174
  return cnt
173
175
 
174
- # add record to allusage tables
175
176
  def add_to_allusage(self, year, pgrec):
177
+ """Add record to allusage tables."""
176
178
  record = {'source' : 'A'}
177
179
  flds = ['ip', 'dsid', 'date', 'time', 'quarter', 'size', 'method',
178
180
  'org_type', 'country', 'region', 'email']
@@ -180,7 +182,7 @@ class FillAWSUsage(PgIPInfo, PgFile):
180
182
  record[fld] = pgrec[fld]
181
183
  return self.add_yearly_allusage(year, record)
182
184
 
183
- # main function to excecute this script
185
+ # main function to execute this script
184
186
  def main():
185
187
  object = FillAWSUsage()
186
188
  object.read_parameters()
@@ -1,16 +1,27 @@
1
1
 
2
- Retrieves usage information from AWS Server logs under directory
3
- ../rda/transer/AWSera5log/ to fill table 'awsusage' in database 'rdadb'.
2
+ fillawsusage - Fill table 'awsusage' from AWS Server log files.
4
3
 
5
- Usage: fillawsusage [-b] [-d LogFileDates] [-N NumberDay] [-p BeginDate [Enddate]]
4
+ Reads AWS access logs from /gpfs/fs1/collections/rda/transer/AWSera5log/
5
+ and inserts usage records into the 'awsusage' table in PostgreSQL
6
+ database 'rdadb'.
6
7
 
7
- select option, -d, -N or -p to run this application.
8
+ USAGE:
9
+ fillawsusage [-b] (-d LogFileDates | -N NumberDays | -p BeginDate [EndDate])
8
10
 
9
- - Option -b, log process information into logfile only;
11
+ OPTIONS (choose exactly one of -d, -N, or -p):
10
12
 
11
- - Option -d, retrieve usage info from given log file dates;
13
+ -d LogFileDates
14
+ Process log files for the given dates.
15
+ Date format: YYYY-MM-DD (e.g. 2024-01-15).
12
16
 
13
- - Option -N, retrieve usage info in recent NumberDay days;
17
+ -N NumberDays
18
+ Process log files covering the most recent NumberDays days.
14
19
 
15
- - Option -p, retrieve usage info between given period. For missing EndDate,
16
- it defaults to the current date.
20
+ -p BeginDate [EndDate]
21
+ Process log files between BeginDate and EndDate, inclusive.
22
+ EndDate defaults to today if omitted.
23
+
24
+ -b Run in background mode (log to file only, no terminal output).
25
+
26
+ EXAMPLE:
27
+ fillawsusage -p 2024-01-01 2024-01-31
@@ -5,7 +5,7 @@
5
5
  # Date : 2025-04-14
6
6
  # 2025-12-16 convert to class FillCDGUsage
7
7
  # Purpose : python program to retrieve info from GDEX Postgres database for GDS
8
- # file accesses and backup fill table tdsusage in PostgreSQL database dssdb.
8
+ # file accesses and backup fill table tdsusage in PostgreSQL database rdadb.
9
9
  # Github : https://github.com/NCAR/rda-python-metrics.git
10
10
  ###############################################################################
11
11
  import sys
@@ -18,6 +18,8 @@ from .pg_ipinfo import PgIPInfo
18
18
 
19
19
  class FillCDGUsage(PgSplit, PgIPInfo):
20
20
 
21
+ """Retrieve info from GDEX Postgres database for CDG file accesses and fill tables tdsusage and wusage in PostgreSQL database rdadb."""
22
+
21
23
  def __init__(self):
22
24
  super().__init__()
23
25
  self.USAGE = {
@@ -92,8 +94,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
92
94
  self.WFILES = {}
93
95
  self.params = {} # array of input values
94
96
 
95
- # function to run this program
96
97
  def read_parameters(self):
98
+ """Function to run this program."""
97
99
  argv = sys.argv[1:]
98
100
  opt = None
99
101
  for arg in argv:
@@ -116,19 +118,19 @@ class FillCDGUsage(PgSplit, PgIPInfo):
116
118
  self.pglog("-(m|N|y): Missing Month, NumberDays or Year to gather CDG metrics", self.LGWNEX)
117
119
  self.cmdlog("fillcdgusage {}".format(' '.join(argv)))
118
120
 
119
- # function to start actions
120
121
  def start_actions(self):
122
+ """Function to start actions."""
121
123
  dranges = self.get_date_ranges(self.params)
122
124
  dsids = self.get_dataset_ids(self.params['s'])
123
125
  if dranges and dsids: self.fill_cdg_usages(dsids, dranges)
124
126
  self.pglog(None, self.LOGWRN|self.SNDEML) # send email out if any
125
127
 
126
- # connect to the gdex database esg-production
127
128
  def gdex_dbname(self):
129
+ """Connect to the gdex database esg-production."""
128
130
  self.set_scname('esg-production', 'metrics', 'gateway-reader', None, 'sagedbprodalma.ucar.edu')
129
131
 
130
- # get datasets
131
132
  def get_dataset_ids(self, dsnames):
133
+ """Get datasets."""
132
134
  self.gdex_dbname()
133
135
  dsids = []
134
136
  tbname = 'metadata.dataset'
@@ -152,8 +154,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
152
154
  if not dsids: self.pglog("No Dataset Id identified to gather CDG metrics", self.LOGWRN)
153
155
  return dsids
154
156
 
155
- # get cdgids recursivley
156
157
  def recursive_dataset_ids(self, pcdgid, cdgids):
158
+ """Get cdgids recursively."""
157
159
  tbname = 'metadata.dataset'
158
160
  pgrecs = self.pgmget(tbname, 'id', "parent_dataset_id = '{}'".format(pcdgid))
159
161
  if not pgrecs: return 0
@@ -165,8 +167,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
165
167
  ccnt += self.recursive_dataset_ids(cdgid, cdgids)
166
168
  return ccnt
167
169
 
168
- # get the date ranges for given condition
169
170
  def get_date_ranges(self, inputs):
171
+ """Get the date ranges for given condition."""
170
172
  dranges = []
171
173
  for opt in inputs:
172
174
  for input in inputs[opt]:
@@ -185,8 +187,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
185
187
  if dates: dranges.append(dates)
186
188
  return dranges
187
189
 
188
- # get file download records for given dsid
189
190
  def get_dsid_records(self, cdgids, dates, strids):
191
+ """Get file download records for given dsid."""
190
192
  self.gdex_dbname()
191
193
  tbname = 'metrics.file_download'
192
194
  fields = ('date_completed, remote_address, logical_file_size, logical_file_name, file_access_point_uri, user_agent_name, bytes_sent, '
@@ -204,8 +206,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
204
206
  self.dssdb_dbname()
205
207
  return pgrecs
206
208
 
207
- # Fill TDS usages into table dssdb.tdsusage from cdg access records
208
209
  def fill_cdg_usages(self, dsids, dranges):
210
+ """Fill TDS usages into table dssdb.tdsusage from cdg access records."""
209
211
  allcnt = awcnt = atcnt = lcnt = 0
210
212
  for dates in dranges:
211
213
  for adsid in dsids:
@@ -305,8 +307,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
305
307
  rmsg = self.seconds_to_string_time(tm() - bt)
306
308
  self.pglog("{}: {}/{} TDS/WEB usage records added for {} CDG entries in {}".format(strids, atcnt, awcnt, allcnt, rmsg), self.LOGWRN)
307
309
 
308
- # get date and time from log record
309
310
  def get_record_date_time(self, ctime):
311
+ """Get date and time from log record."""
310
312
  ms = re.search(r'^(\d+)-(\d+)-(\d+) (\d\d:\d\d:\d\d)', str(ctime))
311
313
  if ms:
312
314
  y = ms.group(1)
@@ -318,8 +320,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
318
320
  else:
319
321
  self.pglog(str(ctime) + ": Invalid time format", self.LGEREX)
320
322
 
321
- # add to tds usage records
322
323
  def add_tdsusage_records(self, year, records, date):
324
+ """Add to tds usage records."""
323
325
  cnt = 0
324
326
  for key in records:
325
327
  record = records[key]
@@ -345,8 +347,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
345
347
  pgrec['ip'] = logrec['ip']
346
348
  return self.add_yearly_allusage(year, pgrec)
347
349
 
348
- # Fill usage of a single online data file into table dssdb.wusage of DSS PgSQL database
349
350
  def add_webfile_usage(self, year, logrec):
351
+ """Fill usage of a single online data file into table dssdb.wusage of DSS PgSQL database."""
350
352
  table = "{}_{}".format(self.USAGE['WEBTBL'], year)
351
353
  cdate = logrec['date']
352
354
  ip = logrec['ip']
@@ -368,8 +370,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
368
370
  else:
369
371
  return 0
370
372
 
371
- # add web record to allusage
372
373
  def add_web_allusage(self, year, logrec, wurec):
374
+ """Add web record to allusage."""
373
375
  pgrec = {'source' : 'C'}
374
376
  pgrec['email'] = wurec['email']
375
377
  pgrec['org_type'] = wurec['org_type']
@@ -384,8 +386,8 @@ class FillCDGUsage(PgSplit, PgIPInfo):
384
386
  pgrec['ip'] = logrec['ip']
385
387
  return self.add_yearly_allusage(year, pgrec)
386
388
 
387
- # return wfile.wid upon success, 0 otherwise
388
389
  def get_wfile_record(self, dsids, wfile):
390
+ """Return wfile.wid upon success, 0 otherwise."""
389
391
  for dsid in dsids:
390
392
  wkey = "{}{}".format(dsid, wfile)
391
393
  if wkey in self.WFILES: return self.WFILES[wkey]
@@ -410,7 +412,7 @@ class FillCDGUsage(PgSplit, PgIPInfo):
410
412
  self.WFILES[wkey] = pgrec
411
413
  return pgrec
412
414
 
413
- # main function to excecute this script
415
+ # main function to execute this script
414
416
  def main():
415
417
  object = FillCDGUsage()
416
418
  object.read_parameters()
@@ -1,18 +1,33 @@
1
1
 
2
- Retrieves CDG usage information from GDEX metrics database to
3
- fill table 'tdsusage' and 'webusage' in PostgreSQL database 'rdadb'.
2
+ fillcdgusage - Fill table 'tdsusage' and 'webusage' from CDG GDEX metrics.
4
3
 
5
- Usage: fillcdgusage [-b] -s DatasetShortNames [-m MonthList] [-N NumberDays] [-y YearList]
4
+ Retrieves CDG (Climate Data Gateway) usage info from the GDEX metrics
5
+ database and inserts records into the 'tdsusage' and 'webusage' tables
6
+ in PostgreSQL database 'rdadb'.
6
7
 
7
- select option -s and one of the options, -m, -N or -y each time to run
8
- this application.
8
+ USAGE:
9
+ fillcdgusage [-b] -s DatasetShortNames
10
+ (-m MonthList | -N NumberDays | -y YearList)
9
11
 
10
- - Option -b, log process information into logfile only;
12
+ OPTIONS:
11
13
 
12
- - Option -s, retrieve usage info for given dataset short names;
14
+ -s DatasetShortNames (required)
15
+ Gather usage info for the given dataset short names.
13
16
 
14
- - Option -m, retrieve usage info in given months (YYYY-MM);
17
+ One of the following time-range options is required:
15
18
 
16
- - Option -N, retrieve usage info in recent Number of days;
19
+ -m MonthList
20
+ Gather usage info for the given months.
21
+ Month format: YYYY-MM (e.g. 2024-01).
17
22
 
18
- - Option -y, retrieve usage info in given years (YYYY).
23
+ -N NumberDays
24
+ Gather usage info for the most recent NumberDays days.
25
+
26
+ -y YearList
27
+ Gather usage info for the given years.
28
+ Year format: YYYY (e.g. 2024).
29
+
30
+ -b Run in background mode (log to file only, no terminal output).
31
+
32
+ EXAMPLE:
33
+ fillcdgusage -s ds083.2 -y 2024
@@ -7,7 +7,7 @@
7
7
  # https://github.com/NCAR/rda-database.git
8
8
  # 2025-12-17 convert to class FillCODEUsage
9
9
  # Purpose : python program to retrieve info from web logs
10
- # and fill table codusage in PostgreSQL database dssdb.
10
+ # and fill table codusage in PostgreSQL database rdadb.
11
11
  # Github : https://github.com/NCAR/rda-python-metrics.git
12
12
  ###############################################################################
13
13
  import sys
@@ -18,6 +18,8 @@ from .pg_ipinfo import PgIPInfo
18
18
 
19
19
  class FillCODUsage(PgIPInfo):
20
20
 
21
+ """Retrieve info from web logs and fill table codusage in PostgreSQL database rdadb."""
22
+
21
23
  def __init__(self):
22
24
  super().__init__()
23
25
  # the define options for gathering COD data usage, one at a time
@@ -36,8 +38,8 @@ class FillCODUsage(PgIPInfo):
36
38
  self.datelimit = ''
37
39
  self.params = [] # array of input values
38
40
 
39
- # function to readparameters
40
41
  def read_parameters(self):
42
+ """Function to readparameters."""
41
43
  argv = sys.argv[1:]
42
44
  for arg in argv:
43
45
  if arg == "-b":
@@ -64,8 +66,8 @@ class FillCODUsage(PgIPInfo):
64
66
  self.dssdb_dbname()
65
67
  self.cmdlog("fillcodusage {}".format(' '.join(argv)))
66
68
 
67
- # function to start actions
68
69
  def start_actions(self):
70
+ """Function to start actions."""
69
71
  if self.USAGE['OPTION']&self.NDAYS:
70
72
  curdate = self.curdate()
71
73
  self.datelimit = self.adddate(curdate, 0, 0, -int(self.params[0]))
@@ -78,8 +80,8 @@ class FillCODUsage(PgIPInfo):
78
80
  self.fill_cod_usages(self.USAGE['OPTION'], self.params)
79
81
  self.pglog(None, self.LOGWRN|self.SNDEML) # send email out if any
80
82
 
81
- # Fill COD usages into table dssdb.codusage of DSS PostgreSQL database from cod access logs
82
83
  def fill_cod_usages(self, option, inputs):
84
+ """Fill COD usages into table dssdb.codusage of DSS PostgreSQL database from cod access logs."""
83
85
  cntall = cntadd = 0
84
86
  for input in inputs:
85
87
  # get log file names
@@ -144,8 +146,8 @@ class FillCODUsage(PgIPInfo):
144
146
  s = 's' if cntadd > 1 else ''
145
147
  self.pglog("{} COD usage records added for {} entries at {}".format(cntadd, cntall, self.current_datetime()), self.LOGWRN)
146
148
 
147
- # add usage to codusage table
148
149
  def add_usage_records(self, records, date):
150
+ """Add usage to codusage table."""
149
151
  ms = re.match(r'(\d+)-(\d+)-', date)
150
152
  if not ms: return 0
151
153
  year = ms.group(1)
@@ -178,8 +180,8 @@ class FillCODUsage(PgIPInfo):
178
180
  cnt += self.pgadd(self.USAGE['PGTBL'], record, self.LOGWRN)
179
181
  return cnt
180
182
 
181
- # add usage to allusage tables
182
183
  def add_to_allusage(self, pgrec, year):
184
+ """Add usage to allusage tables."""
183
185
  record = {'method' : 'COD', 'source' : 'C'}
184
186
  for fld in pgrec:
185
187
  ms = re.match(r'^(engine|count)$', fld)
@@ -187,8 +189,8 @@ class FillCODUsage(PgIPInfo):
187
189
  record[fld] = pgrec[fld]
188
190
  return self.add_yearly_allusage(year, record) # change 1 to 0 to stop checking
189
191
 
190
- # cashe user info for reuse
191
192
  def cache_users(self, aid):
193
+ """Cashe user info for reuse."""
192
194
  pgrec = self.pgget("metautil.custom_dap_history", "*", "ID = '{}'".format(aid), self.LGEREX)
193
195
  if pgrec:
194
196
  ms = re.search(r'dsnum=(\d+\.\d|[a-z]\d{6});', pgrec['rinfo'])
@@ -198,8 +200,8 @@ class FillCODUsage(PgIPInfo):
198
200
  return 1
199
201
  return 0
200
202
 
201
- # get period
202
203
  def access_period(self, etime, btime):
204
+ """Get period."""
203
205
  period = 86400
204
206
  ms = re.search(r'(\d+):(\d+):(\d+)', etime)
205
207
  if ms:
@@ -209,7 +211,7 @@ class FillCODUsage(PgIPInfo):
209
211
  period -= int(ms.group(1))*3600+int(ms.group(2))*60+int(ms.group(3))
210
212
  return period
211
213
 
212
- # main function to excecute this script
214
+ # main function to execute this script
213
215
  def main():
214
216
  object = FillCODUsage()
215
217
  object.read_parameters()
@@ -1,21 +1,32 @@
1
1
 
2
- Retrieves usage information from RDA Web logs under /var/log to
3
- fill table 'codusage' in database 'rdadb'.
2
+ fillcodusage - Fill table 'codusage' from custom OPeNDAP (COD) access logs.
4
3
 
5
- Usage: fillcodusage [-a] [-b] [-f LogFileNames] [-m MonthList] [-N NumberDay] [-y YearList]
4
+ Reads RDA Web/COD access logs under /var/log and inserts usage records
5
+ into the 'codusage' table in PostgreSQL database 'rdadb'.
6
6
 
7
- select one of the options, -a, -f, -m, -N or -y each time to run
8
- this application.
7
+ USAGE:
8
+ fillcodusage [-b] (-a | -f LogFileNames | -m MonthList |
9
+ -N NumberDays | -y YearList)
9
10
 
10
- - Option -b, log process information into logfile only;
11
+ OPTIONS (choose exactly one of -a, -f, -m, -N, or -y):
11
12
 
12
- - Option -a, retrieve usages for all available logs;
13
+ -a Process all available log files.
13
14
 
14
- - Option -f, retrieve usage info from given log file names;
15
+ -f LogFileNames
16
+ Process the given log file names directly.
15
17
 
16
- - Option -m, retrieve usage info in given months;
18
+ -m MonthList
19
+ Process log files for the given months.
20
+ Month format: YYYY-MM (e.g. 2024-01).
17
21
 
18
- - Option -N, retrieve usage info in recent NumberDay days;
22
+ -N NumberDays
23
+ Process log files covering the most recent NumberDays days.
19
24
 
20
- - Option -y, retrieve usage info in given years.
25
+ -y YearList
26
+ Process log files for the given years.
27
+ Year format: YYYY (e.g. 2024).
21
28
 
29
+ -b Run in background mode (log to file only, no terminal output).
30
+
31
+ EXAMPLE:
32
+ fillcodusage -m 2024-01 2024-02
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env python3/
1
+ #!/usr/bin/env python3
2
2
  ###############################################################################
3
3
  # Title : fillcountry
4
4
  # Author : Zaihua Ji, zji@ucar.edu
@@ -15,13 +15,15 @@ import re
15
15
  from rda_python_common.pg_dbi import PgDBI
16
16
 
17
17
  class FillCountry(PgDBI):
18
+ """Fill missing country field from email info for a given table name."""
19
+
18
20
  def __init__(self):
19
21
  super().__init__()
20
22
  self.tables = ['allusage', 'user', 'wuser']
21
23
  self.table = None
22
24
 
23
- # function to read paramters
24
- def read_parameter(self):
25
+ def read_parameters(self):
26
+ """Function to read parameters."""
25
27
  argv = sys.argv[1:]
26
28
  # check command line
27
29
  for arg in argv:
@@ -40,13 +42,13 @@ class FillCountry(PgDBI):
40
42
  self.pglog("{}: table name must be ({})".format(self.table, '|'.join(self.tables)), self.LGEREX)
41
43
  self.cmdlog("fillcountry {}".format(' '.join(argv)))
42
44
 
43
- # function to start actions
44
45
  def start_actions(self):
46
+ """Function to start actions."""
45
47
  self.dssdb_dbname()
46
48
  self.process_countries()
47
49
 
48
- # fill country info
49
50
  def process_countries(self):
51
+ """Fill country info."""
50
52
  pgrecs = self.pgmget(self.table, "email", "country IS NULL", self.LOGWRN)
51
53
  cntall = len(pgrecs['email']) if pgrecs else 0
52
54
  self.pglog("Set {} record(s) for missing country in table {}".format(cntall, self.table), self.LOGWRN)
@@ -60,7 +62,7 @@ class FillCountry(PgDBI):
60
62
  cntmod += self.pgupdt(self.table, record, "email = '{}' AND country IS NULL".format(email), self.LOGWRN)
61
63
  self.pglog("{} Record(s) modified in table '{}'".format(cntmod, self.table), self.LOGWRN)
62
64
 
63
- # main function to excecute this script
65
+ # main function to execute this script
64
66
  def main():
65
67
  object = FillCountry()
66
68
  object.read_parameters()