Skip to content

Commit 42abbd8

Browse files
authored
Merge pull request #1422 from oracle-devrel/newadvisor23ai
newadvisor23ai
2 parents 1900d8a + b9da4bd commit 42abbd8

File tree

4 files changed

+273
-0
lines changed

4 files changed

+273
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Copyright (c) 2024 Oracle and/or its affiliates.
2+
3+
The Universal Permissive License (UPL), Version 1.0
4+
5+
Subject to the condition set forth below, permission is hereby granted to any
6+
person obtaining a copy of this software, associated documentation and/or data
7+
(collectively the "Software"), free of charge and under any and all copyright
8+
rights in the Software, and any and all patent rights owned or freely
9+
licensable by each licensor hereunder covering either (i) the unmodified
10+
Software as contributed to or provided by such licensor, or (ii) the Larger
11+
Works (as defined below), to deal in both
12+
13+
(a) the Software, and
14+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
one is included with the Software (each a "Larger Work" to which the Software
16+
is contributed by such licensors),
17+
18+
without restriction, including without limitation the rights to copy, create
19+
derivative works of, display, perform, and distribute the Software and make,
20+
use, sell, offer for sale, import, export, have made, and have sold the
21+
Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
either these or other terms.
23+
24+
This license is subject to the following condition:
25+
The above copyright notice and either this complete permission notice or at
26+
a minimum a reference to the UPL must be included in all copies or
27+
substantial portions of the Software.
28+
29+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35+
SOFTWARE.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# MongoDB compatibility advisor for Autonomous MongoDB API
2+
3+
This tool helps you to identify which MongoDB queries are supported when using the Oracle Autonomous MongoDB API.
4+
5+
Reviewed: 04.11.2024
6+
7+
# When to use this asset?
8+
9+
This tool generates a report which indicates the percentage of compatibility. There is an example in this repository. This advisor has been tested for the 23ai version.
10+
11+
# How to use this asset?
12+
13+
You need to provide the MongoDB log as an argument.
14+
15+
```
16+
python3 advisor.py --file mongod.log
17+
```
18+
19+
You need to enable logging in the MongoDB by running the following command. It is recommended to run it in non-production environments.
20+
```
21+
db.setProfilingLevel(0, -1)
22+
```
23+
24+
The script generates a report in a file called report_advisor.txt
25+
26+
# License
27+
28+
Copyright (c) 2024 Oracle and/or its affiliates.
29+
30+
Licensed under the Universal Permissive License (UPL), Version 1.0.
31+
32+
See [LICENSE](https://github.com/oracle-devrel/technology-engineering/blob/main/LICENSE) for more details.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
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:])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Report Summary for 23ai:
2+
*****************************
3+
4+
5+
Summary of aggregation operators found: your operators are 100% compatible with MongoDB API
6+
****************************************************************************************************
7+
- Total Aggregation Pipelines found: 17
8+
- Total Supported Aggregation Pipelines: 17
9+
- Total Not Supported Aggregation Pipelines: 0
10+
11+
12+
List of supported aggregation operators and the number of times it appears:
13+
********************************************************************************
14+
{'$set': 3, '$lt': 1, '$and': 1, '$ne': 1, '$exists': 1, '$not': 1, '$regex': 1, '$push': 4, '$each': 2, '$slice': 2}
15+
16+
17+
List of NOT supported aggregation operators and the number of times it appears:
18+
********************************************************************************
19+
{}
20+
21+
22+
Summary of operations found: your operations are 100% compatible with MongoDB API
23+
*************************************************************************************
24+
- Query operations using find: 3
25+
- Update operations : 4
26+
27+
28+
** Operations not supported.
29+
Insert and updates could not be accurate number as appears more in the log.
30+
31+
32+

0 commit comments

Comments
 (0)