From eb39b4a13ce07ebfeb42dc361ac958d65ff994e5 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Wed, 5 Apr 2017 16:03:52 -0700 Subject: [PATCH 1/2] Account for line endings in logging Signed-off-by: Mrunal Patel --- conmon/conmon.c | 84 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/conmon/conmon.c b/conmon/conmon.c index 6c285b4d..f69720f5 100644 --- a/conmon/conmon.c +++ b/conmon/conmon.c @@ -116,6 +116,65 @@ int set_k8s_timestamp(char *buf, ssize_t buflen, const char *stream_type) return 0; } + +/* + * splits buf into lines and inserts timestamps at the beginning of + * the line written to logfd. + */ +int write_with_timestamps(int logfd, const char *buf, ssize_t buflen) +{ + #define TSBUFLEN 34 + char tsbuf[TSBUFLEN]; + static bool last_buf_ended_with_newline = TRUE; + + g_auto(GStrv) lines = g_strsplit(buf, "\n", -1); + ssize_t num_lines = g_strv_length(lines); + for (ssize_t i = 0; i < num_lines; i++) + { + const char *line = lines[i]; + + ninfo("Processing line: %ld, %s", i, line); + + /* Skip last line if it is empty */ + if (i == (num_lines - 1) && buf[buflen-1] == '\n' && !strcmp("", line)) { + ninfo("Skipping last line"); + break; + } + + /* + * Only add timestamps for first line if last buffer's last + * line ended with newline. Add it for all other lines. + */ + if (i != 0 || (i == 0 && last_buf_ended_with_newline)) { + ninfo("Adding timestamp"); + int rc = set_k8s_timestamp(tsbuf, TSBUFLEN, "stdout"); + if (rc < 0) { + nwarn("failed to set timestamp"); + } else { + if (write(logfd, tsbuf, TSBUFLEN) != TSBUFLEN) { + nwarn("partial/failed write ts (logFd)"); + } + } + } + + /* Log output to logfd. */ + ssize_t len = strlen(line); + if (write(logfd, line, len) != len) { + nwarn("partial/failed write (logFd)"); + return -1; + } + /* Write the line ending */ + if (write(logfd, "\n", 1) != 1) { + nwarn("failed to write line ending"); + return -1; + } + } + + last_buf_ended_with_newline = buf[buflen-1] == '\n'; + + return 0; +} + int main(int argc, char *argv[]) { int ret, runtime_status; @@ -395,9 +454,6 @@ int main(int argc, char *argv[]) pexit("Failed to add console master fd to epoll"); } - #define TSBUFLEN 34 - char tsbuf[TSBUFLEN]; - /* * Log all of the container's output and pipe STDIN into it. Currently * nothing using the STDIN setup (which makes its inclusion here a bit @@ -427,28 +483,12 @@ int main(int argc, char *argv[]) if (num_read <= 0) goto out; + buf[num_read] = '\0'; ninfo("read a chunk: (fd=%d) '%s'", mfd, buf); - - /* Prepend the CRI-mandated timestamp and other metadata. */ - /* - * FIXME: Currently this code makes the assumption that - * @buf doesn't contain any newlines (since the CRI - * requires each line to contain a timestamp). This - * is an /okay/ assumption in most cases because - * ptys generally have newline-buffered output. - */ - int rc = set_k8s_timestamp(tsbuf, TSBUFLEN, "stdout"); + /* Insert CRI mandated timestamps in the buffer for each line */ + int rc = write_with_timestamps(logfd, buf, num_read); if (rc < 0) { - nwarn("failed to set timestamp"); - } else { - if (write(logfd, tsbuf, TSBUFLEN) != TSBUFLEN) { - nwarn("partial/failed write ts (logFd)"); - } - } - /* Log all output to logfd. */ - if (write(logfd, buf, num_read) != num_read) { - nwarn("partial/failed write (logFd)"); goto out; } } From cbbf9aea0a8fa5c6754a171ba00f7cd064c2aaa4 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Fri, 7 Apr 2017 10:51:04 -0700 Subject: [PATCH 2/2] Don't write \0 after timestamp and skip line ending on partial lines Signed-off-by: Antonia Murdaca Signed-off-by: Mrunal Patel --- conmon/conmon.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/conmon/conmon.c b/conmon/conmon.c index f69720f5..933963d3 100644 --- a/conmon/conmon.c +++ b/conmon/conmon.c @@ -151,7 +151,8 @@ int write_with_timestamps(int logfd, const char *buf, ssize_t buflen) if (rc < 0) { nwarn("failed to set timestamp"); } else { - if (write(logfd, tsbuf, TSBUFLEN) != TSBUFLEN) { + /* Exclude the \0 while writing */ + if (write(logfd, tsbuf, TSBUFLEN - 1) != (TSBUFLEN - 1)) { nwarn("partial/failed write ts (logFd)"); } } @@ -164,9 +165,11 @@ int write_with_timestamps(int logfd, const char *buf, ssize_t buflen) return -1; } /* Write the line ending */ - if (write(logfd, "\n", 1) != 1) { - nwarn("failed to write line ending"); - return -1; + if ((i < num_lines - 1) || (i == (num_lines - 1) && buf[buflen - 1] == '\n')) { + if (write(logfd, "\n", 1) != 1) { + nwarn("failed to write line ending"); + return -1; + } } }