diff --git a/scripts/base/frameworks/logging/main.bro b/scripts/base/frameworks/logging/main.bro index 153663607d..6a0618fd07 100644 --- a/scripts/base/frameworks/logging/main.bro +++ b/scripts/base/frameworks/logging/main.bro @@ -40,6 +40,45 @@ export { ## Returns: The path to be used for the filter. global default_path_func: function(id: ID, path: string, rec: any) : string &redef; + # Log rotation support. + + ## Information passed into rotation callback functions. + type RotationInfo: record { + writer: Writer; ##< Writer. + fname: string; ##< Full name of the rotated file. + path: string; ##< Original path value. + open: time; ##< Time when opened. + close: time; ##< Time when closed. + terminating: bool; ##< True if rotation occured due to Bro shutting down. + }; + + ## Default rotation interval. Zero disables rotation. + const default_rotation_interval = 0secs &redef; + + ## Default naming format for timestamps embedded into filenames. Uses a strftime() style. + const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; + + ## Default shell command to run on rotated files. Empty for none. + const default_rotation_postprocessor_cmd = "" &redef; + + ## Specifies the default postprocessor function per writer type. Entries in this + ## table are initialized by each writer type. + const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef; + + ## Type for controlling file rotation. + type RotationControl: record { + ## Rotation interval. + interv: interval &default=default_rotation_interval; + ## Callback function to trigger for rotated files. If not set, the default + ## comes out of default_rotation_postprocessors. + postprocessor: function(info: RotationInfo) : bool &optional; + }; + + ## Specifies rotation parameters per ``(id, path)`` tuple. + ## If a pair is not found in this table, default values defined in + ## ``RotationControl`` are used. + const rotation_control: table[Writer, string] of RotationControl &default=[] &redef; + ## Filter customizing logging. type Filter: record { ## Descriptive name to reference this filter. @@ -96,47 +135,13 @@ export { ## If true, entries are passed on to remote peers. log_remote: bool &default=enable_remote_logging; + + ## If set, the rotation control value is automatically added to + ## :bro:id:`Log::rotation_control` for the filter's (writer, path) + ## when adding the filter to a stream via :bro:id:`Log::add_filter` + rotation: RotationControl &optional; }; - # Log rotation support. - - ## Information passed into rotation callback functions. - type RotationInfo: record { - writer: Writer; ##< Writer. - fname: string; ##< Full name of the rotated file. - path: string; ##< Original path value. - open: time; ##< Time when opened. - close: time; ##< Time when closed. - terminating: bool; ##< True if rotation occured due to Bro shutting down. - }; - - ## Default rotation interval. Zero disables rotation. - const default_rotation_interval = 0secs &redef; - - ## Default naming format for timestamps embedded into filenames. Uses a strftime() style. - const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; - - ## Default shell command to run on rotated files. Empty for none. - const default_rotation_postprocessor_cmd = "" &redef; - - ## Specifies the default postprocessor function per writer type. Entries in this - ## table are initialized by each writer type. - const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef; - - ## Type for controlling file rotation. - type RotationControl: record { - ## Rotation interval. - interv: interval &default=default_rotation_interval; - ## Callback function to trigger for rotated files. If not set, the default - ## comes out of default_rotation_postprocessors. - postprocessor: function(info: RotationInfo) : bool &optional; - }; - - ## Specifies rotation parameters per ``(id, path)`` tuple. - ## If a pair is not found in this table, default values defined in - ## ``RotationControl`` are used. - const rotation_control: table[Writer, string] of RotationControl &default=[] &redef; - ## Sentinel value for indicating that a filter was not found when looked up. const no_filter: Filter = [$name=""]; # Sentinel. diff --git a/src/LogMgr.cc b/src/LogMgr.cc index 950de24a8f..368cb84e30 100644 --- a/src/LogMgr.cc +++ b/src/LogMgr.cc @@ -382,6 +382,17 @@ bool LogVal::Write(SerializationFormat* fmt) const LogMgr::Filter::~Filter() { + // If there's a rotation control table entry associated with this + // filter's (writer, path), remove it + TableVal* rc = BifConst::Log::rotation_control->AsTableVal(); + + ListVal* index = new ListVal(TYPE_ANY); + index->Append(writer->Ref()); + index->Append(path_val->Ref()); + + Unref(rc->Delete(index)); + Unref(index); + for ( int i = 0; i < num_fields; ++i ) delete fields[i]; @@ -791,6 +802,21 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) // Remove any filter with the same name we might already have. RemoveFilter(id, filter->name); + // Install the rotation support, if given + Val* rot_val = fval->Lookup(rtype->FieldOffset("rotation")); + if ( rot_val ) + { + TableVal* rc = BifConst::Log::rotation_control->AsTableVal(); + + ListVal* index = new ListVal(TYPE_ANY); + index->Append(filter->writer->Ref()); + index->Append(filter->path_val->Ref()); + + rc->Assign(index, rot_val->Ref()); + + Unref(index); + } + // Add the new one. stream->filters.push_back(filter); diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.filter-remove-rotation/out b/testing/btest/Baseline/scripts.base.frameworks.logging.filter-remove-rotation/out new file mode 100644 index 0000000000..f07e999e38 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.filter-remove-rotation/out @@ -0,0 +1,10 @@ +{ +[WRITER_ASCII, test2] = [interv=30.0 mins, postprocessor=Test::custom_rotate +{ +print custom rotate, Test::info; +return (T); +}] +} +{ + +} diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-in-filter/out b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-in-filter/out new file mode 100644 index 0000000000..18bd12d88f --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-in-filter/out @@ -0,0 +1,83 @@ +1st test.2011-03-07-03-00-05.log test 11-03-07_03.00.05 11-03-07_04.00.05 0 +1st test.2011-03-07-04-00-05.log test 11-03-07_04.00.05 11-03-07_05.00.05 0 +1st test.2011-03-07-05-00-05.log test 11-03-07_05.00.05 11-03-07_06.00.05 0 +1st test.2011-03-07-06-00-05.log test 11-03-07_06.00.05 11-03-07_07.00.05 0 +1st test.2011-03-07-07-00-05.log test 11-03-07_07.00.05 11-03-07_08.00.05 0 +1st test.2011-03-07-08-00-05.log test 11-03-07_08.00.05 11-03-07_09.00.05 0 +1st test.2011-03-07-09-00-05.log test 11-03-07_09.00.05 11-03-07_10.00.05 0 +1st test.2011-03-07-10-00-05.log test 11-03-07_10.00.05 11-03-07_11.00.05 0 +1st test.2011-03-07-11-00-05.log test 11-03-07_11.00.05 11-03-07_12.00.05 0 +1st test.2011-03-07-12-00-05.log test 11-03-07_12.00.05 11-03-07_12.59.55 1 +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_03.00.05.log, path=test2, open=1299466805.0, close=1299470395.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_03.59.55.log, path=test2, open=1299470395.0, close=1299470405.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_04.00.05.log, path=test2, open=1299470405.0, close=1299473995.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_04.59.55.log, path=test2, open=1299473995.0, close=1299474005.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_05.00.05.log, path=test2, open=1299474005.0, close=1299477595.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_05.59.55.log, path=test2, open=1299477595.0, close=1299477605.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_06.00.05.log, path=test2, open=1299477605.0, close=1299481195.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_06.59.55.log, path=test2, open=1299481195.0, close=1299481205.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_07.00.05.log, path=test2, open=1299481205.0, close=1299484795.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_07.59.55.log, path=test2, open=1299484795.0, close=1299484805.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_08.00.05.log, path=test2, open=1299484805.0, close=1299488395.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_08.59.55.log, path=test2, open=1299488395.0, close=1299488405.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_09.00.05.log, path=test2, open=1299488405.0, close=1299491995.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_09.59.55.log, path=test2, open=1299491995.0, close=1299492005.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_10.00.05.log, path=test2, open=1299492005.0, close=1299495595.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_10.59.55.log, path=test2, open=1299495595.0, close=1299495605.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_11.00.05.log, path=test2, open=1299495605.0, close=1299499195.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_11.59.55.log, path=test2, open=1299499195.0, close=1299499205.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_12.00.05.log, path=test2, open=1299499205.0, close=1299502795.0, terminating=F] +custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_12.59.55.log, path=test2, open=1299502795.0, close=1299502795.0, terminating=T] +# t id.orig_h id.orig_p id.resp_h id.resp_p +1299466805.000000 10.0.0.1 20 10.0.0.2 1024 +1299470395.000000 10.0.0.2 20 10.0.0.3 0 +1299470405.000000 10.0.0.1 20 10.0.0.2 1025 +1299473995.000000 10.0.0.2 20 10.0.0.3 1 +1299474005.000000 10.0.0.1 20 10.0.0.2 1026 +1299477595.000000 10.0.0.2 20 10.0.0.3 2 +1299477605.000000 10.0.0.1 20 10.0.0.2 1027 +1299481195.000000 10.0.0.2 20 10.0.0.3 3 +1299481205.000000 10.0.0.1 20 10.0.0.2 1028 +1299484795.000000 10.0.0.2 20 10.0.0.3 4 +1299484805.000000 10.0.0.1 20 10.0.0.2 1029 +1299488395.000000 10.0.0.2 20 10.0.0.3 5 +1299488405.000000 10.0.0.1 20 10.0.0.2 1030 +1299491995.000000 10.0.0.2 20 10.0.0.3 6 +1299492005.000000 10.0.0.1 20 10.0.0.2 1031 +1299495595.000000 10.0.0.2 20 10.0.0.3 7 +1299495605.000000 10.0.0.1 20 10.0.0.2 1032 +1299499195.000000 10.0.0.2 20 10.0.0.3 8 +1299499205.000000 10.0.0.1 20 10.0.0.2 1033 +1299502795.000000 10.0.0.2 20 10.0.0.3 9 +> test.2011-03-07-03-00-05.log +> test.2011-03-07-04-00-05.log +> test.2011-03-07-05-00-05.log +> test.2011-03-07-06-00-05.log +> test.2011-03-07-07-00-05.log +> test.2011-03-07-08-00-05.log +> test.2011-03-07-09-00-05.log +> test.2011-03-07-10-00-05.log +> test.2011-03-07-11-00-05.log +> test.2011-03-07-12-00-05.log +> test.log +> test2-11-03-07_03.00.05.log +> test2-11-03-07_03.59.55.log +> test2-11-03-07_04.00.05.log +> test2-11-03-07_04.59.55.log +> test2-11-03-07_05.00.05.log +> test2-11-03-07_05.59.55.log +> test2-11-03-07_06.00.05.log +> test2-11-03-07_06.59.55.log +> test2-11-03-07_07.00.05.log +> test2-11-03-07_07.59.55.log +> test2-11-03-07_08.00.05.log +> test2-11-03-07_08.59.55.log +> test2-11-03-07_09.00.05.log +> test2-11-03-07_09.59.55.log +> test2-11-03-07_10.00.05.log +> test2-11-03-07_10.59.55.log +> test2-11-03-07_11.00.05.log +> test2-11-03-07_11.59.55.log +> test2-11-03-07_12.00.05.log +> test2-11-03-07_12.59.55.log +> test2.log diff --git a/testing/btest/scripts/base/frameworks/logging/filter-remove-rotation.bro b/testing/btest/scripts/base/frameworks/logging/filter-remove-rotation.bro new file mode 100644 index 0000000000..bb89116084 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/filter-remove-rotation.bro @@ -0,0 +1,30 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +module Test; + +export { + redef enum Log::ID += { Test }; + + type Info: record { + t: time; + id: conn_id; + } &log; +} + +function custom_rotate(info: Log::RotationInfo) : bool +{ + print "custom rotate", info; + return T; +} + +event bro_init() +{ + Log::create_stream(Test, [$columns=Info]); + Log::add_filter(Test, [$name="2nd", $path="test2", + $rotation=[$interv=30mins, $postprocessor=custom_rotate]]); + print Log::rotation_control; + Log::remove_filter(Test, "2nd"); + # The RotationControl should be removed now + print Log::rotation_control; +} diff --git a/testing/btest/scripts/base/frameworks/logging/rotate-in-filter.bro b/testing/btest/scripts/base/frameworks/logging/rotate-in-filter.bro new file mode 100644 index 0000000000..e1a27d0b0e --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/rotate-in-filter.bro @@ -0,0 +1,39 @@ +# +# @TEST-EXEC: bro -b -r %DIR/rotation.trace %INPUT 2>&1 | egrep "test|test2" | sort >out +# @TEST-EXEC: for i in `ls test*.log | sort`; do printf '> %s\n' $i; cat $i; done | sort | uniq >>out +# @TEST-EXEC: btest-diff out + +module Test; + +export { + # Create a new ID for our log stream + redef enum Log::ID += { Test }; + + # Define a record with all the columns the log file can have. + # (I'm using a subset of fields from ssh-ext for demonstration.) + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + } &log; +} + +redef Log::default_rotation_interval = 1hr; +redef Log::default_rotation_postprocessor_cmd = "echo 1st"; + +function custom_rotate(info: Log::RotationInfo) : bool +{ + print "custom rotate", info; + return T; +} + +event bro_init() +{ + Log::create_stream(Test, [$columns=Log]); + Log::add_filter(Test, [$name="2nd", $path="test2", + $rotation=[$interv=30mins, $postprocessor=custom_rotate]]); +} + +event new_connection(c: connection) + { + Log::write(Test, [$t=network_time(), $id=c$id]); + } diff --git a/testing/btest/scripts/base/frameworks/logging/rotate.bro b/testing/btest/scripts/base/frameworks/logging/rotate.bro index d53b92f169..4b496689f5 100644 --- a/testing/btest/scripts/base/frameworks/logging/rotate.bro +++ b/testing/btest/scripts/base/frameworks/logging/rotate.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro -r %DIR/rotation.trace %INPUT 2>&1 | grep "test" >out +# @TEST-EXEC: bro -b -r %DIR/rotation.trace %INPUT 2>&1 | grep "test" >out # @TEST-EXEC: for i in test.*.log; do printf '> %s\n' $i; cat $i; done >>out # @TEST-EXEC: btest-diff out