@@ -10,6 +10,7 @@ local checks = require("checks")
10
10
local fun = require (" fun" )
11
11
local log = require (" log" )
12
12
local fiber = require (" fiber" )
13
+ local is_metrics_package , metrics = pcall (require , " metrics" )
13
14
14
15
-- get fiber id function
15
16
local function get_fiber_id (fiber )
@@ -21,6 +22,7 @@ local function get_fiber_id(fiber)
21
22
end
22
23
23
24
local task_list = {}
25
+ local cfg = {metrics = true }
24
26
25
27
local constants = {
26
28
-- default value of number of tuples that will be checked by one iteration
@@ -49,6 +51,79 @@ local constants = {
49
51
atomic_iteration = false ,
50
52
}
51
53
54
+ local metrics_callback = nil
55
+ local metrics_collectors = nil
56
+
57
+ local function metrics_enable ()
58
+ if metrics_callback then
59
+ return
60
+ end
61
+
62
+ local supported_v0_11 = false
63
+ if is_metrics_package and metrics .unregister_callback then
64
+ local counter = require (' metrics.collectors.counter' )
65
+ supported_v0_11 = counter .remove and true or false
66
+ end
67
+ if not supported_v0_11 then
68
+ error (" metrics >= 0.11.0 is required" , 3 )
69
+ end
70
+
71
+ local create_collector = function (name , description )
72
+ return {
73
+ collector = metrics .counter (name , description ),
74
+ task_value = {},
75
+ }
76
+ end
77
+
78
+ metrics_collectors = {
79
+ [" checked_count" ] = create_collector (
80
+ " expirationd_checked_count" ,
81
+ " expirationd task's a number of checked tuples"
82
+ ),
83
+ [" expired_count" ] = create_collector (
84
+ " expirationd_expired_count" ,
85
+ " expirationd task's a number of expired tuples"
86
+ ),
87
+ [" restarts" ] = create_collector (
88
+ " expirationd_restarts" ,
89
+ " expirationd task's a number of restarts"
90
+ ),
91
+ [" working_time" ] = create_collector (
92
+ " expirationd_working_time" ,
93
+ " expirationd task's operation time"
94
+ ),
95
+ }
96
+
97
+ metrics_callback = function ()
98
+ for task_name , task in pairs (task_list ) do
99
+ local stats = task :statistics ()
100
+ for k , v in pairs (stats ) do
101
+ local prev_v = metrics_collectors [k ].task_value [task_name ] or 0
102
+ local v_inc = v - prev_v
103
+ metrics_collectors [k ].collector :inc (v_inc , {name = task_name })
104
+ metrics_collectors [k ].task_value [task_name ] = v
105
+ end
106
+ end
107
+ end
108
+ metrics .register_callback (metrics_callback )
109
+ end
110
+
111
+ if cfg .metrics then
112
+ enabled , _ = pcall (metrics_enable )
113
+ cfg .metrics = enabled
114
+ end
115
+
116
+ local function metrics_disable ()
117
+ if metrics_callback then
118
+ for _ , c in pairs (metrics_collectors ) do
119
+ metrics .registry :unregister (c .collector )
120
+ end
121
+ metrics .unregister_callback (metrics_callback )
122
+ metrics_callback = nil
123
+ metrics_collectors = nil
124
+ end
125
+ end
126
+
52
127
-- ========================================================================= --
53
128
-- Task local functions
54
129
-- ========================================================================= --
@@ -281,6 +356,12 @@ local Task_methods = {
281
356
-- @function task.kill
282
357
kill = function (self )
283
358
self :stop ()
359
+ if metrics_collectors then
360
+ for _ , c in pairs (metrics_collectors ) do
361
+ c .collector :remove ({name = self .name })
362
+ c .task_value [self .name ] = nil
363
+ end
364
+ end
284
365
task_list [self .name ] = nil
285
366
end ,
286
367
400
481
--
401
482
-- @section Functions
402
483
484
+ --- Configure expirationd.
485
+ --
486
+ -- How to set up a configuration option:
487
+ --
488
+ -- ```
489
+ -- expirationd.cfg({metrics = true})
490
+ -- ```
491
+ --
492
+ -- How to get an option value:
493
+ --
494
+ -- ```
495
+ -- print(expirationd.cfg.metrics)
496
+ -- true
497
+ -- ```
498
+ --
499
+ -- @table options
500
+ --
501
+ -- @bool[opt] options.metrics
502
+ -- Enable or disable stats collection by [metrics][1]. metrics >= 0.11.0
503
+ -- is required. It is enabled by default.
504
+ --
505
+ -- If enabled it creates four counter collectors, see @{task.statistics}:
506
+ --
507
+ -- 1. `expirationd_checked_count`
508
+ --
509
+ -- 2. `expirationd_expired_count`
510
+ --
511
+ -- 3. `expirationd_restarts`
512
+ --
513
+ -- 4. `expirationd_working_time`
514
+ --
515
+ -- Labeled with `name = task_name`.
516
+ --
517
+ -- [1]: https://github.com/tarantool/metrics/
518
+ --
519
+ -- @return None
520
+ --
521
+ -- @function expirationd.cfg
522
+ local function expirationd_cfg (self , options )
523
+ checks (' table' , {
524
+ metrics = ' ?boolean' ,
525
+ })
526
+
527
+ if options .metrics == nil then
528
+ return
529
+ end
530
+
531
+ if cfg .metrics ~= options .metrics then
532
+ if options .metrics == true then
533
+ metrics_enable ()
534
+ else
535
+ metrics_disable ()
536
+ end
537
+ rawset (cfg , ' metrics' , options .metrics )
538
+ end
539
+ end
540
+
403
541
--- Run a scheduled task to check and process (expire) tuples in a given space.
404
542
--
405
543
-- How expirationd works in general:
@@ -949,6 +1087,12 @@ local function show_task_list_obsolete(...)
949
1087
end
950
1088
951
1089
return {
1090
+ cfg = setmetatable ({}, {
1091
+ __index = cfg ,
1092
+ __newindex = function () error (" Use expirationd.cfg{} instead" , 2 ) end ,
1093
+ __call = expirationd_cfg ,
1094
+ __serialize = function () return cfg end ,
1095
+ }),
952
1096
start = expirationd_run_task ,
953
1097
stats = expirationd_task_stats ,
954
1098
update = expirationd_update ,
0 commit comments