diff --git a/scripts/base/frameworks/metrics/cluster.bro b/scripts/base/frameworks/metrics/cluster.bro index a17993cd27..03bbcdf584 100644 --- a/scripts/base/frameworks/metrics/cluster.bro +++ b/scripts/base/frameworks/metrics/cluster.bro @@ -41,7 +41,7 @@ export { ## This event is sent by nodes in response to a ## :bro:id:`Metrics::cluster_index_request` event. - global cluster_index_response: event(uid: string, id: string, filter_name: string, index: Index, val: count); + global cluster_index_response: event(uid: string, id: string, filter_name: string, index: Index, data: DataPoint); ## This is sent by workers to indicate that they crossed the percent of the ## current threshold by the percentage defined globally in @@ -76,7 +76,7 @@ global done_with: table[string] of count &create_expire=5mins &default=0; # This variable is maintained by managers to track intermediate responses as # they are getting a global view for a certain index. -global index_requests: table[string, string, string, Index] of count &create_expire=5mins &default=0; +global index_requests: table[string, string, string, Index] of DataPoint &create_expire=5mins &default=[]; # This variable is maintained by all hosts for different purposes. Non-managers # maintain it to know what indexes they have recently sent as intermediate @@ -157,12 +157,12 @@ event Metrics::cluster_filter_request(uid: string, id: string, filter_name: stri event Metrics::cluster_index_request(uid: string, id: string, filter_name: string, index: Index) { - local val=0; + local data: DataPoint; if ( index in store[id, filter_name] ) - val = store[id, filter_name][index]; + data = store[id, filter_name][index]; # fmt("WORKER %s: received the cluster_index_request event for %s=%d.", Cluster::node, index2str(index), val); - event Metrics::cluster_index_response(uid, id, filter_name, index, val); + event Metrics::cluster_index_response(uid, id, filter_name, index, data); } @endif @@ -195,21 +195,19 @@ function data_added(filter: Filter, index: Index, val: count) do_notice(filter, index, val); } -event Metrics::cluster_index_response(uid: string, id: string, filter_name: string, index: Index, val: count) +event Metrics::cluster_index_response(uid: string, id: string, filter_name: string, index: Index, data: DataPoint) { #print fmt("%0.6f MANAGER: receiving index data from %s", network_time(), get_event_peer()$descr); - - if ( [uid, id, filter_name, index] !in index_requests ) - index_requests[uid, id, filter_name, index] = 0; - index_requests[uid, id, filter_name, index] += val; + index_requests[uid, id, filter_name, index] = merge_data_points(index_requests[uid, id, filter_name, index], data); local ir = index_requests[uid, id, filter_name, index]; ++done_with[uid]; if ( Cluster::worker_count == done_with[uid] ) { - if ( check_notice(filter_store[id, filter_name], index, ir) ) - do_notice(filter_store[id, filter_name], index, ir); + local size = ir?$num ? ir$num : |ir$unique_vals|; + if ( check_notice(filter_store[id, filter_name], index, size) ) + do_notice(filter_store[id, filter_name], index, size); delete done_with[uid]; delete index_requests[uid, id, filter_name, index]; } @@ -233,12 +231,13 @@ event Metrics::cluster_filter_response(uid: string, id: string, filter_name: str local local_data = filter_results[uid, id, filter_name]; for ( index in data ) { - if ( index !in local_data ) - local_data[index] = 0; - local_data[index] += data[index]; + if ( index in local_data ) + local_data[index] = merge_data_points(local_data[index], data[index]); + else + local_data[index] = data[index]; } - # Mark another worker as being "done" for this uid. + # Mark another worker as being "done" for this uid. if ( done ) ++done_with[uid]; diff --git a/scripts/base/frameworks/metrics/main.bro b/scripts/base/frameworks/metrics/main.bro index e5ed63dccd..0e2496ef16 100644 --- a/scripts/base/frameworks/metrics/main.bro +++ b/scripts/base/frameworks/metrics/main.bro @@ -192,6 +192,32 @@ function index2str(index: Index): string return fmt("metric_index(%s)", out); } +function merge_data_points(dp1: DataPoint, dp2: DataPoint): DataPoint + { + local result: DataPoint; + if ( dp1?$num || dp2?$num ) + { + result$num = 0; + if ( dp1?$num ) + result$num += dp1$num; + if ( dp2?$num ) + result$num += dp2$num; + } + + if ( dp1?$unique_vals || dp2?$unique_vals ) + { + result$unique_vals = set(); + if ( dp1?$unique_vals ) + for ( val1 in dp1$unique_vals ) + add result$unique_vals[val1]; + if ( dp2?$unique_vals ) + for ( val2 in dp2$unique_vals ) + add result$unique_vals[val2]; + } + + return result; + } + function write_log(ts: time, filter: Filter, data: MetricTable) { for ( index in data ) diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log index a22deb26e4..26ee55e20f 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path metrics -#fields ts metric_id filter_name index.host index.str index.network value -#types time enum string addr string subnet count -1328303679.867377 TEST_METRIC foo-bar 6.5.4.3 - - 4 -1328303679.867377 TEST_METRIC foo-bar 7.2.1.5 - - 2 -1328303679.867377 TEST_METRIC foo-bar 1.2.3.4 - - 6 +#fields ts ts_delta filter_name metric_id index.str index.host index.network value +#types time interval string string string addr subnet count +1332957065.172883 3.000000 foo-bar test.metric - 6.5.4.3 - 4 +1332957065.172883 3.000000 foo-bar test.metric - 1.2.3.4 - 6 +1332957065.172883 3.000000 foo-bar test.metric - 7.2.1.5 - 2 diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log index 4bfb6964ea..7c625fea5b 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path metrics -#fields ts metric_id filter_name index.host index.str index.network value -#types time enum string addr string subnet count -1328303763.333948 TEST_METRIC foo-bar 6.5.4.3 - - 2 -1328303763.333948 TEST_METRIC foo-bar 7.2.1.5 - - 1 -1328303763.333948 TEST_METRIC foo-bar 1.2.3.4 - - 3 +#fields ts ts_delta filter_name metric_id index.str index.host index.network value +#types time interval string string string addr subnet count +1332956138.267655 3.000000 foo-bar test.metric - 6.5.4.3 - 2 +1332956138.267655 3.000000 foo-bar test.metric - 1.2.3.4 - 3 +1332956138.267655 3.000000 foo-bar test.metric - 7.2.1.5 - 1 diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log index 59d70896fb..d5af4008d0 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log @@ -3,6 +3,6 @@ #empty_field (empty) #unset_field - #path notice -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network -#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet -1325633225.777902 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.str metric_index.host metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double string addr subnet +1332957572.934499 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - 1.2.3.4 - diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log index 58346b79e6..bb25f5b0ea 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path notice -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network -#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet -1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - -1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - - +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.str metric_index.host metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double string addr subnet +1332956197.821031 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - - 1.2.3.4 - +1332956197.821031 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - - 6.5.4.3 - diff --git a/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro index b801074b33..425c91fb53 100644 --- a/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro +++ b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro @@ -10,8 +10,8 @@ @TEST-START-FILE cluster-layout.bro redef Cluster::nodes = { - ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1")], - ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1")], + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1", "worker-2")], ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth0"], ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth1"], }; @@ -19,20 +19,16 @@ redef Cluster::nodes = { redef Log::default_rotation_interval = 0secs; -redef enum Metrics::ID += { - TEST_METRIC, -}; - event bro_init() &priority=5 { - Metrics::add_filter(TEST_METRIC, + Metrics::add_filter("test.metric", [$name="foo-bar", $break_interval=3secs]); if ( Cluster::local_node_type() == Cluster::WORKER ) { - Metrics::add_data(TEST_METRIC, [$host=1.2.3.4], 3); - Metrics::add_data(TEST_METRIC, [$host=6.5.4.3], 2); - Metrics::add_data(TEST_METRIC, [$host=7.2.1.5], 1); + Metrics::add_data("test.metric", [$host=1.2.3.4], 3); + Metrics::add_data("test.metric", [$host=6.5.4.3], 2); + Metrics::add_data("test.metric", [$host=7.2.1.5], 1); } } diff --git a/testing/btest/scripts/base/frameworks/metrics/basic.bro b/testing/btest/scripts/base/frameworks/metrics/basic.bro index 43e7ac28ef..23a79d2bd3 100644 --- a/testing/btest/scripts/base/frameworks/metrics/basic.bro +++ b/testing/btest/scripts/base/frameworks/metrics/basic.bro @@ -1,16 +1,12 @@ # @TEST-EXEC: bro %INPUT # @TEST-EXEC: btest-diff metrics.log -redef enum Metrics::ID += { - TEST_METRIC, -}; - event bro_init() &priority=5 { - Metrics::add_filter(TEST_METRIC, + Metrics::add_filter("test.metric", [$name="foo-bar", $break_interval=3secs]); - Metrics::add_data(TEST_METRIC, [$host=1.2.3.4], 3); - Metrics::add_data(TEST_METRIC, [$host=6.5.4.3], 2); - Metrics::add_data(TEST_METRIC, [$host=7.2.1.5], 1); + Metrics::add_data("test.metric", [$host=1.2.3.4], 3); + Metrics::add_data("test.metric", [$host=6.5.4.3], 2); + Metrics::add_data("test.metric", [$host=7.2.1.5], 1); } diff --git a/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro index 701d2ea378..f442a100f0 100644 --- a/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro +++ b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro @@ -10,8 +10,8 @@ @TEST-START-FILE cluster-layout.bro redef Cluster::nodes = { - ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1")], - ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1")], + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1", "worker-2")], ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth0"], ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth1"], }; @@ -23,13 +23,9 @@ redef enum Notice::Type += { Test_Notice, }; -redef enum Metrics::ID += { - TEST_METRIC, -}; - event bro_init() &priority=5 { - Metrics::add_filter(TEST_METRIC, + Metrics::add_filter("test.metric", [$name="foo-bar", $break_interval=1hr, $note=Test_Notice, @@ -44,7 +40,7 @@ event do_metrics(i: count) # Worker-1 will trigger an intermediate update and then if everything # works correctly, the data from worker-2 will hit the threshold and # should trigger the notice. - Metrics::add_data(TEST_METRIC, [$host=1.2.3.4], i); + Metrics::add_data("test.metric", [$host=1.2.3.4], i); } event bro_init() diff --git a/testing/btest/scripts/base/frameworks/metrics/notice.bro b/testing/btest/scripts/base/frameworks/metrics/notice.bro index 0ac9faa956..1ed11a968c 100644 --- a/testing/btest/scripts/base/frameworks/metrics/notice.bro +++ b/testing/btest/scripts/base/frameworks/metrics/notice.bro @@ -6,19 +6,15 @@ redef enum Notice::Type += { Test_Notice, }; -redef enum Metrics::ID += { - TEST_METRIC, -}; - event bro_init() &priority=5 { - Metrics::add_filter(TEST_METRIC, + Metrics::add_filter("test.metric", [$name="foo-bar", $break_interval=3secs, $note=Test_Notice, $notice_threshold=2, $log=F]); - Metrics::add_data(TEST_METRIC, [$host=1.2.3.4], 3); - Metrics::add_data(TEST_METRIC, [$host=6.5.4.3], 2); - Metrics::add_data(TEST_METRIC, [$host=7.2.1.5], 1); + Metrics::add_data("test.metric", [$host=1.2.3.4], 3); + Metrics::add_data("test.metric", [$host=6.5.4.3], 2); + Metrics::add_data("test.metric", [$host=7.2.1.5], 1); }