1use std::fmt;
2
3use super::*;
4use lz4_flex::block::uncompressed_size;
5use wasmer_wasix_types::wasi;
6
7#[derive(Debug, Default)]
9pub enum JournalPrintingMode {
10 #[default]
11 Text,
12 Json,
13}
14
15#[derive(Debug, Default)]
18pub struct PrintingJournal {
19 mode: JournalPrintingMode,
20}
21
22impl PrintingJournal {
23 pub fn new(mode: JournalPrintingMode) -> Self {
24 Self { mode }
25 }
26}
27
28impl ReadableJournal for PrintingJournal {
29 fn read(&self) -> anyhow::Result<Option<LogReadResult<'_>>> {
30 Ok(None)
31 }
32
33 fn as_restarted(&self) -> anyhow::Result<Box<DynReadableJournal>> {
34 Ok(Box::<PrintingJournal>::default())
35 }
36}
37
38impl WritableJournal for PrintingJournal {
39 fn write<'a>(&'a self, entry: JournalEntry<'a>) -> anyhow::Result<LogWriteResult> {
40 match self.mode {
41 JournalPrintingMode::Text => println!("{entry}"),
42 JournalPrintingMode::Json => {
43 println!("{}", serde_json::to_string_pretty(&entry)?)
44 }
45 }
46 Ok(LogWriteResult {
47 record_start: 0,
48 record_end: entry.estimate_size() as u64,
49 })
50 }
51
52 fn flush(&self) -> anyhow::Result<()> {
53 Ok(())
54 }
55}
56
57impl Journal for PrintingJournal {
58 fn split(self) -> (Box<DynWritableJournal>, Box<DynReadableJournal>) {
59 (
60 Box::<PrintingJournal>::default(),
61 Box::<PrintingJournal>::default(),
62 )
63 }
64}
65
66impl fmt::Display for JournalEntry<'_> {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 match self {
69 JournalEntry::InitModuleV1 { wasm_hash } => {
70 write!(f, "init-module (hash={wasm_hash:x?})")
71 }
72 JournalEntry::ClearEtherealV1 => {
73 write!(f, "clear-ethereal")
74 }
75 JournalEntry::UpdateMemoryRegionV1 {
76 region,
77 compressed_data,
78 } => write!(
79 f,
80 "memory-update (start={}, end={}, data.len={}, compressed.len={})",
81 region.start,
82 region.end,
83 uncompressed_size(compressed_data.as_ref())
84 .map(|a| a.0)
85 .unwrap_or_else(|_| compressed_data.as_ref().len()),
86 compressed_data.len()
87 ),
88 JournalEntry::ProcessExitV1 { exit_code } => {
89 write!(f, "process-exit (code={exit_code:?})")
90 }
91 JournalEntry::SetThreadV1 {
92 id,
93 call_stack,
94 memory_stack,
95 store_data,
96 ..
97 } => write!(
98 f,
99 "thread-update (id={}, call-stack.len={}, mem-stack.len={}, store-size={})",
100 id,
101 call_stack.len(),
102 memory_stack.len(),
103 store_data.len(),
104 ),
105 JournalEntry::CloseThreadV1 { id, exit_code } => {
106 write!(f, "thread-close (id={id}, code={exit_code:?})")
107 }
108 JournalEntry::FileDescriptorSeekV1 { fd, offset, whence } => {
109 write!(f, "fd-seek (fd={fd}, offset={offset}, whence={whence:?})")
110 }
111 JournalEntry::FileDescriptorWriteV1 {
112 fd, offset, data, ..
113 } => write!(
114 f,
115 "fd-write (fd={fd}, offset={offset}, data.len={})",
116 data.len()
117 ),
118 JournalEntry::SetClockTimeV1 { clock_id, time } => {
119 write!(f, "set-clock-time (id={clock_id:?}, time={time})")
120 }
121 JournalEntry::CloseFileDescriptorV1 { fd } => write!(f, "fd-close (fd={fd})"),
122 JournalEntry::OpenFileDescriptorV1 {
123 fd, path, o_flags, ..
124 }
125 | JournalEntry::OpenFileDescriptorV2 {
126 fd, path, o_flags, ..
127 } => {
128 if o_flags.contains(wasi::Oflags::CREATE) {
129 if o_flags.contains(wasi::Oflags::TRUNC) {
130 write!(f, "fd-create-new (fd={fd}, path={path})")
131 } else if o_flags.contains(wasi::Oflags::EXCL) {
132 write!(f, "fd-create-excl (fd={fd}, path={path})")
133 } else {
134 write!(f, "fd-create (fd={fd}, path={path})")
135 }
136 } else if o_flags.contains(wasi::Oflags::TRUNC) {
137 write!(f, "fd-open-new (fd={fd}, path={path})")
138 } else {
139 write!(f, "fd-open (fd={fd}, path={path})")
140 }
141 }
142 JournalEntry::RenumberFileDescriptorV1 { old_fd, new_fd } => {
143 write!(f, "fd-renumber (old={old_fd}, new={new_fd})")
144 }
145 JournalEntry::DuplicateFileDescriptorV1 {
146 original_fd,
147 copied_fd,
148 } => write!(
149 f,
150 "fd-duplicate (original={original_fd}, copied={copied_fd})"
151 ),
152 JournalEntry::DuplicateFileDescriptorV2 {
153 original_fd,
154 copied_fd,
155 cloexec,
156 } => write!(
157 f,
158 "fd-duplicate (original={original_fd}, copied={copied_fd}, cloexec={cloexec})"
159 ),
160 JournalEntry::CreateDirectoryV1 { fd, path } => {
161 write!(f, "path-create-dir (fd={fd}, path={path})")
162 }
163 JournalEntry::RemoveDirectoryV1 { fd, path } => {
164 write!(f, "path-remove-dir (fd={fd}, path={path})")
165 }
166 JournalEntry::PathSetTimesV1 {
167 path,
168 st_atim,
169 st_mtim,
170 ..
171 } => write!(
172 f,
173 "path-set-times (path={path}, atime={st_atim}, mtime={st_mtim}))"
174 ),
175 JournalEntry::FileDescriptorSetTimesV1 {
176 fd,
177 st_atim,
178 st_mtim,
179 ..
180 } => write!(
181 f,
182 "fd-set-times (fd={fd}, atime={st_atim}, mtime={st_mtim})"
183 ),
184 JournalEntry::FileDescriptorSetFdFlagsV1 { fd, flags } => {
185 write!(f, "fd-set-fd-flags (fd={fd}, flags={flags:?})")
186 }
187 JournalEntry::FileDescriptorSetFlagsV1 { fd, flags } => {
188 write!(f, "fd-set-flags (fd={fd}, flags={flags:?})")
189 }
190 JournalEntry::FileDescriptorSetRightsV1 {
191 fd,
192 fs_rights_base,
193 fs_rights_inheriting,
194 } => write!(
195 f,
196 "fd-set-rights (fd={fd}, base={fs_rights_base:?}, inherited={fs_rights_inheriting:?})"
197 ),
198 JournalEntry::FileDescriptorSetSizeV1 { fd, st_size } => {
199 write!(f, "fd-set-size (fd={fd}, size={st_size})")
200 }
201 JournalEntry::FileDescriptorAdviseV1 {
202 fd, offset, len, ..
203 } => write!(f, "fd-advise (fd={fd}, offset={offset}, len={len})"),
204 JournalEntry::FileDescriptorAllocateV1 { fd, offset, len } => {
205 write!(f, "fd-allocate (fd={fd}, offset={offset}, len={len})")
206 }
207 JournalEntry::CreateHardLinkV1 {
208 old_path, new_path, ..
209 } => write!(f, "path-link (from={old_path}, to={new_path})"),
210 JournalEntry::CreateSymbolicLinkV1 {
211 old_path, new_path, ..
212 } => write!(f, "path-symlink (from={old_path}, to={new_path})"),
213 JournalEntry::UnlinkFileV1 { path, .. } => write!(f, "path-unlink (path={path})"),
214 JournalEntry::PathRenameV1 {
215 old_path, new_path, ..
216 } => write!(f, "path-rename (old-path={old_path}, new-path={new_path})"),
217 JournalEntry::ChangeDirectoryV1 { path } => write!(f, "chdir (path={path})"),
218 JournalEntry::EpollCreateV1 { fd } => write!(f, "epoll-create (fd={fd})"),
219 JournalEntry::EpollCtlV1 { epfd, op, fd, .. } => {
220 write!(f, "epoll-ctl (epfd={epfd}, op={op:?}, fd={fd})")
221 }
222 JournalEntry::TtySetV1 { tty, line_feeds } => write!(
223 f,
224 "tty-set (echo={}, buffering={}, feeds={})",
225 tty.echo, tty.line_buffered, line_feeds
226 ),
227 JournalEntry::CreatePipeV1 { read_fd, write_fd } => {
228 write!(f, "fd-pipe (read_fd={read_fd}, write_fd={write_fd})")
229 }
230 JournalEntry::CreateEventV1 {
231 initial_val, fd, ..
232 } => write!(f, "fd-event (fd={fd}, initial={initial_val})"),
233 JournalEntry::PortAddAddrV1 { cidr } => {
234 write!(f, "port-addr-add (ip={}, prefix={})", cidr.ip, cidr.prefix)
235 }
236 JournalEntry::PortDelAddrV1 { addr } => write!(f, "port-addr-del (addr={addr})"),
237 JournalEntry::PortAddrClearV1 => write!(f, "port-addr-clear"),
238 JournalEntry::PortBridgeV1 { network, .. } => {
239 write!(f, "port-bridge (network={network})")
240 }
241 JournalEntry::PortUnbridgeV1 => write!(f, "port-unbridge"),
242 JournalEntry::PortDhcpAcquireV1 => write!(f, "port-dhcp-acquire"),
243 JournalEntry::PortGatewaySetV1 { ip } => write!(f, "port-gateway-set (ip={ip})"),
244 JournalEntry::PortRouteAddV1 {
245 cidr, via_router, ..
246 } => write!(
247 f,
248 "port-route-add (ip={}, prefix={}, via_router={})",
249 cidr.ip, cidr.prefix, via_router
250 ),
251 JournalEntry::PortRouteClearV1 => write!(f, "port-route-clear"),
252 JournalEntry::PortRouteDelV1 { ip } => write!(f, "port-route-del (ip={ip})"),
253 JournalEntry::SocketOpenV1 { af, ty, pt, fd } => {
254 write!(f, "sock-open (fd={fd}, af={af:?}, ty={ty:?}, pt={pt:?})")
255 }
256 JournalEntry::SocketPairV1 { fd1, fd2 } => {
257 write!(f, "sock-pair (fd1={fd1}, fd2={fd2})")
258 }
259 JournalEntry::SocketListenV1 { fd, backlog } => {
260 write!(f, "sock-listen (fd={fd}, backlog={backlog})")
261 }
262 JournalEntry::SocketBindV1 { fd, addr } => {
263 write!(f, "sock-bind (fd={fd}, addr={addr})")
264 }
265 JournalEntry::SocketConnectedV1 {
266 fd,
267 local_addr,
268 peer_addr,
269 } => {
270 write!(
271 f,
272 "sock-connect (fd={fd}, addr={local_addr}, peer={peer_addr})"
273 )
274 }
275 JournalEntry::SocketAcceptedV1 {
276 listen_fd,
277 fd,
278 local_addr,
279 peer_addr,
280 ..
281 } => write!(
282 f,
283 "sock-accept (listen-fd={listen_fd}, sock_fd={fd}, addr={local_addr}, peer={peer_addr})"
284 ),
285 JournalEntry::SocketJoinIpv4MulticastV1 {
286 fd,
287 multiaddr,
288 iface,
289 } => write!(
290 f,
291 "sock-join-mcast-ipv4 (fd={fd}, addr={multiaddr}, iface={iface})"
292 ),
293 JournalEntry::SocketJoinIpv6MulticastV1 {
294 fd,
295 multi_addr: multiaddr,
296 iface,
297 } => write!(
298 f,
299 "sock-join-mcast-ipv6 (fd={fd}, addr={multiaddr}, iface={iface})"
300 ),
301 JournalEntry::SocketLeaveIpv4MulticastV1 {
302 fd,
303 multi_addr: multiaddr,
304 iface,
305 } => write!(
306 f,
307 "sock-leave-mcast-ipv4 (fd={fd}, addr={multiaddr}, iface={iface})"
308 ),
309 JournalEntry::SocketLeaveIpv6MulticastV1 {
310 fd,
311 multi_addr: multiaddr,
312 iface,
313 } => write!(
314 f,
315 "sock-leave-mcast-ipv6 (fd={fd}, addr={multiaddr}, iface={iface})"
316 ),
317 JournalEntry::SocketSendFileV1 {
318 socket_fd,
319 file_fd,
320 offset,
321 count,
322 } => write!(
323 f,
324 "sock-send-file (sock-fd={socket_fd}, file-fd={file_fd}, offset={offset}, count={count})"
325 ),
326 JournalEntry::SocketSendToV1 { fd, data, addr, .. } => {
327 write!(
328 f,
329 "sock-send-to (fd={}, data.len={}, addr={})",
330 fd,
331 data.len(),
332 addr
333 )
334 }
335 JournalEntry::SocketSendV1 { fd, data, .. } => {
336 write!(f, "sock-send (fd={}, data.len={})", fd, data.len())
337 }
338 JournalEntry::SocketSetOptFlagV1 { fd, opt, flag } => {
339 write!(f, "sock-set-opt (fd={fd}, opt={opt:?}, flag={flag})")
340 }
341 JournalEntry::SocketSetOptSizeV1 { fd, opt, size } => {
342 write!(f, "sock-set-opt (fd={fd}, opt={opt:?}, size={size})")
343 }
344 JournalEntry::SocketSetOptTimeV1 { fd, ty, time } => {
345 write!(f, "sock-set-opt (fd={fd}, opt={ty:?}, time={time:?})")
346 }
347 JournalEntry::SocketShutdownV1 { fd, how } => {
348 write!(f, "sock-shutdown (fd={fd}, how={how:?})")
349 }
350 JournalEntry::SnapshotV1 { when, trigger } => {
351 write!(f, "snapshot (when={when:?}, trigger={trigger:?})")
352 }
353 }
354 }
355}