Hi, I would like to integrate logd to the cloud logging service. The service only accepts special format of syslog, so then I make logread support template.
Here's the usage: logread -T "<%priority%> %source% %message% %timestamp%" Currently supports 4 keywords: priority, source, message, timestamp. The keywords should be surrounded by percent signs as showed above. Regards, Henry Chang Signed-off-by: Henry Chang <mr.changyuh...@gmail.com> --- log/logread.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 27 deletions(-) diff --git a/log/logread.c b/log/logread.c index edac1d9..ddb4f12 100644 --- a/log/logread.c +++ b/log/logread.c @@ -56,10 +56,22 @@ static const struct blobmsg_policy log_policy[] = { [LOG_TIME] = { .name = "time", .type = BLOBMSG_TYPE_INT64 }, }; +static const char TP_FIELD_MESSAGE[] = "%message%"; +static const char TP_FIELD_PRIORITY[] = "%priority%"; +static const char TP_FIELD_SOURCE[] = "%source%"; +static const char TP_FIELD_TIMESTAMP[] = "%timestamp%"; +static const char *TP_FIELD_NAMES[] = { + TP_FIELD_MESSAGE, + TP_FIELD_PRIORITY, + TP_FIELD_SOURCE, + TP_FIELD_TIMESTAMP, +}; + static struct uloop_timeout retry; static struct uloop_fd sender; static regex_t regexp_preg; static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname, *regexp_pattern; +static const char *log_template; static int log_type = LOG_STDOUT; static int log_size, log_udp, log_follow, log_trailer_null = 0; static int log_timestamp; @@ -101,13 +113,16 @@ static int log_notify(struct blob_attr *msg) struct blob_attr *tb[__LOG_MAX]; struct stat s; char buf[512]; + char buf2[512]; char buf_ts[32]; + char buf_p[32]; uint32_t p; - char *str; + char *str, *substr, *field; time_t t; uint32_t t_ms = 0; char *c, *m; int ret = 0; + int i, j; if (sender.fd < 0) return 0; @@ -137,34 +152,83 @@ static int log_notify(struct blob_attr *msg) regexec(®exp_preg, m, 0, NULL, 0) == REG_NOMATCH) return 0; t = blobmsg_get_u64(tb[LOG_TIME]) / 1000; - if (log_timestamp) { - t_ms = blobmsg_get_u64(tb[LOG_TIME]) % 1000; - snprintf(buf_ts, sizeof(buf_ts), "[%lu.%03u] ", - (unsigned long)t, t_ms); - } + t_ms = blobmsg_get_u64(tb[LOG_TIME]) % 1000; + snprintf(buf_ts, sizeof(buf_ts), "[%lu.%03u] ", (unsigned long) t, t_ms); c = ctime(&t); p = blobmsg_get_u32(tb[LOG_PRIO]); c[strlen(c) - 1] = '\0'; str = blobmsg_format_json(msg, true); + snprintf(buf_p, sizeof buf_p, "%u", p); + + if (log_template) { + *buf = '\0'; + *buf2 = '\0'; + if ((j = strlen(log_template)) + 1 > sizeof buf) { + fprintf(stderr, "template is larger than the internal buffer\n"); + return 1; + } + strncat(buf, log_template, j); + for (i = 0; i < sizeof TP_FIELD_NAMES / sizeof (char *); ++i) { + field = NULL; + if (!strcmp(TP_FIELD_NAMES[i], TP_FIELD_MESSAGE)) { + field = m; + } else if (!strcmp(TP_FIELD_NAMES[i], TP_FIELD_PRIORITY)) { + field = buf_p; + } else if (!strcmp(TP_FIELD_NAMES[i], TP_FIELD_SOURCE)) { + switch (blobmsg_get_u32(tb[LOG_SOURCE])) { + case SOURCE_KLOG: + field = "kernel"; + break; + case SOURCE_SYSLOG: + field = "syslog"; + break; + case SOURCE_INTERNAL: + field = "internal"; + break; + default: + field = "-"; + } + } else if (!strcmp(TP_FIELD_NAMES[i], TP_FIELD_TIMESTAMP)) { + field = buf_ts; + } + while (field && (substr = strstr(buf, TP_FIELD_NAMES[i]))) { + if (strlen(field) + strlen(buf) - strlen(TP_FIELD_NAMES[i]) + 1 > + sizeof buf) { + fprintf(stderr, "content to fill template is larger than buffer\n"); + return 1; + } + *buf2 = '\0'; + strncat(buf2, buf, substr - buf); + strncat(buf2, field, strlen(field)); + strncat(buf2, substr + strlen(TP_FIELD_NAMES[i]), + strlen(buf) - (substr - buf) - strlen(TP_FIELD_NAMES[i])); + *buf = '\0'; + strncat(buf, buf2, strlen(buf2)); + } + } + } + if (log_type == LOG_NET) { int err; - snprintf(buf, sizeof(buf), "<%u>", p); - strncat(buf, c + 4, 16); - if (log_timestamp) { - strncat(buf, buf_ts, sizeof(buf) - strlen(buf) - 1); + if (!log_template) { + snprintf(buf, sizeof(buf), "<%u>", p); + strncat(buf, c + 4, 16); + if (log_timestamp) { + strncat(buf, buf_ts, sizeof(buf) - strlen(buf) - 1); + } + if (hostname) { + strncat(buf, hostname, sizeof(buf) - strlen(buf) - 1); + strncat(buf, " ", sizeof(buf) - strlen(buf) - 1); + } + if (log_prefix) { + strncat(buf, log_prefix, sizeof(buf) - strlen(buf) - 1); + strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1); + } + if (blobmsg_get_u32(tb[LOG_SOURCE]) == SOURCE_KLOG) + strncat(buf, "kernel: ", sizeof(buf) - strlen(buf) - 1); + strncat(buf, m, sizeof(buf) - strlen(buf) - 1); } - if (hostname) { - strncat(buf, hostname, sizeof(buf) - strlen(buf) - 1); - strncat(buf, " ", sizeof(buf) - strlen(buf) - 1); - } - if (log_prefix) { - strncat(buf, log_prefix, sizeof(buf) - strlen(buf) - 1); - strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1); - } - if (blobmsg_get_u32(tb[LOG_SOURCE]) == SOURCE_KLOG) - strncat(buf, "kernel: ", sizeof(buf) - strlen(buf) - 1); - strncat(buf, m, sizeof(buf) - strlen(buf) - 1); if (log_udp) err = write(sender.fd, buf, strlen(buf)); else { @@ -183,11 +247,18 @@ static int log_notify(struct blob_attr *msg) uloop_timeout_set(&retry, 1000); } } else { - snprintf(buf, sizeof(buf), "%s %s%s.%s%s %s\n", - c, log_timestamp ? buf_ts : "", - getcodetext(LOG_FAC(p) << 3, facilitynames), - getcodetext(LOG_PRI(p), prioritynames), - (blobmsg_get_u32(tb[LOG_SOURCE])) ? ("") : (" kernel:"), m); + if (!log_template) { + snprintf(buf, sizeof(buf), "%s %s%s.%s%s %s\n", + c, log_timestamp ? buf_ts : "", + getcodetext(LOG_FAC(p) << 3, facilitynames), + getcodetext(LOG_PRI(p), prioritynames), + (blobmsg_get_u32(tb[LOG_SOURCE])) ? ("") : (" kernel:"), m); + } else { + size_t buflen = strlen(buf); + buflen = buflen <= sizeof buf - 2 ? buflen : sizeof buf - 2; + buf[buflen] = '\n'; + buf[buflen+1] = '\0'; + } ret = write(sender.fd, buf, strlen(buf)); } @@ -211,6 +282,7 @@ static int usage(const char *prog) " -p <file> PID file\n" " -h <hostname> Add hostname to the message\n" " -P <prefix> Prefix custom text to streamed messages\n" + " -T <template> Custom log output template\n" " -f Follow log messages\n" " -u Use UDP as the protocol\n" " -t Add an extra timestamp\n" @@ -260,7 +332,7 @@ int main(int argc, char **argv) signal(SIGPIPE, SIG_IGN); - while ((ch = getopt(argc, argv, "u0fcs:l:r:F:p:S:P:h:e:t")) != -1) { + while ((ch = getopt(argc, argv, "u0fcs:l:r:F:p:S:P:h:e:tT:")) != -1) { switch (ch) { case 'u': log_udp = 1; @@ -307,6 +379,9 @@ int main(int argc, char **argv) case 't': log_timestamp = 1; break; + case 'T': + log_template = optarg; + break; default: return usage(*argv); } -- 2.7.4 _______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev