1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
use core::fmt;
use core::hash::Hash;
use serde::Deserialize;
use serde::Serialize;
/// A process ID (PID).
#[derive(
Copy,
Clone,
Debug,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
Serialize,
Deserialize
)]
pub struct Pid(libc::pid_t);
impl Pid {
/// Creates `Pid` from a raw `pid_t`.
pub fn from_raw(pid: libc::pid_t) -> Self {
Self(pid)
}
/// Returns the PID of the calling process.
pub fn this() -> Self {
nix::unistd::Pid::this().into()
}
/// Returns the PID of the calling process.
pub fn parent() -> Self {
nix::unistd::Pid::parent().into()
}
/// Gets the raw `pid_t` from this `Pid`.
pub fn as_raw(self) -> libc::pid_t {
self.0
}
/// Returns a `Display`able that is color-coded. That is, the same PID will
/// get the same color. This makes it easy to visually recognize PIDs when
/// looking through logs.
///
/// Note that while the same PIDs always have the same color, different PIDs
/// may also have the same color if they fall into the same color bucket.
pub fn colored(self) -> ColoredPid {
ColoredPid(self)
}
}
impl From<nix::unistd::Pid> for Pid {
fn from(pid: nix::unistd::Pid) -> Pid {
Self(pid.as_raw())
}
}
impl From<Pid> for nix::unistd::Pid {
fn from(pid: Pid) -> nix::unistd::Pid {
nix::unistd::Pid::from_raw(pid.as_raw())
}
}
impl From<Pid> for libc::pid_t {
fn from(pid: Pid) -> libc::pid_t {
pid.as_raw()
}
}
impl From<libc::pid_t> for Pid {
fn from(pid: libc::pid_t) -> Pid {
Pid::from_raw(pid)
}
}
impl fmt::Display for Pid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
/// A colored pid.
pub struct ColoredPid(Pid);
impl ColoredPid {
/// Gets the ansi color code for the current PID. Returns `None` if not
/// writing to a terminal.
fn ansi_code(&self) -> Option<&'static str> {
if colored::control::SHOULD_COLORIZE.should_colorize() {
// Why not just use `colored::Colorize` you ask? It allocates a
// string in order to create the color code. Since we may log a lot
// of output that may contain a lot of PIDs, we don't want that to
// slow us down.
Some(match self.0.as_raw() % 14 {
0 => "\x1b[0;31m", // Red
1 => "\x1b[0;32m", // Green
2 => "\x1b[0;33m", // Yellow
3 => "\x1b[0;34m", // Blue
4 => "\x1b[0;35m", // Magenta
5 => "\x1b[0;36m", // Cyan
6 => "\x1b[0;37m", // White
7 => "\x1b[1;31m", // Bright red
8 => "\x1b[1;32m", // Bright green
9 => "\x1b[01;33m", // Bright yellow
10 => "\x1b[1;34m", // Bright blue
11 => "\x1b[1;35m", // Bright magenta
12 => "\x1b[1;36m", // Bright cyan
_ => "\x1b[1;37m", // Bright white
})
} else {
None
}
}
}
impl fmt::Display for ColoredPid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(color) = self.ansi_code() {
write!(f, "{}{}\x1b[0m", color, self.0)
} else {
fmt::Display::fmt(&self.0, f)
}
}
}