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