Skip to content

Commit 82549de

Browse files
committed
Emit timestamps on each line of output
This commit adds the --timestamp command line option to allow cprover tools to emit timestamps before each line of output. The timestamps are either pretty-formatted wall-clock times (which may decrease as time passes in the event of a leap-second or daylight savings time event), or raw numbers that are guaranteed to increase. In either case, the timestamps have microsecond precision if supported by the underlying platform.
1 parent 3f6965b commit 82549de

15 files changed

+204
-12
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ void cbmc_parse_optionst::help()
10291029
" --json-ui use JSON-formatted output\n"
10301030
HELP_GOTO_TRACE
10311031
" --verbosity # verbosity level\n"
1032+
HELP_TIMESTAMP
10321033
"\n";
10331034
// clang-format on
10341035
}

src/cbmc/cbmc_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <util/ui_message.h>
1616
#include <util/parse_options.h>
17+
#include <util/timestamper.h>
1718

1819
#include <langapi/language.h>
1920

@@ -62,6 +63,7 @@ class optionst;
6263
"(version)" \
6364
"(cover):(symex-coverage-report):" \
6465
"(mm):" \
66+
OPT_TIMESTAMP \
6567
"(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \
6668
"(ppc-macos)(unsigned-char)" \
6769
"(arrays-uf-always)(arrays-uf-never)" \

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,5 +906,6 @@ void goto_analyzer_parse_optionst::help()
906906
"\n"
907907
"Other options:\n"
908908
" --version show version and exit\n"
909+
HELP_TIMESTAMP
909910
"\n";
910911
}

src/goto-analyzer/goto_analyzer_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Author: Daniel Kroening, [email protected]
103103

104104
#include <util/ui_message.h>
105105
#include <util/parse_options.h>
106+
#include <util/timestamper.h>
106107

107108
#include <langapi/language.h>
108109

@@ -135,6 +136,7 @@ class optionst;
135136
"(show-local-may-alias)" \
136137
"(json):(xml):" \
137138
"(text):(dot):" \
139+
OPT_TIMESTAMP \
138140
"(unreachable-instructions)(unreachable-functions)" \
139141
"(reachable-functions)" \
140142
"(intervals)(show-intervals)" \

src/goto-diff/goto_diff_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,5 +501,6 @@ void goto_diff_parse_optionst::help()
501501
"Other options:\n"
502502
" --version show version and exit\n"
503503
" --json-ui use JSON-formatted output\n"
504+
HELP_TIMESTAMP
504505
"\n";
505506
}

src/goto-diff/goto_diff_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Peter Schrammel
1414

1515
#include <util/ui_message.h>
1616
#include <util/parse_options.h>
17+
#include <util/timestamper.h>
1718

1819
#include <goto-programs/goto_model.h>
1920
#include <goto-programs/show_goto_functions.h>
@@ -27,6 +28,7 @@ class optionst;
2728
"(json-ui)" \
2829
OPT_SHOW_GOTO_FUNCTIONS \
2930
"(verbosity):(version)" \
31+
OPT_TIMESTAMP \
3032
"u(unified)(change-impact)(forward-impact)(backward-impact)" \
3133
"(compact-output)"
3234

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,5 +1568,6 @@ void goto_instrument_parse_optionst::help()
15681568
" --version show version and exit\n"
15691569
" --xml-ui use XML-formatted output\n"
15701570
" --json-ui use JSON-formatted output\n"
1571+
HELP_TIMESTAMP
15711572
"\n";
15721573
}

src/goto-instrument/goto_instrument_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <util/ui_message.h>
1616
#include <util/parse_options.h>
17+
#include <util/timestamper.h>
1718

1819
#include <goto-programs/goto_functions.h>
1920
#include <goto-programs/show_goto_functions.h>
@@ -66,6 +67,7 @@ Author: Daniel Kroening, [email protected]
6667
"(show-claims)(show-properties)(property):" \
6768
"(show-symbol-table)(show-points-to)(show-rw-set)" \
6869
"(cav11)" \
70+
OPT_TIMESTAMP \
6971
"(show-natural-loops)(accelerate)(havoc-loops)" \
7072
"(error-label):(string-abstraction)" \
7173
"(verbosity):(version)(xml-ui)(json-ui)(show-loops)" \

src/jbmc/jbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,5 +956,6 @@ void jbmc_parse_optionst::help()
956956
" --json-ui use JSON-formatted output\n"
957957
HELP_GOTO_TRACE
958958
" --verbosity # verbosity level\n"
959+
HELP_TIMESTAMP
959960
"\n";
960961
}

src/jbmc/jbmc_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <util/ui_message.h>
1616
#include <util/parse_options.h>
17+
#include <util/timestamper.h>
1718

1819
#include <langapi/language.h>
1920

@@ -60,6 +61,7 @@ class optionst;
6061
"(verbosity):" \
6162
"(version)" \
6263
"(cover):(symex-coverage-report):" \
64+
OPT_TIMESTAMP \
6365
"(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)" \
6466
"(ppc-macos)" \
6567
"(arrays-uf-always)(arrays-uf-never)" \

src/util/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ SRC = arith_tools.cpp \
8484
tempdir.cpp \
8585
tempfile.cpp \
8686
threeval.cpp \
87+
timestamper.cpp \
8788
type.cpp \
8889
type_eq.cpp \
8990
typecheck.cpp \

src/util/timestamper.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*******************************************************************\
2+
3+
Module: Timestamps
4+
5+
Author: Kareem Khazem <[email protected]>
6+
7+
\*******************************************************************/
8+
9+
#include "timestamper.h"
10+
11+
#include <chrono>
12+
#include <cstdlib>
13+
#include <iomanip>
14+
#include <sstream>
15+
16+
#include "invariant.h"
17+
18+
std::unique_ptr<const timestampert>
19+
timestampert::make(timestampert::clockt clock_type)
20+
{
21+
#ifdef _WIN32
22+
return std::unique_ptr<const timestampert>(new timestampert());
23+
#else
24+
switch(clock_type)
25+
{
26+
case timestampert::clockt::NONE:
27+
return std::unique_ptr<const timestampert>(new timestampert());
28+
case timestampert::clockt::MONOTONIC:
29+
return std::unique_ptr<const monotonic_timestampert>(
30+
new monotonic_timestampert());
31+
case timestampert::clockt::WALL_CLOCK:
32+
return std::unique_ptr<const wall_clock_timestampert>(
33+
new wall_clock_timestampert());
34+
}
35+
UNREACHABLE;
36+
#endif
37+
}
38+
39+
#ifndef _WIN32
40+
std::string monotonic_timestampert::stamp() const
41+
{
42+
std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>
43+
time_stamp = std::chrono::time_point_cast<std::chrono::microseconds>(
44+
std::chrono::steady_clock::now());
45+
46+
auto cnt = time_stamp.time_since_epoch().count();
47+
std::lldiv_t divmod = lldiv(cnt, 1000000);
48+
49+
std::stringstream ss;
50+
ss << divmod.quot << "." << std::setfill('0') << std::setw(6) << divmod.rem
51+
<< " ";
52+
return ss.str();
53+
}
54+
55+
#define WALL_FORMAT "%Y-%m-%dT%H:%M:%S."
56+
57+
std::string wall_clock_timestampert::stamp() const
58+
{
59+
std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>
60+
time_stamp = std::chrono::time_point_cast<std::chrono::microseconds>(
61+
std::chrono::system_clock::now());
62+
63+
unsigned u_seconds = time_stamp.time_since_epoch().count() % 1000000;
64+
65+
std::time_t tt = std::chrono::system_clock::to_time_t(time_stamp);
66+
std::tm local = *std::localtime(&tt);
67+
68+
std::stringstream ss;
69+
ss << std::put_time(&local, WALL_FORMAT) << std::setfill('0') << std::setw(6)
70+
<< u_seconds << " ";
71+
return ss.str();
72+
}
73+
#endif

src/util/timestamper.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/// \file timestamper.h
2+
/// \brief Emit timestamps
3+
/// \author Kareem Khazem <[email protected]>
4+
5+
#ifndef CPROVER_UTIL_TIMESTAMPER_H
6+
#define CPROVER_UTIL_TIMESTAMPER_H
7+
8+
#ifdef _WIN32
9+
#define OPT_TIMESTAMP ""
10+
#define HELP_TIMESTAMP ""
11+
#else
12+
#define OPT_TIMESTAMP "(timestamp):"
13+
14+
#define HELP_TIMESTAMP \
15+
" --timestamp <monotonic|wall> print microsecond-precision timestamps.\n" \
16+
" monotonic: stamps increase monotonically.\n" \
17+
" wall: ISO-8601 wall clock timestamps.\n"
18+
#endif
19+
20+
#include <memory>
21+
#include <string>
22+
23+
/// \brief Timestamp class hierarchy
24+
///
25+
/// This class hierarchy supports generation of timestamps in various textual
26+
/// formats. The timestamps returned by instances of this class are empty; more
27+
/// meaningful timestamps are returned by derived classes.
28+
///
29+
/// Instances of this class can be instantiated to emit empty timestamps, in
30+
/// case the user did not specify `--timestamp` on the command line. The
31+
/// intended use of this class hierarchy is to create a pointer or
32+
/// std::unique_ptr called `time` to a timestampert, and to initialize `time`
33+
/// with either an actual \ref timestampert object or one of the derived
34+
/// classes based on whether the user has asked for timestamps to be emitted.
35+
/// Clients can thus unconditionally call `time->stamp()` and prepend that
36+
/// string to any logging messages; if the user didn't ask for timestamps, then
37+
/// the object pointed to by `time` will be a \ref timestampert and thus
38+
/// timestampert::stamp() will return only an empty string. Derived classes
39+
/// emit an actual timestamp followed by a space, so no conditional checking is
40+
/// needed by the client.
41+
class timestampert
42+
{
43+
public:
44+
/// \brief Derived types of \ref timestampert
45+
enum class clockt
46+
{
47+
/// \ref timestampert
48+
NONE,
49+
/// monotonic_timestampert
50+
MONOTONIC,
51+
/// wall_clock_timestampert
52+
WALL_CLOCK
53+
};
54+
virtual ~timestampert() = default;
55+
56+
/// \brief Default timestamp: the empty string
57+
virtual std::string stamp() const
58+
{
59+
return "";
60+
}
61+
62+
/// \brief Factory method to build timestampert subclasses
63+
static std::unique_ptr<const timestampert> make(clockt clock_type);
64+
};
65+
66+
#ifndef _WIN32
67+
class monotonic_timestampert : public timestampert
68+
{
69+
public:
70+
/// \brief See \ref HELP_TIMESTAMP in util/timestamper.h for time
71+
/// stamp format
72+
virtual std::string stamp() const override;
73+
};
74+
75+
class wall_clock_timestampert : public timestampert
76+
{
77+
public:
78+
/// \brief See \ref HELP_TIMESTAMP in util/timestamper.h for time
79+
/// stamp format
80+
virtual std::string stamp() const override;
81+
};
82+
#endif
83+
84+
#endif /* CPROVER_UTIL_TIMESTAMPER_H */

src/util/ui_message.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ Author: Daniel Kroening, [email protected]
1919
#include "cmdline.h"
2020

2121
ui_message_handlert::ui_message_handlert(
22-
uit __ui, const std::string &program):_ui(__ui)
22+
uit __ui,
23+
const std::string &program,
24+
timestampert::clockt clock_type)
25+
: _ui(__ui), time(timestampert::make(clock_type))
2326
{
2427
switch(__ui)
2528
{
@@ -52,12 +55,19 @@ ui_message_handlert::ui_message_handlert(
5255

5356
ui_message_handlert::ui_message_handlert(
5457
const class cmdlinet &cmdline,
55-
const std::string &program):
56-
ui_message_handlert(
57-
cmdline.isset("xml-ui")?uit::XML_UI:
58-
cmdline.isset("json-ui")?uit::JSON_UI:
59-
uit::PLAIN,
60-
program)
58+
const std::string &program)
59+
: ui_message_handlert(
60+
cmdline.isset("xml-ui") ? uit::XML_UI : cmdline.isset("json-ui")
61+
? uit::JSON_UI
62+
: uit::PLAIN,
63+
program,
64+
cmdline.isset("timestamp")
65+
? cmdline.get_value("timestamp") == "monotonic"
66+
? timestampert::clockt::MONOTONIC
67+
: cmdline.get_value("timestamp") == "wall"
68+
? timestampert::clockt::WALL_CLOCK
69+
: timestampert::clockt::NONE
70+
: timestampert::clockt::NONE)
6171
{
6272
}
6373

@@ -99,7 +109,9 @@ void ui_message_handlert::print(
99109
case uit::PLAIN:
100110
{
101111
console_message_handlert console_message_handler;
102-
console_message_handler.print(level, message);
112+
std::stringstream ss;
113+
ss << time->stamp() << message;
114+
console_message_handler.print(level, ss.str());
103115
}
104116
break;
105117

src/util/ui_message.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,22 @@ Author: Daniel Kroening, [email protected]
1111
#define CPROVER_UTIL_UI_MESSAGE_H
1212

1313
#include "message.h"
14+
#include "timestamper.h"
1415

15-
class ui_message_handlert:public message_handlert
16+
class ui_message_handlert : public message_handlert
1617
{
1718
public:
1819
enum class uit { PLAIN, XML_UI, JSON_UI };
1920

20-
ui_message_handlert(uit, const std::string &program);
21+
ui_message_handlert(
22+
uit,
23+
const std::string &program,
24+
timestampert::clockt clock_type);
25+
2126
ui_message_handlert(const class cmdlinet &, const std::string &program);
22-
ui_message_handlert():
23-
_ui(uit::PLAIN)
27+
28+
ui_message_handlert()
29+
: _ui(uit::PLAIN), time(timestampert::make(timestampert::clockt::NONE))
2430
{
2531
}
2632

@@ -40,6 +46,7 @@ class ui_message_handlert:public message_handlert
4046

4147
protected:
4248
uit _ui;
49+
std::unique_ptr<const timestampert> time;
4350

4451
virtual void print(
4552
unsigned level,

0 commit comments

Comments
 (0)