32515a6797b6e68daa3aa94c663760216b24dd67 lrnassar Thu Sep 3 13:30:26 2026 -0700 Usage stats cron fixes from code review. refs #38232 Apply the same db mismatch guard to assemblyStatsCron.py that generateUsageStats.py already had. Both files ask hgTracks for one assembly's default tracks and parse the answer off stderr, but only one of them checked that hgTracks answered about the assembly it was asked about. Without it, a repeat of the db= bug this ticket fixed would quietly fill the default track filter with another assembly's tracks and say nothing. Drop any database name that does not look like one before interpolating it into a shell command. The trimmed logs only ever carry real assembly names, so this is defence in depth rather than a live hole. Fix a comment in resolveHub that still described the lastOkTime fallback, which was replaced by mirror order earlier in this ticket. No change to the report. The row counts for the database usage and non-public hub tables were cut from 15 to 10 in the previous commit, which its message did not mention; that was intentional, to make room for the new GenArk and hubSpace sections. diff --git src/hg/logCrawl/dbTrackAndSearchUsage/generateUsageStats.py src/hg/logCrawl/dbTrackAndSearchUsage/generateUsageStats.py index d6990f214db..67f00547d1e 100755 --- src/hg/logCrawl/dbTrackAndSearchUsage/generateUsageStats.py +++ src/hg/logCrawl/dbTrackAndSearchUsage/generateUsageStats.py @@ -1,18 +1,18 @@ #!/usr/bin/env python3 -import subprocess, os, gzip, argparse, sys, json, operator, datetime +import subprocess, os, gzip, argparse, sys, json, operator, datetime, re from collections import Counter, defaultdict ##### # Define dictionaries/sets/etc. needed to record stats ##### # Making these global so that they can be modified by functions whithout needing # a function argument to specify them # Dictionaries for holding information about db use dbUsers = defaultdict(Counter) # Ex dbUsers struct: {"db":{"hgsid":count}} dbCounts = dict() # Ex dbCounts struct: {"db":count} # Dictionaries for recording information per month dbUsersMonth = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict()))) # Ex dbUsersMonth struct: {"db":{"year":{"month":{"hgsid":count}}}} @@ -594,31 +594,34 @@ dumpToJson(trackCountsHubsMonth, "trackCountsHubs.perMonth.json", outDir) #if args.monthYear == True: # dumpToJson(monthYearSet, "monthYearSet.json") ##### ##### Output information on default track usage if indicated ##### if args.outputDefaults == True and all([args.dbCounts, args.trackCounts]): # Sort dbs by most popular. Hub-backed dbs (e.g. hub_3671779_hs1) are skipped: hub ids # are handed out per hgcentral, so the ids in the logs never match the ids hgTracks # returns here and every track lookup below would miss. dbCountsSorted = sorted(dbCounts.items(), key=operator.itemgetter(1)) dbCountsSorted.reverse() - dbsToCheck = [db for db, useCount in dbCountsSorted if not db.startswith("hub_")] + #The name is interpolated into a shell command below, so anything that does not look + #like an assembly name is dropped rather than passed to sh + dbsToCheck = [db for db, useCount in dbCountsSorted + if not db.startswith("hub_") and re.match(r'^[A-Za-z0-9_.-]+$', db)] defaultCountsFile = open(os.path.join(outDir, "defaultCounts.tsv"), "w") for db in dbsToCheck[0:15]: # Only the default track stats for the 15 most popular assemblies dbOpt = "db=" + db # HGDB_CONF must be set here so that we use default tracks from beta, not dev # Dev can contain staged tracks that don't exist on RR, leading to errors later in script # The space before dbOpt matters - without it cgiSpoof reads the whole thing as one # variable and db is silently ignored, leaving every assembly with hg38's defaults. cmd = ["cd /usr/local/apache/cgi-bin && HGDB_CONF=$HOME/.hg.conf.beta ./hgTracks hgt.trackImgOnly=1 " + dbOpt] p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmdout, cmderr = p.communicate() # Hub shortLabels are user supplied, so an errAbort here can carry non-ASCII errText = cmderr.decode("utf-8", errors="replace") # hgTracks writes the visible track list to stderr as "trackLog N db hgsid t:vis,t:vis", # split into ~800 byte blocks so Apache does not chop the lines. Every numbered block