get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/138672/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 138672,
    "url": "http://patches.dpdk.org/api/patches/138672/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20240321161146.340421-9-stephen@networkplumber.org/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20240321161146.340421-9-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240321161146.340421-9-stephen@networkplumber.org",
    "date": "2024-03-21T16:00:24",
    "name": "[v10,08/10] eal: add option to put timestamp on console output",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e735b795fed40cfd11c115ba33388822cefb27a7",
    "submitter": {
        "id": 27,
        "url": "http://patches.dpdk.org/api/people/27/?format=api",
        "name": "Stephen Hemminger",
        "email": "stephen@networkplumber.org"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20240321161146.340421-9-stephen@networkplumber.org/mbox/",
    "series": [
        {
            "id": 31589,
            "url": "http://patches.dpdk.org/api/series/31589/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=31589",
            "date": "2024-03-21T16:00:17",
            "name": "Logging enhancements.",
            "version": 10,
            "mbox": "http://patches.dpdk.org/series/31589/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/138672/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/138672/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id C073F43D17;\n\tThu, 21 Mar 2024 17:19:27 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 21BF742E3D;\n\tThu, 21 Mar 2024 17:19:23 +0100 (CET)",
            "from mail-qk1-f178.google.com (mail-qk1-f178.google.com\n [209.85.222.178])\n by mails.dpdk.org (Postfix) with ESMTP id 05A6642E1B\n for <dev@dpdk.org>; Thu, 21 Mar 2024 17:19:22 +0100 (CET)",
            "by mail-qk1-f178.google.com with SMTP id\n af79cd13be357-789f1b59a28so75638885a.3\n for <dev@dpdk.org>; Thu, 21 Mar 2024 09:19:21 -0700 (PDT)",
            "from hermes.local (204-195-123-203.wavecable.com. [204.195.123.203])\n by smtp.gmail.com with ESMTPSA id\n w62-20020a638241000000b005e485fbd455sm41815pgd.45.2024.03.21.09.12.01\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 21 Mar 2024 09:12:02 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1711037961;\n x=1711642761; darn=dpdk.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=YasWm7iHbQbdWvAWYjHC7AHoqXZSd0sHra3BoBBQ/fw=;\n b=DhMVvFflzQpu0+FwkAdWhMQO8dO+IlhqQEjaysW/G81U2e9BZjJMD6rjdMf0lBBQFr\n Yv/jFuayCRfwdVNTD0ZtOIXpBG4Rq81sQg+XwRO0TmzWzgFoHQhHY9PMRBuYiDHXGPj4\n V3hEmV5NL8pFRnzVNCvdo79gZGdbXzhg3VrzTnQ5Xb1/KZG+DP5Yd9XnGkkdwIB48/ex\n xvaM5v/jadu5A/CXCDouL53Ch8cogM0Cu1oBYkTjrxbipGPmlo4QUYliapjPUsJltBSC\n UFjzmFMJJCSH4xHjJRkySbx26l24UDYJDPluVPgfxjdMkyDejoHh+/a3hBVeDZkA1CJP\n uZZw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1711037961; x=1711642761;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=YasWm7iHbQbdWvAWYjHC7AHoqXZSd0sHra3BoBBQ/fw=;\n b=A4nwd7WM6XSli0Hq08ryzLsHMqZxUDUbDkg6DMCk7DZtXbUs5EyOGhNul8g2evXN9a\n BP005UpG4e01uH/iZxAQoebWdLgHo7STI3A8yrZBMFPHTyL6zGbMsChA3GNFdomSUUVn\n Pe6ani2V2WslCAdjfHXxQliLz75uMpy2Rpn/fYwbImnnsJ2xUbxbN6TnZpHTBL4fYTab\n e2i/e/AVidBATDFoLXIHQw56wF6OCzlunydGOkCgIWgDrmMG4A56U+yjvzT9VjIWbQDc\n WxiGFj2H3KwnXWAVyq5MzCedso75JnAKZ9CtRy6/a8MHssBwpZ/OqS/yvuTKIFDNaoDq\n BGnQ==",
        "X-Gm-Message-State": "AOJu0YyrUBjnfxi8Hzbo8Cnaf9GIsA7FGp7+c1vSR1BphqoVgczLlDEF\n Ao7ZiST69oTtdSmFo3X+a9S2FTnl5G7NZSP6cnTWGB+eKICdihgL5jfBf9S8fBxSVcGVmza39Pi\n J",
        "X-Google-Smtp-Source": "\n AGHT+IFuJ2g+Xz0x4n2/EaHugsIoUMxIK3PsbH/nRpU8fCdWidx402cYQpVvteEikCXqnvgaEv3TLg==",
        "X-Received": "by 2002:a05:6358:d5aa:b0:17b:416a:38ba with SMTP id\n ms42-20020a056358d5aa00b0017b416a38bamr24642865rwb.26.1711037522728;\n Thu, 21 Mar 2024 09:12:02 -0700 (PDT)",
        "From": "Stephen Hemminger <stephen@networkplumber.org>",
        "To": "dev@dpdk.org",
        "Cc": "Stephen Hemminger <stephen@networkplumber.org>",
        "Subject": "[PATCH v10 08/10] eal: add option to put timestamp on console output",
        "Date": "Thu, 21 Mar 2024 09:00:24 -0700",
        "Message-ID": "<20240321161146.340421-9-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20240321161146.340421-1-stephen@networkplumber.org>",
        "References": "<20200814173441.23086-1-stephen@networkplumber.org>\n <20240321161146.340421-1-stephen@networkplumber.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "When debugging driver or startup issues, it is useful to have\na timestamp on each message printed. The messages in syslog\nalready have a timestamp, but often syslog is not available\nduring testing.\n\nThere are multiple timestamp formats similar to Linux dmesg.\nThe default is time relative since startup. Other alternatives\nare delta, ctime, reltime and iso formats.\n\nExample:\n$ dpdk-testpmd --log-timestamp -- -i\nEAL: Detected CPU lcores: 8\nEAL: Detected NUMA nodes: 1\n[     0.000083] EAL: Detected static linkage of DPDK\n[     0.002000] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket\n[     0.003507] EAL: Selected IOVA mode 'VA'\n[     0.006272] testpmd: No probed ethernet devices\nInteractive-mode selected\n[     0.029567] testpmd: create a new mbuf pool <mb_pool_0>: n=203456, size=2176, socket=0\n[     0.029588] testpmd: preferred mempool ops selected: ring_mp_mc\n\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n app/test/test_eal_flags.c           |  17 ++++\n doc/guides/prog_guide/log_lib.rst   |  10 ++\n lib/eal/common/eal_common_options.c |  14 ++-\n lib/eal/common/eal_options.h        |   2 +\n lib/log/log_internal.h              |   9 ++\n lib/log/log_unix.c                  | 152 +++++++++++++++++++++++++++-\n lib/log/log_windows.c               |   6 ++\n lib/log/version.map                 |   1 +\n 8 files changed, 205 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/app/test/test_eal_flags.c b/app/test/test_eal_flags.c\nindex 6cb4b0675730..eeb1799381d7 100644\n--- a/app/test/test_eal_flags.c\n+++ b/app/test/test_eal_flags.c\n@@ -1055,6 +1055,14 @@ test_misc_flags(void)\n \tconst char * const argv22[] = {prgname, prefix, mp_flag,\n \t\t\t\t       \"--huge-worker-stack=512\"};\n \n+\t/* Try running with --log-timestamp */\n+\tconst char * const argv23[] = {prgname, prefix, mp_flag,\n+\t\t\t\t       \"--log-timestamp\" };\n+\n+\t/* Try running with --log-timestamp=iso */\n+\tconst char * const argv24[] = {prgname, prefix, mp_flag,\n+\t\t\t\t       \"--log-timestamp=iso\" };\n+\n \t/* run all tests also applicable to FreeBSD first */\n \n \tif (launch_proc(argv0) == 0) {\n@@ -1162,6 +1170,15 @@ test_misc_flags(void)\n \t\tprintf(\"Error - process did not run ok with --huge-worker-stack=size parameter\\n\");\n \t\tgoto fail;\n \t}\n+\tif (launch_proc(argv23) != 0) {\n+\t\tprintf(\"Error - process did not run ok with --log-timestamp parameter\\n\");\n+\t\tgoto fail;\n+\t}\n+\tif (launch_proc(argv24) != 0) {\n+\t\tprintf(\"Error - process did not run ok with --log-timestamp=iso parameter\\n\");\n+\t\tgoto fail;\n+\t}\n+\n \n \trmdir(hugepath_dir3);\n \trmdir(hugepath_dir2);\ndiff --git a/doc/guides/prog_guide/log_lib.rst b/doc/guides/prog_guide/log_lib.rst\nindex aacb36c36ce0..1d6b2e3cea5d 100644\n--- a/doc/guides/prog_guide/log_lib.rst\n+++ b/doc/guides/prog_guide/log_lib.rst\n@@ -73,6 +73,16 @@ For example::\n \t/path/to/app --syslog local0\n \n \n+Console timestamp\n+~~~~~~~~~~~~~~~~~\n+\n+On Linux and FreeBSD, an optional timestamp can be added before each\n+message by adding the ``--log-timestamp`` option.\n+For example::\n+\n+\t/path/to/app --log-level=lib.*:debug --log-timestamp\n+\n+\n Using Logging APIs to Generate Log Messages\n -------------------------------------------\n \ndiff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c\nindex 7310d10dfd78..4e2c3d0f255c 100644\n--- a/lib/eal/common/eal_common_options.c\n+++ b/lib/eal/common/eal_common_options.c\n@@ -77,6 +77,7 @@ eal_long_options[] = {\n \t{OPT_IOVA_MODE,\t        1, NULL, OPT_IOVA_MODE_NUM        },\n \t{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },\n \t{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },\n+\t{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },\n \t{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },\n \t{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },\n \t{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },\n@@ -1663,6 +1664,7 @@ eal_log_level_parse(int argc, char * const argv[])\n \n \t\tswitch (opt) {\n \t\tcase OPT_LOG_LEVEL_NUM:\n+\t\tcase OPT_LOG_TIMESTAMP_NUM:\n \t\t\tif (eal_parse_common_option(opt, optarg, internal_conf) < 0)\n \t\t\t\treturn -1;\n \t\t\tbreak;\n@@ -1890,7 +1892,7 @@ eal_parse_common_option(int opt, const char *optarg,\n \t\tbreak;\n #endif\n \n-\tcase OPT_LOG_LEVEL_NUM: {\n+\tcase OPT_LOG_LEVEL_NUM:\n \t\tif (eal_parse_log_level(optarg) < 0) {\n \t\t\tEAL_LOG(ERR,\n \t\t\t\t\"invalid parameters for --\"\n@@ -1898,9 +1900,16 @@ eal_parse_common_option(int opt, const char *optarg,\n \t\t\treturn -1;\n \t\t}\n \t\tbreak;\n-\t}\n \n #ifndef RTE_EXEC_ENV_WINDOWS\n+\tcase OPT_LOG_TIMESTAMP_NUM:\n+\t\tif (eal_log_timestamp(optarg) < 0) {\n+\t\t\tEAL_LOG(ERR, \"invalid parameters for --\"\n+\t\t\t\tOPT_LOG_TIMESTAMP);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\n \tcase OPT_TRACE_NUM: {\n \t\tif (eal_trace_args_save(optarg) < 0) {\n \t\t\tEAL_LOG(ERR, \"invalid parameters for --\"\n@@ -2261,6 +2270,7 @@ eal_common_usage(void)\n \t       \"  --\"OPT_PROC_TYPE\"         Type of this process (primary|secondary|auto)\\n\"\n #ifndef RTE_EXEC_ENV_WINDOWS\n \t       \"  --\"OPT_SYSLOG\"            Set syslog facility\\n\"\n+\t       \"  --\"OPT_LOG_TIMESTAMP\"     Timestamp log output\\n\"\n #endif\n \t       \"  --\"OPT_LOG_LEVEL\"=<level> Set global log level\\n\"\n \t       \"  --\"OPT_LOG_LEVEL\"=<type-match>:<level>\\n\"\ndiff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h\nindex f3f2e104f6d7..e24c9eca53ca 100644\n--- a/lib/eal/common/eal_options.h\n+++ b/lib/eal/common/eal_options.h\n@@ -35,6 +35,8 @@ enum {\n \tOPT_LCORES_NUM,\n #define OPT_LOG_LEVEL         \"log-level\"\n \tOPT_LOG_LEVEL_NUM,\n+#define OPT_LOG_TIMESTAMP     \"log-timestamp\"\n+\tOPT_LOG_TIMESTAMP_NUM,\n #define OPT_TRACE             \"trace\"\n \tOPT_TRACE_NUM,\n #define OPT_TRACE_DIR         \"trace-dir\"\ndiff --git a/lib/log/log_internal.h b/lib/log/log_internal.h\nindex c77e687e28bc..0e18d147cf98 100644\n--- a/lib/log/log_internal.h\n+++ b/lib/log/log_internal.h\n@@ -5,8 +5,10 @@\n #ifndef LOG_INTERNAL_H\n #define LOG_INTERNAL_H\n \n+#include <stdbool.h>\n #include <stdio.h>\n #include <stdint.h>\n+#include <time.h>\n \n #include <rte_compat.h>\n \n@@ -44,4 +46,11 @@ const char *eal_log_level2str(uint32_t level);\n __rte_internal\n void rte_eal_log_cleanup(void);\n \n+/*\n+ * Add timestamp to console logs\n+ */\n+__rte_internal\n+int eal_log_timestamp(const char *fmt);\n+\n+\n #endif /* LOG_INTERNAL_H */\ndiff --git a/lib/log/log_unix.c b/lib/log/log_unix.c\nindex c56f80ac6967..cb8f17bc83ef 100644\n--- a/lib/log/log_unix.c\n+++ b/lib/log/log_unix.c\n@@ -2,28 +2,169 @@\n  * Copyright(c) 2010-2014 Intel Corporation\n  */\n \n+#include <stdbool.h>\n #include <stdio.h>\n+#include <string.h>\n #include <sys/types.h>\n+#include <sys/uio.h>\n #include <syslog.h>\n+#include <time.h>\n+#include <unistd.h>\n \n #include <rte_log.h>\n \n #include \"log_internal.h\"\n \n+enum eal_log_time_format {\n+\tEAL_LOG_TIMESTAMP_NONE = 0,\n+\tEAL_LOG_TIMESTAMP_TIME,\t\t/* time since start */\n+\tEAL_LOG_TIMESTAMP_DELTA,\t/* time since last message */\n+\tEAL_LOG_TIMESTAMP_RELTIME,\n+\tEAL_LOG_TIMESTAMP_CTIME,\n+\tEAL_LOG_TIMESTAMP_ISO,\n+};\n+\n+static struct {\n+\tenum eal_log_time_format time_format;\n+\tstruct timespec start_time;\n+\tstruct timespec last_time;\n+\tstruct tm last_tm;\n+} log = {\n+\t.time_format = EAL_LOG_TIMESTAMP_NONE,\n+};\n+\n+int\n+eal_log_timestamp(const char *str)\n+{\n+\tif (str == NULL)\n+\t\tlog.time_format = EAL_LOG_TIMESTAMP_TIME;\n+\telse if (strcmp(str, \"notime\") == 0)\n+\t\tlog.time_format = EAL_LOG_TIMESTAMP_NONE;\n+\telse if (strcmp(str, \"reltime\") == 0)\n+\t\tlog.time_format = EAL_LOG_TIMESTAMP_RELTIME;\n+\telse if (strcmp(str, \"delta\") == 0)\n+\t\tlog.time_format = EAL_LOG_TIMESTAMP_DELTA;\n+\telse if (strcmp(str, \"ctime\") == 0)\n+\t\tlog.time_format =  EAL_LOG_TIMESTAMP_CTIME;\n+\telse if (strcmp(str, \"iso\") == 0)\n+\t\tlog.time_format = EAL_LOG_TIMESTAMP_ISO;\n+\telse\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static struct timespec\n+timespec_sub(const struct timespec *t0, const struct timespec *t1)\n+{\n+\tstruct timespec ts;\n+\n+\tts.tv_sec = t0->tv_sec - t1->tv_sec;\n+\tts.tv_nsec = t0->tv_nsec - t1->tv_nsec;\n+\tif (ts.tv_nsec < 0) {\n+\t\tts.tv_sec--;\n+\t\tts.tv_nsec += 1000000000L;\n+\t}\n+\treturn ts;\n+}\n+\n+static ssize_t\n+console_log_timestamp(char *tsbuf, size_t tsbuflen)\n+{\n+\tstruct timespec now, ts;\n+\tstruct tm *tm, cur;\n+\n+\tswitch (log.time_format) {\n+\tcase EAL_LOG_TIMESTAMP_NONE:\n+\t\treturn 0;\n+\n+\tcase EAL_LOG_TIMESTAMP_TIME:\n+\t\tif (clock_gettime(CLOCK_MONOTONIC, &now) < 0)\n+\t\t\treturn 0;\n+\n+\t\tts = timespec_sub(&now, &log.start_time);\n+\n+\t\treturn snprintf(tsbuf, tsbuflen, \"%6lu.%06lu\",\n+\t\t\t\tts.tv_sec, ts.tv_nsec / 1000u);\n+\n+\tcase EAL_LOG_TIMESTAMP_DELTA:\n+\t\tif (clock_gettime(CLOCK_MONOTONIC, &now) < 0)\n+\t\t\treturn 0;\n+\n+\t\tts = timespec_sub(&now, &log.last_time);\n+\t\tlog.last_time = now;\n+\n+\t\treturn snprintf(tsbuf, tsbuflen, \"<%6lu.%06lu>\",\n+\t\t\t\tts.tv_sec, ts.tv_nsec / 1000u);\n+\n+\tcase EAL_LOG_TIMESTAMP_RELTIME:\n+\t\tif (clock_gettime(CLOCK_REALTIME, &now) < 0)\n+\t\t\treturn 0;\n+\n+\t\ttm = localtime_r(&now.tv_sec, &cur);\n+\t\tts = timespec_sub(&now, &log.last_time);\n+\t\tlog.last_time = now;\n+\n+\t\t/* if minute, day, hour hasn't changed then print delta */\n+\t\tif (cur.tm_min != log.last_tm.tm_min ||\n+\t\t    cur.tm_hour != log.last_tm.tm_hour ||\n+\t\t    cur.tm_yday != log.last_tm.tm_yday) {\n+\t\t\tlog.last_tm = cur;\n+\t\t\treturn strftime(tsbuf, tsbuflen, \"%b%e %H:%M\", tm);\n+\t\t} else {\n+\t\t\treturn snprintf(tsbuf, tsbuflen, \"+%4lu.%06lu\",\n+\t\t\t\t\tts.tv_sec, ts.tv_nsec / 1000u);\n+\t\t}\n+\n+\tcase EAL_LOG_TIMESTAMP_CTIME: {\n+\t\tchar cbuf[32]; /* \"Wed Jun 30 21:49:08 1993\\n\" */\n+\n+\t\tif (clock_gettime(CLOCK_REALTIME, &now) < 0)\n+\t\t\treturn 0;\n+\n+\t\t/* .24s is to remove newline from ctime result */\n+\t\treturn snprintf(tsbuf, tsbuflen, \"%.24s\",\n+\t\t\t\tctime_r(&now.tv_sec, cbuf));\n+\t}\n+\n+\tcase EAL_LOG_TIMESTAMP_ISO: {\n+\t\tchar dbuf[64]; /* \"2024-05-01T22:11:00\" */\n+\t\tif (clock_gettime(CLOCK_REALTIME, &now) < 0)\n+\t\t\treturn 0;\n+\t\ttm = localtime_r(&now.tv_sec, &cur);\n+\n+\t\t/* make \"2024-05-01T22:11:00,123456+0100\" */\n+\t\tif (strftime(dbuf, sizeof(dbuf), \"%Y-%m-%dT%H:%M:%S\", tm) == 0)\n+\t\t\treturn 0;\n+\n+\t\treturn snprintf(tsbuf, tsbuflen, \"%s,%06lu%+03ld:%02ld\", dbuf,\n+\t\t\t\tnow.tv_nsec / 1000u,\n+\t\t\t\ttm->tm_gmtoff / 3600,\n+\t\t\t\t(tm->tm_gmtoff / 60) % 60);\n+\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n /*\n  * default log function\n  */\n static ssize_t\n-console_log_write(__rte_unused void *c, const char *buf, size_t size)\n+console_log_write(__rte_unused void *c, const char *msg, size_t size)\n {\n+\tchar buf[128];\n \tssize_t ret;\n \n-\t/* write on stderr */\n-\tret = fwrite(buf, 1, size, stderr);\n+\tret = console_log_timestamp(buf, sizeof(buf));\n+\tif (ret == 0)\n+\t\tret = fwrite(msg, 1, size, stderr);\n+\telse\n+\t\tret = fprintf(stderr, \"[%s] %.*s\", buf, (int)size, msg);\n \tfflush(stderr);\n \n \t/* Syslog error levels are from 0 to 7, so subtract 1 to convert */\n-\tsyslog(rte_log_cur_msg_loglevel() - 1, \"%.*s\", (int)size, buf);\n+\tsyslog(rte_log_cur_msg_loglevel() - 1, \"%.*s\", (int)size, msg);\n \n \treturn ret;\n }\n@@ -49,6 +190,9 @@ eal_log_init(const char *id, int facility)\n {\n \tFILE *log_stream;\n \n+\tclock_gettime(CLOCK_MONOTONIC, &log.start_time);\n+\tlog.last_time = log.start_time;\n+\n \t/* skip if user has already setup a log stream */\n \tif (eal_log_get_default())\n \t\treturn 0;\ndiff --git a/lib/log/log_windows.c b/lib/log/log_windows.c\nindex a6a08895501e..8aa68a181bec 100644\n--- a/lib/log/log_windows.c\n+++ b/lib/log/log_windows.c\n@@ -6,6 +6,12 @@\n #include <rte_log.h>\n #include \"log_internal.h\"\n \n+int\n+eal_log_timestamp(__rte_unused const char *fmt)\n+{\n+\treturn -1; /* not implemented */\n+}\n+\n /* set the log to default function, called during eal init process. */\n int\n eal_log_init(__rte_unused const char *id, __rte_unused int facility)\ndiff --git a/lib/log/version.map b/lib/log/version.map\nindex 6ecc656d1d65..697cdb3cb1b2 100644\n--- a/lib/log/version.map\n+++ b/lib/log/version.map\n@@ -31,5 +31,6 @@ INTERNAL {\n \teal_log_save_pattern;\n \teal_log_save_regexp;\n \teal_log_set_default;\n+\teal_log_timestamp;\n \trte_eal_log_cleanup;\n };\n",
    "prefixes": [
        "v10",
        "08/10"
    ]
}