Is it possible to use the System Event Log for logging custom events?
Hi community, the system event log by default is configured so we can track successful and failed login attempts. I wonder if we can also use the log to track other events of interest? E.g. I have a few C# Methods where I want to track when and how often the Methods fails. I have added a custom SystemEvent type for "MethodFailed". But when I use the following code, I will get the following error message: "Requested value "MethodFailed" was not found. CCO.SystemEventLogger.CreateSystemLogRecord("MethodFailed","Method_doSomething",inn.getUserID(),"Method xy failed, value z invalid" ); This line of code in a C# Method only works, when I use one of the standard OOTB system events: CCO.SystemEventLogger.CreateSystemLogRecord("SuccessfulLogin","Method_doSomething",inn.getUserID(),"Method xy failed, value z invalid" ); Is it possible to use own system events types at all? If yes, where do I have to add my custom event type? Or maybe someone know some other log options? I don´t want to build a separate ItemType for this use case. The System Event log would fit very well, cause it is checked and cleared on a regular basis anyway. Would be cool if somebody has an idea how to solve this one!Solved10KViews0likes5CommentsHow to Track the deleted Item
Hi Experts, In my system, I have created one ItemType called "PDT Projects". So, whatever the Items will get created and deleted under this "PDT Projects", I want to track those items. Is it possible to get deleted Items Log anywhere in the system? So I can show a report to end users these are the deleted Items by this user. Regards, Maddy.3.3KViews0likes1CommentCreate Server Logs
Dear Aras Community, I have the following problem. I want to activate the server logs. To do this, I set <operating_parameter key = "debug_log_flag" value = "true" /> as described in the instructions and restarted the server. The following error occurs when I want to log in ( Could not find a part of the path 'D:\ARASInstances\KPEC\Innovator\Server\logs\2021-12-23-11-04-59-26.xml'). Can you please help me? Best regards1.9KViews1like2CommentsCreate log file with CCO.Logger
Hello, I want to start using the CCO.Logger for creating log files and I didn't find any information about this. The only thing I found is a topic that the appsettings needs to be configured. I'm assuming that over there I can manage the writing level and also where the log file will be created. Currently my appsettings is looking like this: { "LoggerConfiguration": { "MinimumLevel": "Fatal", "WriteTo": [ { "Name": "Console" }, { "Name": "File" }, { "Name": "EventLog" } ] } } Is someone can point me to relevant documentation, or give me some examples, I will appreciate it. Thanks in advanceSolved217Views0likes6CommentsLogging & Progressbars Inside Innovator
In Aras, we have a lot of different automations running at any given time, and there is no clean way (I know of) to see them all in one place. Further, I don't have access to the server, so I can't access the log files you might typically see so I'm looking for a way to write those directly into Aras. So I set out to address these issues, by creating an ItemType called Progressbar with fields for tracking progress and on the form I created a html object and a button to trigger a 'ProgressBarClient' Method, which repeatedly calls a 'ProgressBarServer' Method multiple times. This gets me an interface to see the status of the processing... So before I spend too much time on this, I thought I'd see if the community has any ideas on better ways to approach this or ideas for improvement. Some thoughts: Using the button on the item probably wasn't the best move, it stops processing if you close the item. It also gave me a lot of headaches getting the typing right I should probably set it up so the C# method doesn't require a return to update the progress I was hoping for a live progressbar in the search grid... but using the html on the form isn't going to work because its not a property // Javascript Client Method: ProgressBarClient console.group("---Action Trigger---"); // ProgressBar ItemType Values // barmin - int - minimum value of progressbar // barmax - int - maximum value of progressbar // barvalue - int - current value of progressbar // barpercent - decimal - % complete, barvalue / barmax // currenttask - string - text description of current action // debuglog - Text - log of all activity // errorlog - Text - log of error messages console.log("Name: ProgressBar Prototype"); console.log("Description: This will call a server side method and update a progressbar"); console.log(""); console.log("Setting up progressbar..."); // --- Instantiate Innovator object at the beginning --- var inn; try { inn = new Innovator(); console.log("Innovator object instantiated successfully."); } catch (e) { console.error("CRITICAL ERROR: Failed to instantiate Innovator. The global 'Innovator' might not be a constructor or is not available. Error: " + e.message); alert("An internal error occurred. Please contact support. (Innovator instantiation failed)"); console.groupEnd(); return; } // Basic check to ensure 'inn' is a valid object after instantiation if (!inn || typeof inn.getItemById !== 'function') { console.error("CRITICAL ERROR: The 'inn' object does not have the expected Aras API methods (e.g., getItemById) even after instantiation."); alert("An internal error occurred. Please contact support. (Invalid Innovator object)"); console.groupEnd(); return; } console.log("Innovator object retrieved and validated."); // Get the current Aras Item object (assuming parent.item is available and is an XML DOM node) var currentArasItemXml = parent.item; if (!currentArasItemXml) { console.error("CRITICAL ERROR: Aras Item XML object (parent.item) could not be retrieved."); alert("An internal error occurred. Please contact support. (Aras Item XML not found)"); console.groupEnd(); return; } console.log("Current Aras Item XML object retrieved."); var itemId = currentArasItemXml.getAttribute('id'); console.log("item ID:" + itemId); var itemTypeName = currentArasItemXml.getAttribute('type'); console.log("item Type:" + itemTypeName); if (!itemId || !itemTypeName) { console.error("CRITICAL ERROR: Item ID or ItemType name not found from parent.item."); alert("An internal error occurred. Please contact support. (Item ID/Type missing)"); console.groupEnd(); return; } var currentArasItem = inn.getItemById(itemTypeName, itemId); if (currentArasItem.isError()) { console.error("CRITICAL ERROR: Failed to fetch full Aras Item object: " + currentArasItem.getErrorString()); alert("An internal error occurred. Please contact support. (Failed to fetch item)"); console.groupEnd(); return; } console.log("Full Aras Item object fetched."); // Find the form field control for our property var propName = "html0"; // This is correct based on your HTML inspection var fieldContainerEl; // This will be the <div> with name="html0" var targetHtmlEl; // This will be the inner <div class="sys_f_value"> // --- MODIFIED: Robust way to find the field element without aras.uiFindField --- console.log("Attempting to find field for property: " + propName + " directly in the DOM..."); // Try to find the element in the current document (most likely the iframe document) fieldContainerEl = document.getElementsByName(propName)[0]; // If not found, try to find it in the top document (less likely for form fields, but a fallback) if (!fieldContainerEl) { try { fieldContainerEl = top.document.getElementsByName(propName)[0]; } catch (e) { console.warn("Could not access top.document directly to find field. Error: " + e.message); } } if (!fieldContainerEl) { console.error("CRITICAL ERROR: Progress bar field '" + propName + "' not found on form. Please ensure the field's HTML 'name' attribute is '" + propName + "' and the form is loaded."); alert("Progress bar field '" + propName + "' not found on form. Please ensure the field's HTML 'name' attribute is '" + propName + "' and the form is loaded."); console.groupEnd(); return; } console.log("Progress bar field container element found. Name attribute used: " + fieldContainerEl.name); // Find the inner div with class "sys_f_value" to inject the HTML targetHtmlEl = fieldContainerEl.querySelector('.sys_f_value'); if (!targetHtmlEl) { console.error("CRITICAL ERROR: Could not find the inner '.sys_f_value' div within the '" + propName + "' field container."); alert("An internal error occurred. Please contact support. (Target HTML element for injection not found)"); console.groupEnd(); return; } console.log("Target HTML element for injection found."); // --- END MODIFIED SECTION --- // Create basic progress bar HTML function renderBar(percent, currentTask) { percent = Math.max(0, Math.min(100, percent)); return '' + '<div style="border:1px solid #999;width:100%;height:18px;background:#f5f5f5;">' + ' <div style="height:100%;width:' + percent + '%;background:#4caf50;transition:width 0.2s;"></div>' + '</div>' + '<div style="font-size:10px;margin-top:2px;">' + percent.toFixed(2) + '% ' + (currentTask ? '(' + currentTask + ')' : '') + '</div>'; } // Helper to set the field value + UI function setProgress(barvalue, barmax, currenttask) { var percent = (barmax > 0) ? (barvalue / barmax) * 100 : 0; var renderedHtml = renderBar(percent, currenttask); // Update rendered field in current UI targetHtmlEl.innerHTML = renderedHtml; } // Initialize at 0% setProgress(0, 100, "Initializing..."); console.log("Progress bar initialized to 0%."); // --- START: Replaced simulated work with Server Method call --- // Variables to maintain state across server calls var progressItemId = null; // Stores the ID of the Progressbar item created/updated by the server var currentStep = 0; // Stores the current step to send to the server // Function to call the server method and update progress function callServerMethodForProgress(initialCall) { console.log("Calling the server-side method 'ProgressBarServer'..."); var serverMethod = inn.newItem("Method", "ProgressBarServer"); serverMethod.setProperty("itemId", itemId); // Pass the ID of the item that triggered this client method serverMethod.setProperty("itemTypeName", itemTypeName); // Pass the ItemType name serverMethod.setProperty("initialCall", initialCall ? "true" : "false"); serverMethod.setProperty("progressItemId", progressItemId || ""); // Pass the ID of the Progressbar item serverMethod.setProperty("currentStep", currentStep.toString()); // Pass the current step var result = serverMethod.apply(); if (result.isError()) { var errorMsg = result.getErrorString(); console.error("Server method 'ProgressBarServer' error: " + errorMsg); alert("Server method error: " + errorMsg); setProgress(0, 100, "Error: " + errorMsg); // Show error in progress bar console.groupEnd(); return; // Stop progress } // Parse the response from the server method var progressItem = result.getItemByIndex(0); if (!progressItem || progressItem.isError()) { console.error("Server method 'ProgressBarServer' returned an invalid or empty item."); alert("Server method returned invalid data."); setProgress(0, 100, "Error: Invalid server response"); console.groupEnd(); return; } // Extract properties from the server's response progressItemId = progressItem.getProperty("id", progressItemId); // Update progressItemId if it's the first call var barmin = parseInt(progressItem.getProperty("barmin", "0")); var barmax = parseInt(progressItem.getProperty("barmax", "100")); var barvalue = parseInt(progressItem.getProperty("barvalue", "0")); var barpercent = parseFloat(progressItem.getProperty("barpercent", "0")); var currenttask = progressItem.getProperty("currenttask", "Processing..."); var debuglog = progressItem.getProperty("debuglog", ""); var errorlog = progressItem.getProperty("errorlog", ""); var isComplete = progressItem.getProperty("is_complete", "false") === "true"; currentStep = parseInt(progressItem.getProperty("next_step", (currentStep + 1).toString())); // Get next step from server console.log("Server response - Value: " + barvalue + ", Max: " + barmax + ", Task: " + currenttask + ", Complete: " + isComplete + ", Progress Item ID: " + progressItemId); if (debuglog) console.log("Server Debug Log:\n" + debuglog); if (errorlog) console.error("Server Error Log:\n" + errorlog); // Update the client-side progress bar setProgress(barvalue, barmax, currenttask); // Persist the progress to the Progressbar ItemType (if it's the item being edited) // This assumes the form you are on *is* the Progressbar ItemType form. // If this client method is on a *different* ItemType's form, you would need to // load the Progressbar item by its ID and update its properties. if (itemTypeName === "Progressbar" && itemId === progressItemId) { currentArasItem.setProperty("barmin", barmin.toString()); currentArasItem.setProperty("barmax", barmax.toString()); currentArasItem.setProperty("barvalue", barvalue.toString()); currentArasItem.setProperty("barpercent", barpercent.toFixed(2)); currentArasItem.setProperty("currenttask", currenttask); currentArasItem.setProperty("debuglog", debuglog); currentArasItem.setProperty("errorlog", errorlog); // Note: This only updates the client-side item object. // To save to the database, the user would need to click 'Save' on the form, // or you would need to explicitly call currentArasItem.apply("update") here, // which might be too frequent and cause performance issues. // The server method already saves the Progressbar item. } else { // If the client method is on a different ItemType, we need to explicitly update the Progressbar item // This is an example of how to update the Progressbar item from a different context var updateProgressItem = inn.newItem("Progressbar", "edit"); updateProgressItem.setID(progressItemId); updateProgressItem.setProperty("barmin", barmin.toString()); updateProgressItem.setProperty("barmax", barmax.toString()); updateProgressItem.setProperty("barvalue", barvalue.toString()); updateProgressItem.setProperty("barpercent", barpercent.toFixed(2)); updateProgressItem.setProperty("currenttask", currenttask); updateProgressItem.setProperty("debuglog", debuglog); updateProgressItem.setProperty("errorlog", errorlog); // updateProgressItem.apply("update"); // Uncomment if you want to save from client, but server already does this. } if (!isComplete) { // If not complete, call the server method again after a short delay setTimeout(function () { callServerMethodForProgress(false); }, 500); // Adjust delay as needed } else { inn.showStatusMessage("Processing completed.", "info"); console.log("Processing completed."); console.groupEnd(); } } // Start the process by making the initial call to the server method callServerMethodForProgress(true); // --- END: Replaced simulated work --- console.log("Notify user of completion (handled by showStatusMessage)"); // C# Server Method: ProgressBarServer Innovator innovator = this.getInnovator(); // Get parameters from the client string progressItemId = this.getProperty("itemId"); string currentStepStr = this.getProperty("currentStep", "0"); int currentStep = int.Parse(currentStepStr); Item progressBarItem; int barmin = 0; int barmax = 10; // Define total steps for the simulated task // --- Step 1: Load the existing Progressbar Item --- if (string.IsNullOrEmpty(progressItemId)) { return innovator.newError("Error: 'progressItemId' is required but was not provided. The Progressbar item must exist."); } // Load the item first to get its current state progressBarItem = innovator.newItem("Progressbar", "get"); progressBarItem.setID(progressItemId); progressBarItem = progressBarItem.apply(); if (progressBarItem.isError()) { return innovator.newError("Failed to load Progressbar item (ID: " + progressItemId + "): " + progressBarItem.getErrorString()); } // Ensure barmax is consistent if it was set on creation barmax = int.Parse(progressBarItem.getProperty("barmax", barmax.ToString())); // --- Step 2: Attempt to lock the item for update --- // Use the loaded item to attempt the lock. // This is important: applying 'lock' on the loaded item ensures we're working with the same item instance. Item lockResult = progressBarItem.apply("lock"); if (lockResult.isError()) { string errorString = lockResult.getErrorString(); // Check for the specific Aras error message indicating it's already locked by *this* user. // The exact message for "already locked by current user" can vary slightly. // We'll use a broader check for "locked" and then check the user. if (errorString.Contains("Item is already locked") || errorString.Contains("Aras.Server.Core.ItemIsAlreadyLockedException")) { // Now, check *who* locked it. // Get the locked_by property from the item (if it exists and is populated) string lockedById = progressBarItem.getProperty("locked_by_id", ""); string currentUserId = innovator.getUserID(); if (lockedById == currentUserId) { // Item is already locked by the current user. This is expected in polling. // Proceed with the update. No error needed. System.Diagnostics.Trace.WriteLine("DEBUG: Progressbar item (ID: " + progressItemId + ") already locked by current user. Proceeding."); } else if (!string.IsNullOrEmpty(lockedById)) { // Item is locked by another user. This is a genuine conflict. Item lockedByUser = innovator.getItemById("User", lockedById); string lockedByUserName = lockedByUser.getProperty("keyed_name", "Unknown User"); return innovator.newError("Failed to lock Progressbar item (ID: " + progressItemId + "): Item is already locked by another user: " + lockedByUserName + "."); } else { // Item is locked, but locked_by_id is not set or couldn't be determined. // This might indicate a stale lock or an unexpected state. return innovator.newError("Failed to lock Progressbar item (ID: " + progressItemId + "): Item is already locked, but the locker could not be identified. Error: " + errorString); } } else { // Some other locking error occurred. return innovator.newError("Failed to lock Progressbar item (ID: " + progressItemId + "): " + errorString); } } // If lockResult is not an error, or if it was already locked by current user, // the progressBarItem is now locked by this session and ready for update. // --- Step 3: Simulate work and update progress --- string currentTaskDescription = ""; bool isComplete = false; // Simulate different steps switch (currentStep) { case 0: currentTaskDescription = "Step 1: Preparing data..."; System.Threading.Thread.Sleep(500); // Simulate work break; case 1: currentTaskDescription = "Step 2: Processing records..."; System.Threading.Thread.Sleep(700); // Simulate work break; case 2: currentTaskDescription = "Step 3: Validating inputs..."; System.Threading.Thread.Sleep(400); // Simulate work break; case 3: currentTaskDescription = "Step 4: Performing calculations..."; System.Threading.Thread.Sleep(800); // Simulate work break; case 4: currentTaskDescription = "Step 5: Generating reports..."; System.Threading.Thread.Sleep(600); // Simulate work break; case 5: currentTaskDescription = "Step 6: Saving results..."; System.Threading.Thread.Sleep(500); // Simulate work break; case 6: currentTaskDescription = "Step 7: Finalizing process..."; System.Threading.Thread.Sleep(300); // Simulate work break; case 7: currentTaskDescription = "Step 8: Cleaning up temporary files..."; System.Threading.Thread.Sleep(200); // Simulate work break; case 8: currentTaskDescription = "Step 9: Notifying stakeholders..."; System.Threading.Thread.Sleep(100); // Simulate work break; case 9: currentTaskDescription = "Step 10: Task completed."; isComplete = true; break; default: currentTaskDescription = "Unknown step or task completed."; isComplete = true; break; } // Update properties on the progressBarItem object int barvalue = currentStep + 1; // Increment value for the next step if (isComplete) barvalue = barmax; // Ensure it reaches max when complete double barpercent = (double)barvalue / barmax * 100; progressBarItem.setProperty("barvalue", barvalue.ToString()); progressBarItem.setProperty("barpercent", barpercent.ToString("F2")); // Format to 2 decimal places progressBarItem.setProperty("currenttask", currentTaskDescription); progressBarItem.setProperty("debuglog", progressBarItem.getProperty("debuglog", "") + currentTaskDescription + " at " + DateTime.Now.ToString("HH:mm:ss") + "\n"); // --- Step 4: Persist the updated Progressbar item --- // At this point, progressBarItem *must* be locked by this session. Item updateResult = progressBarItem.apply("update"); if (updateResult.isError()) { // If update fails here, it's a critical error. // This could still be a locking issue if the lock was somehow lost or not acquired correctly. return innovator.newError("Failed to update Progressbar item (ID: " + progressItemId + "): " + updateResult.getErrorString()); } // --- Step 5: Prepare the response for the client --- Item resultItem = innovator.newItem("Progressbar", "get"); // Return the updated Progressbar item resultItem.setProperty("id", progressItemId); // Ensure the ID is returned resultItem.setProperty("barmin", progressBarItem.getProperty("barmin")); resultItem.setProperty("barmax", progressBarItem.getProperty("barmax")); resultItem.setProperty("barvalue", progressBarItem.getProperty("barvalue")); resultItem.setProperty("barpercent", progressBarItem.getProperty("barpercent")); resultItem.setProperty("currenttask", progressBarItem.getProperty("currenttask")); resultItem.setProperty("debuglog", progressBarItem.getProperty("debuglog")); resultItem.setProperty("errorlog", progressBarItem.getProperty("errorlog")); resultItem.setProperty("is_complete", isComplete ? "true" : "false"); resultItem.setProperty("next_step", (currentStep + 1).ToString()); // Tell client the next step to send // --- Step 6: Unlock the item if the task is complete --- Item unlockResult = progressBarItem.apply("unlock"); // Unlock the item that was locked if (unlockResult.isError()) { // Log the unlock error, but don't fail the entire method as the task is complete. System.Diagnostics.Trace.WriteLine("ERROR: Failed to unlock Progressbar item (ID: " + progressItemId + "): " + unlockResult.getErrorString()); } return resultItem;200Views0likes4Comments