diff --git a/common/thorhelper/thorsoapcall.cpp b/common/thorhelper/thorsoapcall.cpp index b87a2bd4ec1..1970b44e6a0 100644 --- a/common/thorhelper/thorsoapcall.cpp +++ b/common/thorhelper/thorsoapcall.cpp @@ -50,6 +50,40 @@ using roxiemem::OwnedRoxieString; #define CONNECTION "Connection" unsigned soapTraceLevel = 1; +static StringBuffer soapSepString; + +void setSoapSepString(const char *_soapSepString) +{ + soapSepString.set(_soapSepString); +} + +static void multiLineAppendReplace(StringBuffer &origStr, StringBuffer &newStr) +{ + if (origStr.isEmpty()) + return; + + newStr.ensureCapacity(origStr.length()); + + const char *cursor = origStr; + while (*cursor) + { + switch (*cursor) + { + case '\r': + newStr.append(soapSepString); + if ('\n' == *(cursor+1)) + cursor++; + break; + case '\n': + newStr.append(soapSepString); + break; + default: + newStr.append(*cursor); + break; + } + ++cursor; + } +} #define WSCBUFFERSIZE 0x10000 #define MAXWSCTHREADS 50 //Max Web Service Call Threads @@ -1940,10 +1974,18 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo { if (soapTraceLevel > 6 || master->logXML) { - if (!contentEncoded) - master->logctx.mCTXLOG("%s: request(%s)", master->wscCallTypeText(), request.str()); + StringBuffer contentStr; + if (contentEncoded) + contentStr.append(", content encoded."); + // Only do translation if soapcall LOG option set and soapSepString defined + if ( (master->logXML) && (soapSepString.length() > 0) ) + { + StringBuffer request2; + multiLineAppendReplace(request, request2); + master->logctx.CTXLOG("%s: request(%s)%s", master->wscCallTypeText(), request2.str(), contentStr.str()); + } else - master->logctx.mCTXLOG("%s: request(%s), content encoded.", master->wscCallTypeText(), request.str()); + master->logctx.mCTXLOG("%s: request(%s)%s", master->wscCallTypeText(), request.str(), contentStr.str()); } } @@ -2247,9 +2289,18 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo if (checkContentDecoding(dbgheader, response, contentEncoding)) decodeContent(contentEncoding.str(), response); if (soapTraceLevel > 6 || master->logXML) - master->logctx.mCTXLOG("%s: LEN=%d %sresponse(%s%s)", getWsCallTypeName(master->wscType),response.length(),chunked?"CHUNKED ":"", dbgheader.str(), response.str()); - else if (soapTraceLevel > 8) - master->logctx.mCTXLOG("%s: LEN=%d %sresponse(%s)", getWsCallTypeName(master->wscType),response.length(),chunked?"CHUNKED ":"", response.str()); // not sure this is that useful but... + { + // Only do translation if soapcall LOG option set and soapSepString defined + if ( (master->logXML) && (soapSepString.length() > 0) ) + { + StringBuffer response2; + multiLineAppendReplace(dbgheader, response2); + multiLineAppendReplace(response, response2); + master->logctx.CTXLOG("%s: LEN=%d %sresponse(%s)", getWsCallTypeName(master->wscType),response.length(),chunked?"CHUNKED ":"", response2.str()); + } + else + master->logctx.mCTXLOG("%s: LEN=%d %sresponse(%s%s)", getWsCallTypeName(master->wscType),response.length(),chunked?"CHUNKED ":"", dbgheader.str(), response.str()); + } return rval; } diff --git a/common/thorhelper/thorsoapcall.hpp b/common/thorhelper/thorsoapcall.hpp index aa1c97a6c22..4ea42feef69 100644 --- a/common/thorhelper/thorsoapcall.hpp +++ b/common/thorhelper/thorsoapcall.hpp @@ -86,5 +86,6 @@ interface IRoxieAbortMonitor extern THORHELPER_API unsigned soapTraceLevel; extern THORHELPER_API IWSCHelper * createSoapCallHelper(IWSCRowProvider *, IEngineRowAllocator * outputAllocator, const char *authToken, SoapCallMode scMode, ClientCertificate *clientCert, const IContextLogger &logctx, IRoxieAbortMonitor * roxieAbortMonitor); extern THORHELPER_API IWSCHelper * createHttpCallHelper(IWSCRowProvider *, IEngineRowAllocator * outputAllocator, const char *authToken, SoapCallMode scMode, ClientCertificate *clientCert, const IContextLogger &logctx, IRoxieAbortMonitor * roxieAbortMonitor); +extern THORHELPER_API void setSoapSepString(const char *_soapSepString); #endif /* __THORSOAPCALL_HPP_ */ diff --git a/ecl/hthor/hthor.cpp b/ecl/hthor/hthor.cpp index e00fb39bcb7..610c15507cc 100644 --- a/ecl/hthor/hthor.cpp +++ b/ecl/hthor/hthor.cpp @@ -7738,6 +7738,10 @@ void CHThorWSCBaseActivity::init() JBASE64_Encode(uidpair.str(), uidpair.length(), authToken, false); } soapTraceLevel = agent.queryWorkUnit()->getDebugValueInt("soapTraceLevel", 1); + StringBuffer soapSepStr; + StringBufferAdaptor soapSepAdaptor(soapSepStr); + agent.queryWorkUnit()->getDebugValue("soapLogSepString", soapSepAdaptor); + setSoapSepString(soapSepStr.str()); } //--------------------------------------------------------------------------- diff --git a/esp/src/eclwatch/WUDetailsWidget.js b/esp/src/eclwatch/WUDetailsWidget.js index c7d2c331af0..411bba32c52 100644 --- a/esp/src/eclwatch/WUDetailsWidget.js +++ b/esp/src/eclwatch/WUDetailsWidget.js @@ -117,6 +117,16 @@ define([ this.emailFrom = registry.byId(this.id + "EmailFrom"); this.emailSubject = registry.byId(this.id + "EmailSubject"); this.emailBody = registry.byId(this.id + "EmailBody"); + + //Zap LogFilters + this.logFilterStartDateTime = dom.byId(this.id + "StartDateTime"); + this.logFilterStartDate = registry.byId(this.id + "StartDate"); + this.logFilterStartTime = registry.byId(this.id + "StartTime"); + this.logFilterEndDateTime = dom.byId(this.id + "EndDateTime"); + this.logFilterEndDate = registry.byId(this.id + "EndDate"); + this.logFilterEndTime = registry.byId(this.id + "EndTime"); + this.logFilterRelativeTimeRangeBuffer = registry.byId(this.id + "RelativeTimeRangeBuffer"); + this.protected = registry.byId(this.id + "Protected"); this.infoGridWidget = registry.byId(this.id + "InfoContainer"); this.zapDialog = registry.byId(this.id + "ZapDialog"); @@ -146,14 +156,33 @@ define([ this.checkThorLogStatus(); }, + formatLogFilterDateTime: function (dateField, timeField, dateTimeField) { + if (dateField.value.toString() !== "Invalid Date") { + const d = new Date(dateField.value); + const date = `${d.getFullYear()}-${(d.getMonth() < 9 ? "0" : "") + parseInt(d.getMonth() + 1, 10)}-${d.getDate()}`; + const time = timeField.value.toString().replace(/.*1970\s(\S+).*/, "$1"); + dateTimeField.value = `${date}T${time}.000Z`; + } + }, + _onSubmitDialog: function () { var context = this; var includeSlaveLogsCheckbox = this.includeSlaveLogsCheckbox.get("checked"); + if (this.logFilterRelativeTimeRangeBuffer.value !== "") { + this.logFilterEndDate.required = ""; + this.logFilterStartDate.required = ""; + } if (this.zapForm.validate()) { //WUCreateAndDownloadZAPInfo is not a webservice so relying on form to submit. //Server treats "on" and '' as the same thing. this.includeSlaveLogsCheckbox.set("value", includeSlaveLogsCheckbox ? "on" : "off"); + + // Log Filters + this.formatLogFilterDateTime(this.logFilterStartDate, this.logFilterStartTime, this.logFilterStartDateTime); + this.formatLogFilterDateTime(this.logFilterEndDate, this.logFilterEndTime, this.logFilterEndDateTime); + this.zapForm.set("action", "/WsWorkunits/WUCreateAndDownloadZAPInfo"); + this.zapDialog.hide(); this.checkThorLogStatus(); if (this.logAccessorMessage !== "") { diff --git a/esp/src/eclwatch/css/hpcc.css b/esp/src/eclwatch/css/hpcc.css index 26559935861..e6d0e6f6f0b 100644 --- a/esp/src/eclwatch/css/hpcc.css +++ b/esp/src/eclwatch/css/hpcc.css @@ -74,6 +74,10 @@ form li label { padding-top: 4px; } +.dijitDialogPaneContent { + overflow-x: hidden !important; +} + .dijitDialogPaneContent form li label { float: left; width: 25%; diff --git a/esp/src/eclwatch/templates/WUDetailsWidget.html b/esp/src/eclwatch/templates/WUDetailsWidget.html index a56d36ec15c..ef58752e1a6 100644 --- a/esp/src/eclwatch/templates/WUDetailsWidget.html +++ b/esp/src/eclwatch/templates/WUDetailsWidget.html @@ -183,7 +183,7 @@