diff --git a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py
index a648db73..53766d8a 100644
--- a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py
+++ b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py
@@ -348,4 +348,12 @@ def Update(inGSettings):
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'") # Log about compatibility
if "VersionStr" not in inGSettings: # Create new ProcessorDict structure
inGSettings["VersionStr"] = None
- if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'VersionStr'") # Log about compatibility
\ No newline at end of file
+ if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'VersionStr'") # Log about compatibility
+ if "DumpLogListRefreshIntervalSecFloat" not in inGSettings["Client"]: # Create new ProcessorDict structure
+ inGSettings["Client"].update({
+ "DumpLogListRefreshIntervalSecFloat": 5.0, # Duration between updates for the Client
+ "DumpLogListCountInt": 100, # Set the max row for the dump
+ "DumpLogList": [], # Will be filled automatically
+ "DumpLogListHashStr": None, # Will be filled automatically
+ })
+ if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'Client > DumpLog... with default parameters'") # Log about compatibility
\ No newline at end of file
diff --git a/Sources/pyOpenRPA/Orchestrator/HandlerList.py b/Sources/pyOpenRPA/Orchestrator/HandlerList.py
new file mode 100644
index 00000000..72d00b3b
--- /dev/null
+++ b/Sources/pyOpenRPA/Orchestrator/HandlerList.py
@@ -0,0 +1,14 @@
+from logging import StreamHandler
+
+class HandlerDumpLog(StreamHandler):
+ def __init__(self, inDict, inKeyStr, inHashKeyStr, inRowCountInt):
+ StreamHandler.__init__(self)
+ self.Dict = inDict
+ self.KeyStr = inKeyStr
+ self.HashKeyStr = inHashKeyStr
+ self.RowCountInt = inRowCountInt
+ self.Dict[self.HashKeyStr]="0"
+ def emit(self, inRecord):
+ inMessageStr = self.format(inRecord)
+ self.Dict[self.KeyStr].append(inMessageStr)
+ self.Dict[self.HashKeyStr]=str(int(self.Dict[self.HashKeyStr])+1)
\ No newline at end of file
diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py
index 660aa001..eb55d67b 100644
--- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py
+++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py
@@ -540,8 +540,18 @@ def GSettingsAutocleaner(inGSettings):
# # # # # # # # # # # # # # # # # # # # # # # # # #
from .. import __version__ # Get version from the package
+import logging
# Main def for orchestrator
def Orchestrator(inGSettings):
+
+ # TEst
+ from . import HandlerList
+ mHandlerDumpLogList = HandlerList.HandlerDumpLog( inDict=inGSettings["Client"],inKeyStr="DumpLogList", inHashKeyStr="DumpLogListHashStr",inRowCountInt=100)
+ mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
+ mHandlerDumpLogList.setFormatter(mRobotLoggerFormatter)
+ lL = inGSettings["Logger"]
+ lL.addHandler(mHandlerDumpLogList)
+
#mGlobalDict = Settings.Settings(sys.argv[1])
gSettingsDict = inGSettings # Alias for old name in alg
inGSettings["VersionStr"] = __version__
diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
index 37929b88..bd367326 100644
--- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
+++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
@@ -95,7 +95,7 @@ def pyOpenRPA_ServerData(inRequest,inGSettings):
lServerDataDictJSONStr = json.dumps(lServerDataDict)
# Generate hash
lServerDataHashStr = str(hash(lServerDataDictJSONStr))
- if lValueStr!=lServerDataHashStr: # Case if Hash is not equal
+ if lValueStr!=lServerDataHashStr and lServerDataHashStr!= "" and lServerDataHashStr!= None: # Case if Hash is not equal
lFlagDoGenerateBool = False
else: # Case Hashes are equal
time.sleep(inGSettings["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"])
@@ -108,7 +108,36 @@ def pyOpenRPA_ServerData(inRequest,inGSettings):
inResponseDict["Body"] = bytes(message, "utf8")
return lResult
-
+#v1.2.0 Send data container to the client from the server
+# /pyOpenRPA/ServerLog return {"HashStr" , "ServerLogList": ["row 1", "row 2"]}
+# Client: mGlobal.pyOpenRPA.ServerLogListHashStr
+# Client: mGlobal.pyOpenRPA.ServerLogList
+def pyOpenRPA_ServerLog(inRequest,inGSDict):
+ # Extract the hash value from request
+ lValueStr = None
+ if inRequest.headers.get('Content-Length') is not None:
+ lInputByteArrayLength = int(inRequest.headers.get('Content-Length'))
+ lInputByteArray = inRequest.rfile.read(lInputByteArrayLength)
+ # Превращение массива байт в объект
+ lValueStr = (lInputByteArray.decode('utf8'))
+ # Generate ServerDataDict
+ lFlagDoGenerateBool = True
+ while lFlagDoGenerateBool:
+ lServerLogList = inGSDict["Client"]["DumpLogList"]
+ # Get hash
+ lServerLogListHashStr = inGSDict["Client"]["DumpLogListHashStr"]
+ if lValueStr!=lServerLogListHashStr and lServerLogListHashStr!= "" and lServerLogListHashStr!= None: # Case if Hash is not equal Fix because None can be obtained without JSON decode
+ lFlagDoGenerateBool = False
+ else: # Case Hashes are equal
+ time.sleep(inGSDict["Client"]["DumpLogListRefreshIntervalSecFloat"])
+ # Return the result if Hash is changed
+ lResult = {"HashStr": lServerLogListHashStr, "ServerLogList": lServerLogList}
+ inResponseDict = inRequest.OpenRPAResponseDict
+ # Send message back to client
+ message = json.dumps(lResult)
+ # Write content as utf-8 data
+ inResponseDict["Body"] = bytes(message, "utf8")
+ return lResult
def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
@@ -159,6 +188,7 @@ def SettingsUpdate(inGlobalConfiguration):
{"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": BackwardCompatibility.v1_2_0_UserRoleHierarchyGet, "ResponseContentType": "application/json"},
# New way of the v.1.2.0 functionallity (all defs by the URL from /pyOpenRPA/...)
{"Method": "POST", "URL": "/pyOpenRPA/ServerData", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"},
+ {"Method": "POST", "URL": "/pyOpenRPA/ServerLog", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerLog, "ResponseContentType": "application/json"},
{"Method": "GET", "URL": "/pyOpenRPA/Screenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"},
]
inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
diff --git a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py
index 85f501d7..d15fc481 100644
--- a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py
+++ b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py
@@ -28,8 +28,14 @@ def __Create__():
# "UserADStr": None, # User, who connect. None if user is not exists
# "DomainADStr": None, # Domain of the user who connect. None if user is not exists
# }
- }
- }
+ },
+ },
+ # # # # # # Client... # # # # # # # #
+ "DumpLogListRefreshIntervalSecFloat": 5.0, # Duration between updates for the Client
+ "DumpLogListCountInt": 100, # Set the max row for the dump
+ "DumpLogList": [], # Will be filled automatically
+ "DumpLogListHashStr": None, # Will be filled automatically
+ # # # # # # # # # # # # # # # # # #
},
"Server": {
"WorkingDirectoryPathStr": None, # Will be filled automatically
@@ -287,6 +293,7 @@ def __Create__():
# inModeStr:
# "BASIC" - create standart configuration
+
def Create(inModeStr="BASIC"):
if inModeStr=="BASIC":
lResult = __Create__() # Create settings
diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.js b/Sources/pyOpenRPA/Orchestrator/Web/Index.js
index 1e81769a..838eca83 100644
--- a/Sources/pyOpenRPA/Orchestrator/Web/Index.js
+++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.js
@@ -350,7 +350,6 @@ $(document).ready(function() {
}
/// v1.2.0 pyOpenRPA ServerData
-
mGlobal.pyOpenRPA.ServerDataDict = null
mGlobal.pyOpenRPA.ServerDataHashStr = ""
mGlobal.pyOpenRPA.ServerDataRefreshDef_TechnicalRender = function()
@@ -401,8 +400,56 @@ $(document).ready(function() {
mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive
}
}
-
/////////////////////////////////////////////////////////////
+ /// v1.2.0 pyOpenRPA ServerLogs
+ mGlobal.pyOpenRPA.ServerLogList = null
+ mGlobal.pyOpenRPA.ServerLogListHashStr = ""
+ mGlobal.pyOpenRPA.ServerLogListScrollBottomDef = function() {
+ var lTA = $("textarea.mGlobal-pyOpenRPA-ServerLogList")[0];
+ lTA.scrollTop = lTA.scrollHeight;
+ }
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef_TechnicalRender = function()
+ {
+ lResponseJSON = mGlobal.pyOpenRPA.ServerLogList
+ if (lResponseJSON!= null) {
+ lText = lResponseJSON.join("\n") /// Code for the processing the text
+ $("textarea.mGlobal-pyOpenRPA-ServerLogList")[0].value= lText ///Прогрузить новую таблицу
+ mGlobal.pyOpenRPA.ServerLogListScrollBottomDef() //Scroll to the bottom
+ }
+ }
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef=function() {
+ try {
+ $.ajax({
+ type: "POST",
+ headers: {},
+ url: 'pyOpenRPA/ServerLog',
+ data: mGlobal.pyOpenRPA.ServerLogListHashStr,
+ success: function(lData,l2,l3) {
+ try {
+ var lResponseJSON=JSON.parse(lData)
+ mGlobal.pyOpenRPA.ServerLogList = lResponseJSON["ServerLogList"]
+ mGlobal.pyOpenRPA.ServerLogListHashStr = lResponseJSON["HashStr"]
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef_TechnicalRender()
+ }
+ catch(error) {
+ }
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive
+ },
+ dataType: "text",
+ error: function(jqXHR, textStatus, errorThrown ) {
+ sleep(3000)
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive
+ }
+ });
+ }
+ catch(error) {
+ sleep(3000)
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive
+ }
+ }
+ /////////////////////////////////////////////////////////////
+
+
mGlobal.Monitor.mDatasetLast = null
mGlobal.fControlPanelRefresh=function() {
@@ -786,5 +833,6 @@ $(document).ready(function() {
/// v1.2.0 pyOpenRPA Init defs
mGlobal.pyOpenRPA.ServerDataRefreshDef() // Init the refresh data def from server side
+ mGlobal.pyOpenRPA.ServerLogListRefreshDef() // Init the refresh data def from the log window
});
\ No newline at end of file
diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
index 7d948b0d..e63e8c61 100644
--- a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
+++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
@@ -279,7 +279,7 @@
Logs
-