@@ -66,23 +66,6 @@ static const INTEGER_CONSTANT kIntegerConstants[] = {
6666// Class to set zero overhead breakpoints.
6767static BytecodeBreakpoint g_bytecode_breakpoint;
6868
69- // Condition and dynamic logging rate limits are defined as the maximum
70- // amount of time in nanoseconds to spend on particular processing per
71- // second. These rate are enforced as following:
72- // 1. If a single breakpoint contributes to half the maximum rate, that
73- // breakpoint will be deactivated.
74- // 2. If all breakpoints combined hit the maximum rate, any breakpoint to
75- // exceed the limit gets disabled.
76- //
77- // The first rule ensures that in vast majority of scenarios expensive
78- // breakpoints will get deactivated. The second rule guarantees that in edge
79- // case scenarios the total amount of time spent in condition evaluation will
80- // not exceed the alotted limit.
81- //
82- // All limits ignore the number of CPUs since Python is inherently single
83- // threaded.
84- static std::unique_ptr<LeakyBucket> g_global_condition_quota_;
85-
8669// Initializes C++ flags and logging.
8770//
8871// This function should be called exactly once during debugger bootstrap. It
@@ -376,6 +359,31 @@ static PyObject* CallImmutable(PyObject* self, PyObject* py_args) {
376359 return PyEval_EvalCode (code, frame->f_globals , frame->f_locals );
377360}
378361
362+ // Applies the dynamic logs quota, which is limited by both total messages and
363+ // total bytes. This should be called before doing the actual logging call.
364+ //
365+ // Args:
366+ // num_bytes: number of bytes in the message to log.
367+ // Returns:
368+ // True if there is quota available, False otherwise.
369+ static PyObject* ApplyDynamicLogsQuota (PyObject* self, PyObject* py_args) {
370+ LazyInitializeRateLimit ();
371+ int num_bytes = -1 ;
372+ if (!PyArg_ParseTuple (py_args, " i" , &num_bytes) || num_bytes < 1 ) {
373+ Py_RETURN_FALSE;
374+ }
375+
376+ LeakyBucket* global_dynamic_log_limiter = GetGlobalDynamicLogQuota ();
377+ LeakyBucket* global_dynamic_log_bytes_limiter =
378+ GetGlobalDynamicLogBytesQuota ();
379+
380+ if (global_dynamic_log_limiter->RequestTokens (1 ) &&
381+ global_dynamic_log_bytes_limiter->RequestTokens (num_bytes)) {
382+ Py_RETURN_TRUE;
383+ } else {
384+ Py_RETURN_FALSE;
385+ }
386+ }
379387
380388static PyMethodDef g_module_functions[] = {
381389 {
@@ -427,6 +435,12 @@ static PyMethodDef g_module_functions[] = {
427435 METH_VARARGS,
428436 " Invokes a Python callable object with immutability tracer."
429437 },
438+ {
439+ " ApplyDynamicLogsQuota" ,
440+ ApplyDynamicLogsQuota,
441+ METH_VARARGS,
442+ " Applies the dynamic log quota"
443+ },
430444 { nullptr , nullptr , 0 , nullptr } // sentinel
431445};
432446
0 commit comments