Skip to content

Commit

Permalink
Merge pull request #601 from squidowl/feat/logging-buffer
Browse files Browse the repository at this point in the history
Feat/logging buffer
  • Loading branch information
tarkah authored Oct 1, 2024
2 parents 5629a05 + 5b84d1f commit 315d964
Show file tree
Hide file tree
Showing 23 changed files with 468 additions and 59 deletions.
6 changes: 6 additions & 0 deletions assets/fontello/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@
"css": "popup",
"code": 59406,
"src": "typicons"
},
{
"uid": "8ea66d97faf9816abd34f48f3f26d216",
"css": "bucket",
"code": 59408,
"src": "entypo"
}
]
}
3 changes: 3 additions & 0 deletions data/src/config/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub struct Buttons {
pub reload_config: bool,
#[serde(default = "default_bool_true")]
pub theme_editor: bool,
#[serde(default = "default_bool_true")]
pub logs: bool,
}

impl Default for Buttons {
Expand All @@ -78,6 +80,7 @@ impl Default for Buttons {
command_bar: default_bool_true(),
reload_config: default_bool_true(),
theme_editor: default_bool_true(),
logs: default_bool_true(),
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions data/src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub enum Kind {
Server,
Channel(String),
Query(Nick),
Logs,
}

impl Kind {
Expand All @@ -39,6 +40,7 @@ impl Kind {
Kind::Server => None,
Kind::Channel(channel) => Some(channel),
Kind::Query(nick) => Some(nick.as_ref()),
Kind::Logs => None,
}
}
}
Expand All @@ -49,6 +51,7 @@ impl fmt::Display for Kind {
Kind::Server => write!(f, "server"),
Kind::Channel(channel) => write!(f, "channel {channel}"),
Kind::Query(nick) => write!(f, "user {}", nick),
Kind::Logs => write!(f, "logs"),
}
}
}
Expand All @@ -59,6 +62,7 @@ impl From<message::Target> for Kind {
message::Target::Server { .. } => Kind::Server,
message::Target::Channel { channel, .. } => Kind::Channel(channel),
message::Target::Query { nick, .. } => Kind::Query(nick),
message::Target::Logs => Kind::Logs,
}
}
}
Expand Down Expand Up @@ -154,6 +158,7 @@ async fn path(server: &server::Server, kind: &Kind) -> Result<PathBuf, Error> {
Kind::Server => format!("{server}"),
Kind::Channel(channel) => format!("{server}channel{channel}"),
Kind::Query(nick) => format!("{server}nickname{}", nick),
Kind::Logs => "logs".to_string(),
};

let hashed_name = seahash::hash(name.as_bytes());
Expand Down
41 changes: 40 additions & 1 deletion data/src/history/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,24 @@ use crate::user::Nick;
use crate::{config, input};
use crate::{server, Buffer, Config, Input, Server, User};

// Hack since log messages are app wide and not scoped to any server
const LOG_SERVER_NAME: &str = "<halloy-logs>";

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Resource {
pub server: server::Server,
pub kind: history::Kind,
}

impl Resource {
pub fn logs() -> Self {
Self {
server: Server::from(LOG_SERVER_NAME),
kind: history::Kind::Logs,
}
}
}

#[derive(Debug)]
pub enum Message {
LoadFull(
Expand Down Expand Up @@ -112,7 +124,10 @@ impl Manager {
log::warn!("failed to close history for {kind} on {server}: {error}")
}
Message::Flushed(server, kind, Ok(_)) => {
log::debug!("flushed history for {kind} on {server}",);
// Will cause flush loop if we emit a log every time we flush logs
if !matches!(kind, history::Kind::Logs) {
log::debug!("flushed history for {kind} on {server}",);
}
}
Message::Flushed(server, kind, Err(error)) => {
log::warn!("failed to flush history for {kind} on {server}: {error}")
Expand Down Expand Up @@ -225,6 +240,17 @@ impl Manager {
)
}

pub fn record_log(
&mut self,
record: crate::log::Record,
) -> Option<impl Future<Output = Message>> {
self.data.add_message(
Server::from(LOG_SERVER_NAME),
history::Kind::Logs,
crate::Message::log(record),
)
}

pub fn update_read_marker(
&mut self,
server: Server,
Expand Down Expand Up @@ -282,6 +308,19 @@ impl Manager {
)
}

pub fn get_log_messages(
&self,
limit: Option<Limit>,
buffer_config: &config::Buffer,
) -> Option<history::View<'_>> {
self.data.history_view(
&Server::from(LOG_SERVER_NAME),
&history::Kind::Logs,
limit,
buffer_config,
)
}

pub fn get_unique_queries(&self, server: &Server) -> Vec<&Nick> {
let Some(map) = self.data.map.get(server) else {
return vec![];
Expand Down
1 change: 1 addition & 0 deletions data/src/history/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ async fn path(server: &server::Server, kind: &Kind) -> Result<PathBuf, Error> {
Kind::Server => format!("{server}-metadata"),
Kind::Channel(channel) => format!("{server}channel{channel}-metadata"),
Kind::Query(nick) => format!("{server}nickname{}-metadata", nick),
Kind::Logs => "logs-metadata".to_string(),
};

let hashed_name = seahash::hash(name.as_bytes());
Expand Down
35 changes: 34 additions & 1 deletion data/src/log.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::path::PathBuf;
use std::{fs, io};

pub use log::*;
use chrono::{DateTime, Utc};

use serde::{Deserialize, Serialize};

use crate::environment;

Expand All @@ -26,6 +28,37 @@ fn path() -> Result<PathBuf, Error> {
Ok(parent.join("halloy.log"))
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Record {
pub timestamp: DateTime<Utc>,
pub level: Level,
pub message: String,
}

#[derive(
Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize, strum::Display,
)]
#[strum(serialize_all = "UPPERCASE")]
pub enum Level {
Error,
Warn,
Info,
Debug,
Trace,
}

impl From<log::Level> for Level {
fn from(level: log::Level) -> Self {
match level {
log::Level::Error => Level::Error,
log::Level::Warn => Level::Warn,
log::Level::Info => Level::Info,
log::Level::Debug => Level::Debug,
log::Level::Trace => Level::Trace,
}
}
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Expand Down
18 changes: 18 additions & 0 deletions data/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ pub enum Target {
nick: Nick,
source: Source,
},
Logs,
}

impl Target {
Expand All @@ -124,6 +125,7 @@ impl Target {
Target::Server { .. } => None,
Target::Channel { prefix, .. } => prefix.as_ref(),
Target::Query { .. } => None,
Target::Logs => None,
}
}

Expand All @@ -132,6 +134,7 @@ impl Target {
Target::Server { source } => source,
Target::Channel { source, .. } => source,
Target::Query { source, .. } => source,
Target::Logs => &Source::Internal(source::Internal::Logs),
}
}
}
Expand Down Expand Up @@ -233,6 +236,18 @@ impl Message {
match &self.content {
Content::Plain(s) => Some(s),
Content::Fragments(_) => None,
Content::Log(_) => None,
}
}

pub fn log(record: crate::log::Record) -> Self {
Self {
received_at: Posix::now(),
server_time: record.timestamp,
direction: Direction::Received,
target: Target::Logs,
content: Content::Log(record),
id: None,
}
}
}
Expand Down Expand Up @@ -467,13 +482,15 @@ fn parse_user_and_channel_fragments(text: &str, channel_users: &[User]) -> Vec<F
pub enum Content {
Plain(String),
Fragments(Vec<Fragment>),
Log(crate::log::Record),
}

impl Content {
fn text(&self) -> Cow<str> {
match self {
Content::Plain(s) => s.into(),
Content::Fragments(fragments) => fragments.iter().map(Fragment::as_str).join("").into(),
Content::Log(record) => (&record.message).into(),
}
}
}
Expand Down Expand Up @@ -1073,6 +1090,7 @@ pub fn references_user(sender: NickRef, own_nick: NickRef, message: &Message) ->
Content::Fragments(fragments) => fragments
.iter()
.any(|f| references_user_text(sender, own_nick, f.as_str())),
Content::Log(_) => false,
}
}

Expand Down
1 change: 1 addition & 0 deletions data/src/message/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum Source {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Internal {
Status(Status),
Logs,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
Expand Down
1 change: 1 addition & 0 deletions data/src/pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum Pane {
},
Empty,
FileTransfers,
Logs,
}

#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
Expand Down
Binary file modified fonts/halloy-icons.ttf
Binary file not shown.
30 changes: 23 additions & 7 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use data::user::Nick;
use data::{buffer, file_transfer, history, Config};
use iced::Task;

use self::channel::Channel;
use self::file_transfers::FileTransfers;
use self::query::Query;
use self::server::Server;
pub use self::channel::Channel;
pub use self::file_transfers::FileTransfers;
pub use self::logs::Logs;
pub use self::query::Query;
pub use self::server::Server;
use crate::screen::dashboard::sidebar;
use crate::widget::Element;
use crate::Theme;
Expand All @@ -15,6 +16,7 @@ pub mod channel;
pub mod empty;
pub mod file_transfers;
mod input_view;
pub mod logs;
pub mod query;
mod scroll_view;
pub mod server;
Expand All @@ -27,6 +29,7 @@ pub enum Buffer {
Server(Server),
Query(Query),
FileTransfers(FileTransfers),
Logs(Logs),
}

#[derive(Debug, Clone)]
Expand All @@ -35,6 +38,7 @@ pub enum Message {
Server(server::Message),
Query(query::Message),
FileTransfers(file_transfers::Message),
Log(logs::Message),
}

pub enum Event {
Expand All @@ -55,6 +59,7 @@ impl Buffer {
Buffer::Server(state) => Some(&state.buffer),
Buffer::Query(state) => Some(&state.buffer),
Buffer::FileTransfers(_) => None,
Buffer::Logs(_) => None,
}
}

Expand Down Expand Up @@ -142,6 +147,7 @@ impl Buffer {
Buffer::FileTransfers(state) => {
file_transfers::view(state, file_transfers).map(Message::FileTransfers)
}
Buffer::Logs(state) => logs::view(state, history, config, theme).map(Message::Log),
}
}

Expand All @@ -167,7 +173,7 @@ impl Buffer {

pub fn focus(&self) -> Task<Message> {
match self {
Buffer::Empty | Buffer::FileTransfers(_) => Task::none(),
Buffer::Empty | Buffer::FileTransfers(_) | Buffer::Logs(_) => Task::none(),
Buffer::Channel(channel) => channel.focus().map(Message::Channel),
Buffer::Server(server) => server.focus().map(Message::Server),
Buffer::Query(query) => query.focus().map(Message::Query),
Expand All @@ -176,7 +182,7 @@ impl Buffer {

pub fn reset(&mut self) {
match self {
Buffer::Empty | Buffer::FileTransfers(_) => {}
Buffer::Empty | Buffer::FileTransfers(_) | Buffer::Logs(_) => {}
Buffer::Channel(channel) => channel.reset(),
Buffer::Server(server) => server.reset(),
Buffer::Query(query) => query.reset(),
Expand All @@ -190,7 +196,9 @@ impl Buffer {
) -> Task<Message> {
if let Some(buffer) = self.data().cloned() {
match self {
Buffer::Empty | Buffer::Server(_) | Buffer::FileTransfers(_) => Task::none(),
Buffer::Empty | Buffer::Server(_) | Buffer::FileTransfers(_) | Buffer::Logs(_) => {
Task::none()
}
Buffer::Channel(channel) => channel
.input_view
.insert_user(nick, buffer, history)
Expand Down Expand Up @@ -220,6 +228,10 @@ impl Buffer {
.scroll_view
.scroll_to_start()
.map(|message| Message::Query(query::Message::ScrollView(message))),
Buffer::Logs(log) => log
.scroll_view
.scroll_to_start()
.map(|message| Message::Log(logs::Message::ScrollView(message))),
}
}

Expand All @@ -238,6 +250,10 @@ impl Buffer {
.scroll_view
.scroll_to_end()
.map(|message| Message::Query(query::Message::ScrollView(message))),
Buffer::Logs(log) => log
.scroll_view
.scroll_to_end()
.map(|message| Message::Log(logs::Message::ScrollView(message))),
}
}
}
Expand Down
Loading

0 comments on commit 315d964

Please sign in to comment.