1
+ import argparse
2
+ import sys
3
+
4
+ supported_keywords = ["$gt" ,"$gte" ,"$lt" ,"$and" ,"$not" ,"$or" ,"$nor" ,"$ne" ,"$eq" ,"$in" ,"$lte" ,"$nin" ,"$exists" ,"$type" ,"$regex" ,"$text" ,"$near" ,"$nearSphere" ,"$size" ,"$natural" ,"$inc" ,"$min" ,"$max" ,
5
+ "$rename" ,"$set" ,"$addToSet" ,"$pop" ,"$pull" ,"$push" ,"$pullAll" ,"$each" ,"$position" ,"$sort" ,"$bit" ,"$count" ,"$limit" ,"$match" ,"$skip" ,"$slice" ,"$mod" ,"$geoIntersects" ,
6
+ "$geoWithin" ,"$all" ,"$elemMatch" ,"$rand" ,"$mul" ,"$setOnInsert" ,"$abs" ,"$addFields" ,"$bucket" ,"$collStats" ,"$facet" ,"$group" ,"$out" ,"$project" ,"$replaceRoot" ,"$sortByCount" ,
7
+ "$unionWith" ,"$unset" ,"$unwind" ,"$add" ,"$arrayElemAt" ,"$arrayToObject" ,"$bottom" ,"$ceil" ,"$cmp" ,"$concatArrays" ,"$concat" ,"$cond" ,"$dateFromString" ,"$dateToString" ,"$divide" ,
8
+ "$exp" ,"$filter" ,"$first" ,"$firstN" ,"$floor" ,"$ifNull" ,"$isArray" ,"$isNumber" ,"$last" ,"$let" ,"$literal" ,"$ln" ,"$ltrim" ,"$mergeObjects" ,"$multiply" ,"$objectToArray" ,"$pow" ,
9
+ "$reverseArray" ,"$round" ,"$rtrim" ,"$setUnion" ,"$sortArray" ,"$sqrt" ,"$subtract" ,"$top" ,"$toString" ,"$toLower" ,"$toUpper" ,"$trim" ,"$trunc" ,"$zip" ,"$currentDate" ,"$lastN" ,"$reduce" ,
10
+ "$strcasecmp" ,"$sql" ,"$stdDevPop" ,"$stdDevSamp" ,"$replaceWith" ,"$sample" ,"$avg" ,"$indexOfArray" ,"$indexOfCP" ,"$log" ,"$log10" ,"$sum" ,"$switch" ,"$toBool" ,"$toDate" ,"$toDouble" ]
11
+
12
+ not_supported_keywords = ["$expr" ,"$jsonSchema" ,"$box" ,"$center" ,"$centerSphere" ,"$maxDistance" ,"$minDistance" ,"$polygon" ,"$bitsAllClear" ,"$bitsAllSet" ,"$bitsANyClear" ,"$bitsAnySet" ,"$currentData" ,
13
+ "$accumulator" ,"$acos" ,"$acosh" ,"$bucketAuto" ,"$changeStream" ,"$currentOp" ,"$densify" ,"$documents" ,"$fill" ,"$geoNear" ,"$graphLookup" ,"$indexStats" ,"$lookup" ,"$merge" ,"$redact" ,
14
+ "$search" ,"$searchMeta" ,"$setWindowFields" ,"$allElementsTrue" ,"$anyElementTrue" ,"$asin" ,"$asinh" ,"$atan" ,"$atan2" ,"$atanh" ,"$binarySize" ,"$bottomN" ,
15
+ "$bsonSize" ,"$convert" ,"$cosh" ,"$cosh" ,"$covariancePop" ,"$covarianceSamp" ,"$dateAdd" ,"$dateDiff" ,"$dateFromParts" ,"$datesubtract" ,"$dateToParts" ,"$dateTrunc" ,"$dayOfMonth" ,"$dayOfWeek" ,
16
+ "$dayOfYear" ,"$degreesToRadians" ,"$denseRank" ,"$derivative" ,"$documentNumber" ,"$expMovingAvg" ,"$function" ,"$getField" ,"$hour" ,"$indexOfBytes" ,"$integral" ,
17
+ "$isoDayOfWeek" ,"$isoWeek" ,"$isoWeekYear" ,"$linearFill" ,"$map" ,"$maxN" ,"$meta" ,"$minN" ,"$millisecond" ,"$minute" ,"$month" ,"$radiansToDegrees" ,"$range" ,"$rank" ,"$regexFind" ,
18
+ "$regexFindAll" ,"$regexMatch" ,"$replaceOne" ,"$replaceAll" ,"$sampleRate" ,"$second" ,"$setDifference" ,"$setEquals" ,"$setField" ,"$setIntersection" ,"$setIsSubset" ,"$shift" ,"$sin" ,"$sinh" ,
19
+ "$split" ,"$stsDevPop" ,"$stsDevSamp" ,"$strLenBytes" ,"$strLenCP" ,"$substr" ,"$substrCP" ,"$tan" ,"$tanh" ,"$toDecimal" ,"$toInt" ,"$toLong" ,
20
+ "$toObjectId" ,"$topN" ,"$tsIncrement" ,"$tsSecond" ,"$unsetField" ,"$week" ,"$year" ]
21
+
22
+ operations = ["\" command\" :{\" find\" " ,"\" command\" :{\" update\" " ,"\" command\" :{\" insert\" " ,"\" command\" :{\" delete\" " ,"\" command\" :{\" aggregate\" " ,"\" command\" :{\" mapReduce\" " ,"\" command\" :{\" getMore\" " ,"\" command\" :{\" findAndModify\" " ]
23
+
24
+ def main (argv ):
25
+ parser = argparse .ArgumentParser ()
26
+ parser .add_argument ("--file" ,dest = "file" ,help = "Set the MongoDB log file to analyze" )
27
+
28
+ argv = parser .parse_args ()
29
+
30
+ if argv .file is None :
31
+ parser .error ("--file is required" )
32
+
33
+ mongo_log = read_log (argv .file )
34
+ supported_dictionary ,not_supported_dictionary ,operation_dictionary = search (mongo_log )
35
+ generate_report (supported_dictionary ,not_supported_dictionary ,operation_dictionary )
36
+
37
+
38
+ def read_log (file ):
39
+ with open (file , 'r' ) as f :
40
+ text = f .readlines ()
41
+ return text
42
+
43
+
44
+ def search (input_file ):
45
+
46
+ supported_dictionary = dict ()
47
+ not_supported_dictionary = dict ()
48
+ operation_dictionary = dict ()
49
+
50
+ for line in input_file :
51
+ for keyword in supported_keywords :
52
+ if keyword in line :
53
+ if not keyword in supported_dictionary :
54
+ supported_dictionary [keyword ]= 1
55
+ else :
56
+ supported_dictionary [keyword ]+= 1
57
+
58
+ for keyword in not_supported_keywords :
59
+ if keyword in line :
60
+ if not keyword in not_supported_dictionary :
61
+ not_supported_dictionary [keyword ]= 1
62
+ else :
63
+ not_supported_dictionary [keyword ]+= 1
64
+
65
+ for keyword in operations :
66
+ if keyword in line :
67
+ if not keyword in operation_dictionary :
68
+ operation_dictionary [keyword ]= 1
69
+ else :
70
+ operation_dictionary [keyword ]+= 1
71
+
72
+
73
+ return supported_dictionary ,not_supported_dictionary ,operation_dictionary
74
+
75
+
76
+
77
+
78
+ def generate_report (supported_dictionary ,not_supported_dictionary ,operations_dictionary ):
79
+
80
+ #Calculate aggregation pipelines perc
81
+ total = sum (supported_dictionary .values ()) + sum (not_supported_dictionary .values ())
82
+ total_supported = sum (supported_dictionary .values ())
83
+ total_not_supported = sum (not_supported_dictionary .values ())
84
+ if total == 0 :
85
+ perc = 0
86
+ else :
87
+ perc = round (total_supported / total * 100 )
88
+
89
+ #Calculate operations perc
90
+ total_operations = sum (operations_dictionary .values ())
91
+
92
+ supp_find = operations_dictionary ["\" command\" :{\" find\" " ] if "\" command\" :{\" find\" " in operations_dictionary else 0
93
+ supp_delete = operations_dictionary ["\" command\" :{\" delete\" " ] if "\" command\" :{\" delete\" " in operations_dictionary else 0
94
+ supp_insert = operations_dictionary ["\" command\" :{\" insert\" " ] if "\" command\" :{\" insert\" " in operations_dictionary else 0
95
+ supp_update = operations_dictionary ["\" command\" :{\" update\" " ] if "\" command\" :{\" update\" " in operations_dictionary else 0
96
+ supp_findAndModify = operations_dictionary ["\" command\" :{\" findAndModify\" " ] if "\" command\" :{\" findAndModify\" " in operations_dictionary else 0
97
+ supp_getMore = operations_dictionary ["\" command\" :{\" getMore\" " ] if "\" command\" :{\" getMore\" " in operations_dictionary else 0
98
+
99
+ supported_operations = supp_find + supp_delete + supp_insert + supp_update + supp_findAndModify + supp_getMore
100
+
101
+
102
+ if total_operations == 0 :
103
+ perc_operations = 0
104
+ else :
105
+ perc_operations = round (supported_operations / total_operations * 100 )
106
+
107
+ #Calculate overall compatibility per
108
+
109
+ if (perc_operations )== 0 :
110
+ overall_supported = 0
111
+ else :
112
+ overall_supported = (perc + perc_operations )/ 2
113
+
114
+
115
+ with open ('report_advisor.txt' ,'w' ) as f :
116
+ f .write ("Report Summary for 23ai: " + "\n " )
117
+ f .write ("*****************************" + "\n \n \n " )
118
+
119
+
120
+
121
+ f .write ("Summary of aggregation operators found: your operators are " + str (perc )+ "% compatible with MongoDB API \n " )
122
+ f .write ("****************************************************************************************************" + "\n " )
123
+
124
+ f .write (" - Total Aggregation Pipelines found: " + str (total )+ "\n " )
125
+ f .write (" - Total Supported Aggregation Pipelines: " + str (total_supported )+ "\n " )
126
+ f .write (" - Total Not Supported Aggregation Pipelines: " + str (total_not_supported )+ "\n \n \n " )
127
+
128
+
129
+
130
+ f .write ("List of supported aggregation operators and the number of times it appears: \n " )
131
+ f .write ("********************************************************************************" + "\n " )
132
+ f .write (str (supported_dictionary )+ "\n \n \n " )
133
+
134
+
135
+ f .write ("List of NOT supported aggregation operators and the number of times it appears: \n " )
136
+ f .write ("********************************************************************************" + "\n " )
137
+
138
+ f .write (str (not_supported_dictionary )+ "\n \n \n " )
139
+
140
+ f .write ("Summary of operations found: your operations are " + str (perc_operations )+ "% compatible with MongoDB API \n " )
141
+ f .write ("*************************************************************************************" + "\n " )
142
+
143
+
144
+ if '\" command\" :{\" find\" ' in operations_dictionary :
145
+ f .write (" - Query operations using find: " + str (operations_dictionary ["\" command\" :{\" find\" " ])+ "\n " )
146
+
147
+ if '\" command\" :{\" delete\" ' in operations_dictionary :
148
+ f .write (" - Delete operations : " + str (operations_dictionary ["\" command\" :{\" delete\" " ])+ "\n " )
149
+
150
+
151
+ if '\" command\" :{\" insert\" ' in operations_dictionary :
152
+ f .write (" - Insert operations : " + str (operations_dictionary ["\" command\" :{\" insert\" " ])+ "\n " )
153
+
154
+ if '\" command\" :{\" update\" ' in operations_dictionary :
155
+ f .write (" - Update operations : " + str (operations_dictionary ["\" command\" :{\" update\" " ])+ "\n " )
156
+
157
+ if '\" command\" :{\" findAndModify\" ' in operations_dictionary :
158
+ f .write (" - findAndModify operations : " + str (operations_dictionary ["\" command\" :{\" findAndModify\" " ])+ "\n " )
159
+
160
+ if '\" command\" :{\" getMore\" ' in operations_dictionary :
161
+ f .write (" - getMore operations : " + str (operations_dictionary ["\" command\" :{\" getMore\" " ])+ "\n " )
162
+
163
+ if "\" command\" :{\" aggregate\" " in operations_dictionary :
164
+ f .write (" - Aggregate operations** : " + str (operations_dictionary ["\" command\" :{\" aggregate\" " ])+ "\n " )
165
+
166
+ if "\" command\" :{\" mapReduce\" " in operations_dictionary :
167
+ f .write (" - mapReduce operations** : " + str (operations_dictionary ["\" command\" :{\" mapReduce\" " ])+ "\n " + "\n " + "\n " + "\n " )
168
+
169
+ f .write ("\n " + "\n " + " ** Operations not supported.\n " )
170
+ f .write (" Insert and updates could not be accurate number as appears more in the log." + "\n " + "\n " + "\n " + "\n " )
171
+
172
+
173
+ if __name__ == "__main__" :
174
+ main (sys .argv [1 :])
0 commit comments