Skip to content

Logging screen implementation#163

Open
soujanyadhungel wants to merge 2 commits intopariyatti:masterfrom
soujanyadhungel:logging-screen-implementation
Open

Logging screen implementation#163
soujanyadhungel wants to merge 2 commits intopariyatti:masterfrom
soujanyadhungel:logging-screen-implementation

Conversation

@soujanyadhungel
Copy link
Copy Markdown
Contributor

Creating pull request for Issue #8.

  • LogEntry class: Represents individual log entries with timestamp, message, and level information.
  • LogManager class: Manages log entries with constraints on both count (1000 entries) and memory usage (10MB).
  • Updated log.dart to integrate with the new LogManager while maintaining backward compatibility.
  • Enhanced the LogsScreen to display logs
  • Updated main_common.dart to initialize the logging system and add initial log entries.

@soujanyadhungel soujanyadhungel requested a review from deobald as a code owner March 1, 2025 04:16
Copy link
Copy Markdown
Member

@deobald deobald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @soujanyadhungel there are some necessary changes to make before this can be merged.

Also, if you can please pull from pariyatti:master to incorporate the latest changes to master into your branch before we merge it, that would be good.

"nothing_bookmarked": "您還沒有書籤",
"only_english": "目前僅提供英文作為替代語言",
"pali_word": "每日一个巴利语单词",
"pali_word": "每日一个巴利語單詞",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has this line changed? This PR shouldn't be changing translations for Pali Word, since that is unrelated.

"try_again_later": "發生錯誤,請稍後再試。",
"was_empty": "沒有內容",
"words_of_the_buddha": "佛陀每日法语"
"words_of_the_buddha": "佛陀每日法語",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as with Pali Word: why has this Chinese translation changed in this PR? This PR should only make changes related to logging.

/// Adds a new log entry to the queue, respecting size and memory constraints
void addLog(String message, String level) {
final entry = LogEntry(message, level);
final entrySize = entry.estimatedSize;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not do this. The following while loop is kind of convoluted and I'm not sure the constraint on memory usage is required. I think that having a max count of 1000 entries will be fine. If that size goes over 10MB by a small amount it's not a big deal. I think trying to constrain the memory usage by the estimated size of the entries makes the code too hard to read.

Feel free to push back if you think this is essential for low-power devices.

/// - File-based persistent logging with rotation
/// - Console logging for debugging
/// - Multiple severity levels (debug, info, warning, error)
class AppLogger {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please name the file and class the same: app_logger.dart


// In-memory circular buffer
static final List<String> _memoryLogs = [];
static const int _maxMemoryLogs = 1000;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's important that this 1000 log entry limit is the same as the other 1000 from LogManager, that number should be defined in a single place so it's not repeated.

),
body: _isLoading
? Center(child: CircularProgressIndicator())
: _logs.isEmpty
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting from the end of the first ternary operator (x ? y : z), you should extract a function/method to return the rest of this data. Don't nest code this deeply, even in Flutter UI stuff.

In general, we don't ever want to nest ternary operators. 9/10 times, a ternary operator is the wrong choice if it doesn't fit on a single line:

a ? b : c is good

a
? b
: c

...is much less good and probably deserves an if/else statement instead.

body: _isLoading
? Center(child: CircularProgressIndicator())
: _logs.isEmpty
? Center(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once extracted into its own function, then the check on _logs.isEmpty can be an if/else which returns the 'logs_empty' Text widget below and in the else clause returns an entirely new function (appropriately named logsWithContent or something) with the RefreshIndicator at the top level.

color: isError
? Theme.of(context).colorScheme.errorContainer
: isWarning
? Theme.of(context).colorScheme.secondaryContainer
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even shallowly-nested ternary operators are extremely hard to read. This is less of a problem than the top-level ternary operators but I would say all of the right-hand-side of color: could be extracted into its own function and it would make it clearer, whether you switch away from nested ternary operators or not.

}

// Write to persistent storage
_writeToFile(logMessage);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the in-memory log is the only one used in the UI (as far as I can tell), why do we bother writing the logs to disk at all?

Preferably, we would only use the disk-based log for all our purposes, since I don't understand the value of the in-memory logs, and the on-disk logs could be shared in the event of a crash. At the moment, if the app crashes and then the user tries to share the logs, they are sharing the empty in-memory log, not the on-disk log which would contain the events before the crash.

Let me know if this question makes sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants