-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Log Refactor #14087
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?
Log Refactor #14087
Conversation
package org.signal.glide.transforms; | ||
|
||
public record LogMessage(String value) { | ||
public LogMessage { | ||
if (value == null || value.isBlank()) { | ||
throw new IllegalArgumentException("LogMessage cannot be null or blank"); | ||
} | ||
} | ||
} |
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.
I noticed that this PR introduces a new file in Java, while we're in the midst of migrating our codebase to Kotlin. Is there a particular reason we opted for Java here instead of Kotlin?
Would it be possible to implement this new functionality in Kotlin to maintain consistency with our migration efforts?
package org.signal.glide.transforms; | ||
|
||
public record LogTag(String value) { | ||
public LogTag { | ||
if (value == null || value.isBlank()) { | ||
throw new IllegalArgumentException("LogTag cannot be null or blank"); | ||
} | ||
} | ||
} |
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.
Same as above
package org.signal.glide.transforms; | ||
|
||
import androidx.annotation.Nullable; | ||
|
||
public interface LoggingService { | ||
void logDebug(LogTag tag, LogMessage message); | ||
void logInfo(LogTag tag, LogMessage message); | ||
void logWarn(LogTag tag, LogMessage message); | ||
void logError(LogTag tag, LogMessage message, @Nullable Throwable throwable); | ||
} |
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.
Same as above
Hi! Thank you for choosing Signal for your university software architecture course :) . I'm going to caution against opening a pr to change our logging mechanism. Logging is crucial to working on and improving Signal and it is something that works well. A new refactor will be difficult to review meaningfully and still lead to its own specific set of bugs which we want to avoid, given how vital and functional logging is. |
Overview
We propose refactoring the Log utility in org.signal.glide to better align with DDD principles by introducing the following:
A LoggingService interface.
LogTag and LogMessage value objects.
Moving implementation details to the infrastructure layer.
This will decouple logging from domain logic, improve modularity, and enhance testability. During a deep dive into the Signal Android codebase for a university software architecture course, our team identified a tight coupling between domain logic and infrastructure in the current logging mechanism.
The static, global access to logging (SignalGlideCodecs.getLogProvider()) and raw strings for tags/messages make logging less flexible, error-prone, and more complicated to test. It is this idea we are targeting for our refactoring.
Problems Identified
Tight Coupling to static global state (SignalGlideCodecs).
There is no Abstraction between domain logic and infrastructure.
Strongly typed metadata, which reduces clarity and consistency.
Logging Output Loss due to silent fallback EMPTY Provider.
Benefits
Improved separation of concerns.
Consistent and error-resistant metadata handling.
Aligns logging infrastructure with DDD best practices.
We’re happy to submit a Draft Pull Request with this implementation for further discussion if the maintainers are interested. We would love to hear your thoughts.
Proposed Refactor
Abstract Logging Behind a Service Interface
public interface LoggingService {
void logInfo(LogTag tag, LogMessage message);
void logError(LogTag tag, LogMessage message, @nullable Throwable throwable);
}
Introduce Value Objects for Log Metadata
public record LogTag(String value) { }
public record LogMessage(String value) { }
Move the Implementation to the Infrastructure Layer
public class AndroidLoggingService implements LoggingService {
public void logInfo(LogTag tag, LogMessage message) {
SignalGlideCodecs.getLogProvider().i(tag.value(), message.value());
}
public void logError(LogTag tag, LogMessage message, @nullable Throwable t) {
SignalGlideCodecs.getLogProvider().e(tag.value(), message.value(), t);
}
}
Thanks for your time and the great work on Signal