-
Notifications
You must be signed in to change notification settings - Fork 39
Include Channel Name in server log #206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Include Channel Name in server log #206
Conversation
client/src/com/mirth/connect/plugins/serverlog/ServerLogPanel.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChain.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/plugins/serverlog/ArrayAppender.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/plugins/serverlog/ServerLogItem.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationConnector.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/Channel.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/Channel.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChain.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationConnector.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/plugins/serverlog/ArrayAppender.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/plugins/serverlog/ServerLogItem.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/plugins/serverlog/ServerLogProvider.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/server/util/javascript/JavaScriptTask.java
Outdated
Show resolved
Hide resolved
9fce32c to
3c94136
Compare
|
@mgaffigan Thoughts on the map implementation? Did you have this in mind when you suggested a map? |
Signed-off-by: Nico Piel <nicopiel@mailbox.org> Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nicopiel@mailbox.org> Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nicopiel@mailbox.org> Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nicopiel@mailbox.org> Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nicopiel@mailbox.org> Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Changes the ArrayAppender to construct a ServerLogItem directly instead of passing individual log properties. The ServerLogProvider now accepts a ServerLogItem, extracts the log properties, adds the server ID and log ID, and then passes the log item to the log controller. This change simplifies the code and makes it more efficient by reducing the number of parameters passed and centralizing the creation of the ServerLogItem. Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Ensures that the ServerLogItem properties are initialized with default values when retrieving them from the context. This prevents null pointer exceptions or unexpected behavior when these properties are not explicitly set in the context. Signed-off-by: Nico Piel <nico.piel@hotmail.de>
2482499 to
53a85d9
Compare
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
a418b01 to
278d2b3
Compare
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
469b1c1 to
b1623c9
Compare
client/src/com/mirth/connect/plugins/serverlog/ServerLogClient.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/Channel.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChain.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationConnector.java
Outdated
Show resolved
Hide resolved
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationConnector.java
Outdated
Show resolved
Hide resolved
server/src/com/mirth/connect/server/servlets/SwaggerExamplesServlet.java
Show resolved
Hide resolved
server/src/com/mirth/connect/server/util/javascript/JavaScriptTask.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChain.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Nico Piel <nico.piel@hotmail.de>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds channel name information to server logs by propagating channel context through Log4j's ThreadContext mechanism. The implementation spans three main components: server-side logging infrastructure, the Donkey engine threading model, and the client UI.
Key changes:
- Modified
ServerLogItemto store channel information in an attributes map with convenient getter/setter methods - Updated all channel-related thread entry points to populate
ThreadContextwith channel ID and name usingCloseableThreadContext - Enhanced the server log UI table to display a new "Channel" column
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| server/src/com/mirth/connect/server/util/javascript/JavaScriptTask.java | Added ThreadContext population with channel info in JavaScript task execution |
| server/src/com/mirth/connect/plugins/serverlog/ServerLogProvider.java | Updated method signature to accept attributes map for channel information |
| server/src/com/mirth/connect/plugins/serverlog/ServerLogItem.java | Added attributes map to store channel data with dedicated getter/setter methods |
| server/src/com/mirth/connect/plugins/serverlog/ArrayAppender.java | Modified to extract context data from Log4j events and pass to provider |
| donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationConnector.java | Wrapped queue thread execution with ThreadContext for channel info |
| donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChainProvider.java | Added channelName field with getter/setter |
| donkey/src/main/java/com/mirth/connect/donkey/server/channel/DestinationChain.java | Added ThreadContext population in chain execution threads |
| donkey/src/main/java/com/mirth/connect/donkey/server/channel/Channel.java | Updated to set channel name on chain providers and populate ThreadContext in dispatch/queue threads |
| client/src/com/mirth/connect/plugins/serverlog/ServerLogPanel.java | Added "Channel" column to server log table and adjusted column indices |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .put("channelId", channelId) | ||
| .put("channelName", name) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When channelId or name are null (which can happen in tests or partially initialized channels), passing null values to CloseableThreadContext.put() may cause issues. Consider adding null checks or using StringUtils.defaultString() to provide empty strings instead of null values.
Example:
try (CloseableThreadContext.Instance ctc = CloseableThreadContext
.put("channelId", StringUtils.defaultString(channelId))
.put("channelName", StringUtils.defaultString(name))
) {| .put("channelId", channelId) | |
| .put("channelName", name) | |
| .put("channelId", StringUtils.defaultString(channelId)) | |
| .put("channelName", StringUtils.defaultString(name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If null is unacceptable (refer to Log4j docs), then the call to put should be omitted. Empty string does not seem semantically better than null. "fear" of nulls is foolish - equivalent to adding try-catch all over the place. Either null is valid or it is not.
| // Add channel info to ThreadContext | ||
| try (CloseableThreadContext.Instance ctc = CloseableThreadContext | ||
| .put("channelId", getChannelId()) | ||
| .put("channelName", channel.getName()) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When channel.getName() returns null (which can happen in tests or partially initialized channels), passing null values to CloseableThreadContext.put() may cause issues. Consider adding null checks or using StringUtils.defaultString() to provide empty strings instead of null values.
Example:
try (CloseableThreadContext.Instance ctc = CloseableThreadContext
.put("channelId", StringUtils.defaultString(getChannelId()))
.put("channelName", StringUtils.defaultString(channel.getName()))
) {| .put("channelName", channel.getName()) | |
| .put("channelName", StringUtils.defaultString(channel.getName())) |
| public void setChannelId(String channelId) { | ||
| this.attributes.put("channelId", channelId); | ||
| } |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setChannelId method doesn't check if attributes is null before calling put(). If setAttributes(null) was called previously, or if the attributes map becomes null through some other means, this will throw a NullPointerException. The setAttributes method ensures the map is never null, but adding a null check here would make this method more defensive.
Example:
public void setChannelId(String channelId) {
if (this.attributes != null) {
this.attributes.put("channelId", channelId);
}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attributes should never be null. If there's no way for it to be null, then this is bad advice.
|
|
||
| @JsonIgnore | ||
| public void setChannelName(String channelName) { | ||
| this.attributes.put("channelName", channelName); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setChannelName method doesn't check if attributes is null before calling put(). If setAttributes(null) was called previously, or if the attributes map becomes null through some other means, this will throw a NullPointerException. The setAttributes method ensures the map is never null, but adding a null check here would make this method more defensive.
Example:
public void setChannelName(String channelName) {
if (this.attributes != null) {
this.attributes.put("channelName", channelName);
}
}| this.attributes.put("channelName", channelName); | |
| if (this.attributes != null) { | |
| this.attributes.put("channelName", channelName); | |
| } |
| .put("channelName", channelName) | ||
| ) { | ||
| Thread.currentThread().setName(threadName + " < " + originalThreadName); | ||
|
|
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace on this line should be removed.
| .put("channelId", channelId) | ||
| .put("channelName", name) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When channelId or name are null (which can happen in tests or partially initialized channels), passing null values to CloseableThreadContext.put() may cause issues. Consider adding null checks or using StringUtils.defaultString() to provide empty strings instead of null values.
Example:
try (CloseableThreadContext.Instance ctc = CloseableThreadContext
.put("channelId", StringUtils.defaultString(channelId))
.put("channelName", StringUtils.defaultString(name))
) {| .put("channelId", channelId) | |
| .put("channelName", name) | |
| .put("channelId", StringUtils.defaultString(channelId)) | |
| .put("channelName", StringUtils.defaultString(name)) |
| } else { | ||
| connectorMessage.setStatus(Status.ERROR); | ||
| connectorMessage.setProcessingError("Queued message has not yet been transformed, and Include Filter/Transformer is currently disabled."); | ||
| connectorMessage.setProcessingError("Mismatched connector properties detected in queued message. The connector type may have changed since the message was queued.\nFOUND: " + serializedPropertiesClass.getSimpleName() + "\nEXPECTED: " + connectorPropertiesClass.getSimpleName()); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable serializedPropertiesClass may be null at this access because of this assignment.
| connectorMessage.setProcessingError("Mismatched connector properties detected in queued message. The connector type may have changed since the message was queued.\nFOUND: " + serializedPropertiesClass.getSimpleName() + "\nEXPECTED: " + connectorPropertiesClass.getSimpleName()); | |
| connectorMessage.setProcessingError("Mismatched connector properties detected in queued message. The connector type may have changed since the message was queued.\nFOUND: " + (serializedPropertiesClass != null ? serializedPropertiesClass.getSimpleName() : "null") + "\nEXPECTED: " + connectorPropertiesClass.getSimpleName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No changes were made to this line of code. If there's an issue, it's pre-existing and should be fixed in an unrelated PR.
| } | ||
| } | ||
| } catch (RuntimeException e) { | ||
| logger.error("Error processing queued " + (connectorMessage != null ? connectorMessage.toString() : "message (null)") + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ". This error is expected if the message was manually removed from the queue.", e); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is useless. connectorMessage cannot be null at this check, since it is guarded by ... != ....
| logger.error("Error processing queued " + (connectorMessage != null ? connectorMessage.toString() : "message (null)") + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ". This error is expected if the message was manually removed from the queue.", e); | |
| logger.error("Error processing queued " + connectorMessage.toString() + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ". This error is expected if the message was manually removed from the queue.", e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not changed - preexisting.
| return; | ||
| } catch (Throwable t) { | ||
| // Send a different error message to the server log, but still invalidate the queue buffer | ||
| logger.error("Error processing queued " + (connectorMessage != null ? connectorMessage.toString() : "message (null)") + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ".", t); |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is useless. connectorMessage cannot be null at this check, since it is guarded by ... != ....
| logger.error("Error processing queued " + (connectorMessage != null ? connectorMessage.toString() : "message (null)") + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ".", t); | |
| logger.error("Error processing queued " + connectorMessage.toString() + " for channel " + channel.getName() + " (" + channel.getChannelId() + ") on destination " + destinationName + ".", t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not changed. Preexisting.
Changelog:
Server:
ServerLogItemto includechannelName, updated constructor, getters/setters.ServerLogProviderto passchannelNametoServerLogItem.ArrayAppenderto extractchannelNameandchannelIdfrom Log4jThreadContext.JavaScriptTaskto populateThreadContextwith channel info.Donkey Engine:
Channelto populateThreadContextin dispatch and source queue threads.DestinationChainto populateThreadContextusing channel info.DestinationConnectorto populateThreadContextin queue threads.Client:
ServerLogPanelto add "Channel" column to the UI table.