Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Improve logging #46

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

WIP: Improve logging #46

wants to merge 1 commit into from

Conversation

nirs
Copy link
Contributor

@nirs nirs commented Sep 16, 2024

This is a quick draft to experiment with better logging. Posting to get an early review on this changes.

This does not fix all the issues mentioned in #43 but prepare the infrastructure. With these changes adding timestamps for all logs is a trivial change.

Example log with this change

# tail -f /var/log/socket_vmnet/stderr
INFO | Initializing vmnet.framework (mode 1001)
INFO | * vmnet_subnet_mask: 255.255.255.0
INFO | * vmnet_mtu: 1500
INFO | * vmnet_end_address: 192.168.105.254
INFO | * vmnet_start_address: 192.168.105.1
INFO | * vmnet_interface_id: 9EF22956-C8DF-4242-8239-150985812E89
INFO | * vmnet_max_packet_size: 1514
INFO | * vmnet_nat66_prefix: fd9b:5a14:ba57:e3d3::
INFO | * vmnet_mac_address: 26:42:48:f0:96:21
INFO | Accepted a connection (fd 5)
INFO | Closing a connection (fd 5)
INFO | Received signal: Broken pipe: 13
ERROR| writev: Broken pipe

#define INFOF(fmt, ...) fprintf(stderr, "INFO | " fmt "\n", __VA_ARGS__)
#define ERROR(msg) fprintf(stderr, "ERROR| " msg "\n")
#define ERRORF(fmt, ...) fprintf(stderr, "ERROR| " fmt "\n", __VA_ARGS__)
#define ERRORN(name) ERRORF(name ": %s", strerror(errno))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should move to log.h so we can split the to code to multiple files and use consistent logging.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

See man 3 os_log for the usage

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I'll try this.

But I think we should keep the logging macros so it is easy to change the logging backend later.

default:
fprintf(stderr, "%s(): vmnet_return_t %d\n", func, v);
break;
return "(unknown status)";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did not check the enums values, maybe we can replace this with a simpler table lookup.

@AkihiroSuda AkihiroSuda added this to the v1.1.5 milestone Sep 17, 2024
main.c Outdated Show resolved Hide resolved
- Log everything to stderr - this has many advantages: Much easier to
  understand what happened before errors, Much easier to understand the
  daemon state, since stderr is line buffered, so events (e.g. start,
  stop, connect, disconnect) are logged immediately. Easier to get logs
  from users.
- Replace fprintf and printf with logging macros (ERRORF, ERROR, INFO)
- Replace perror with ERRORN, showing the same output an error log.
- Use prefix for all logs ("DEBUG|", "INFO |", "ERROR|") to make the
  meaning of the message clear, and make all log message
  aligned nicely.
- Remove unneeded log for vmnet_return_t when we get VMNET_SUCCESS
- Replace print_vmnet_status() with vmnet_strerror() returning readable
  error name. Callers use ERRORF() to log the vmnet function name,
  return value and error name.
- Log socket length when it is too long
- Log the signal name and number

Signed-off-by: Nir Soffer <nsoffer@redhat.com>
@@ -330,39 +326,40 @@ static int socket_bindlisten(const char *socket_path,
memset(&addr, 0, sizeof(addr));
unlink(socket_path); /* avoid EADDRINUSE */
if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
perror("socket");
ERRORN("socket");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ERRORN was a quick way to convert perror calls to standard logs, but I think in most case it will be better to use ERRORF and add more context about the error. For example here adding the socket path will help to debug issues.

goto err;
}
/* fchown can't be used (EINVAL) */
if (chown(socket_path, -1, grp->gr_gid) < 0) {
perror("chown");
ERRORN("chown");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here including the argument so the call in the error can help debugging later.

goto err;
}
if (chmod(socket_path, 0770) < 0) {
perror("chmod");
ERRORN("chmod");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Including the permissions in the error message can help debugging.

@@ -406,15 +403,15 @@ int main(int argc, char *argv[]) {
pid_fd = open(cliopt->pidfile,
O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, 0644);
if (pid_fd == -1) {
perror("pidfile_open");
ERRORN("pidfile_open");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Including the path that failed will help debugging.

@@ -423,23 +420,23 @@ int main(int argc, char *argv[]) {
state.sem = dispatch_semaphore_create(1);
iface = start(&state, cliopt);
if (iface == NULL) {
perror("start");
ERRORN("start");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This looks wrong - start does not set errno and already logged failures.

goto done;
}

if (pid_fd != -1) {
char pid[20];
snprintf(pid, sizeof(pid), "%u", getpid());
if (write(pid_fd, pid, strlen(pid)) != (ssize_t)strlen(pid)) {
perror("pidfile_write");
ERRORN("pidfile_write");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be ERRNO("write"), but using ERRORF with more context will be more helpful.

goto done;
}
uint32_t header = ntohl(header_be);
assert(header <= buf_len);
ssize_t received = read(accept_fd, buf, header);
if (received < 0) {
perror("read");
ERRORN("read");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be ERRORN("read[body]") for consistency with ERRORN("read[header]").

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