Logging and Tracing#

Traces#

Pluggable sinks for the structured events that Cvxium solvers emit.

A Trace receives the events a solver reports while it runs: the equality solver’s feasible-point computation, the barrier method’s Phase I outcome, centering steps, Newton steps, dual evaluations and line searches, the two-block saddle solver’s Newton steps, and the iterations of the homogeneous self-dual and primal-dual loops. Each event is one on_* method, a no-op in the base class, so a subclass overrides only the events it cares about. Solvers read the trace from OptimizationSettings.trace.

Three implementations are provided:

  • LoggingTrace, the default, writes each event as a log record on the cvxium.optimization, cvxium.linear_programs, cvxium.hsd_solver or cvxium.pd_solver logger, with structured cvx_ fields that IterationHandler collects.

  • ListTrace collects every event as a dict in memory, with no logging configuration.

  • DataFrameTrace adds conversion of those dicts to a pandas DataFrame.

Two want_* methods let a trace tell the solver whether to compute diagnostics that cost extra work and that only a consumer of the corresponding event needs.

class cvxium.diagnostics.trace.Trace[source]#

Bases: object

Base class for solver event traces.

Each on_* method reports one solver event and does nothing by default; subclass and override the events to collect. The two want_* methods return False by default, so the solver skips the extra work behind on_btls and the rt_new field of on_pd_iteration.

LoggingTrace, the default value of OptimizationSettings.trace, writes each event as a structured record on the appropriate cvxium.* logger, following the logging contract described in Cvxium’s USAGE.md (section 7).

on_feasible_initial_guess()[source]#

Report that the initial guess already satisfies the equality constraints.

Emitted by EqualitySolver when the supplied x0 satisfies A x = b to within 1e-10 in every component, so it is returned unchanged.

on_svd_done(elapsed_ms)[source]#

Report the time taken to compute an equality-feasible point.

Emitted by EqualitySolver after it computes a point satisfying A x = b. For a dense A the time covers the SVD of A and the projection that uses it; for a sparse A, which has no SVD path, the event is reused for the saddle-point projection.

Parameters:

elapsed_ms (float) – Wall-clock time of the computation, in milliseconds: the SVD of A and the projection that follows it, or, for a sparse A, the saddle-point projection, which forms no SVD.

on_phase1_feasible(solver)[source]#

Report that Phase I returned a point already feasible for this solver.

Emitted by a barrier solver running in feasibility mode when the point from its nested Phase I solver already passes its own feasibility test, so its interior-point loop is skipped.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_ipm_start(solver)[source]#

Report that the outer barrier loop is about to begin.

Emitted after Phase I, by the barrier method and by StationaritySolver.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_centering_start(outer_nit, t)[source]#

Report that a centering step is starting.

Emitted by the barrier method and by StationaritySolver.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • t (float) – Barrier parameter for this centering step.

on_centering_done(outer_nit, elapsed_ms, duality_gap)[source]#

Report that a centering step has finished.

Emitted by the barrier method and by StationaritySolver, which report different gaps (see duality_gap). The barrier method’s per-step gap is not monotone, and it inflates when t is large even while the best-bounds certificate holds; the solve’s convergence test and its recorded duality gaps use that certificate instead.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the centering step, in milliseconds.

  • duality_gap (float) – Duality gap at the centered iterate. The barrier method reports the per-step gap objective - dual at the returned iterate; StationaritySolver reports the surrogate gap n_b / t, where n_b counts its barrier terms (0.0 when there are none).

on_dual_eval_start(outer_nit)[source]#

Report that the per-centering Lagrange dual evaluation is starting.

The barrier method evaluates the dual once per centering step, itself a small Newton minimization of the Lagrangian (see on_dual_newton_step); this event and on_dual_eval_done bracket it, so its cost can be compared with the Newton and line-search timings.

Parameters:

outer_nit (int) – Outer (centering) iteration, 1-indexed.

on_dual_eval_done(outer_nit, elapsed_ms)[source]#

Report that the per-centering Lagrange dual evaluation has finished.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the dual evaluation, in milliseconds.

on_early_stop(outer_nit)[source]#

Report that a solve is stopping before its outer loop runs to completion.

Emitted in three situations: a barrier Phase I solve finds a strictly feasible point; a primal-dual solver minimizing an objective with a feasibility threshold sees the value cross it; or a primal-dual solver’s stall detector stops and returns the best iterate seen. Distinct from on_converged.

Parameters:

outer_nit (int) – Iteration at which the solve stopped, 1-indexed: the outer (centering) iteration of a barrier solve, or the iteration count of a primal-dual solve.

on_converged(outer_nit, duality_gap)[source]#

Report that the outer loop met its gap tolerance and is stopping.

In the barrier method (optimization only, not Phase I), emitted when the best-bounds certificate, the best primal objective minus the best dual value seen so far, is within outer.tolerance before the planned number of centering steps is exhausted. Stopping there keeps t out of the ill-conditioned large-t regime. StationaritySolver emits it when its surrogate gap meets its gap tolerance.

Parameters:
  • outer_nit (int) – Outer iteration at which the tolerance was met, 1-indexed.

  • duality_gap (float) – The gap that met the tolerance: the best-bounds certificate in the barrier method, the surrogate gap in StationaritySolver.

on_ipm_done(solver, elapsed_ms)[source]#

Report that the outer barrier loop has finished.

Emitted by the barrier method and by StationaritySolver.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • elapsed_ms (float) – Wall-clock time of the outer loop, in milliseconds.

on_newton_step(outer_nit, inner_nit, elapsed_ms, suboptimality, lambda_norm, quadratic_convergence_threshold)[source]#

Report a completed Newton step of a barrier centering step.

Emitted once per inner iteration, after the Newton step is computed and before the line search.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • elapsed_ms (float) – Wall-clock time to compute the Newton step, in milliseconds.

  • suboptimality (float) – Estimated suboptimality λ^2 / 2 of the iterate for the centering problem, where λ is the Newton decrement.

  • lambda_norm (float) – The Newton decrement λ at the start of the step.

  • quadratic_convergence_threshold (bool) – True only on the first inner step of the centering step whose Newton decrement satisfies λ ≤ η, where η = (1 - 2α) / 4 and α is the Armijo parameter: the step at which Newton’s method enters its quadratically convergent phase.

on_saddle_newton_step(outer_nit, inner_nit, elapsed_ms, residual_norm, lambda_norm)[source]#

Report a completed Newton step of a two-block saddle centering step.

StationaritySolver centers a coupled two-block saddle problem with an infeasible-start Newton step driven by the residual norm: a cap that keeps the iterate in the domain, then an Armijo backtrack on ‖r‖. It computes no Newton decrement, so this is a separate event from on_newton_step rather than a reuse with an unused field. Emitted once per accepted step.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Accepted inner step within the centering, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • residual_norm (float) – ‖r(x, y, t, λ)‖_2, the norm of the residual the step drives toward zero, measured at the start of the step.

  • lambda_norm (float) – ‖λ‖_2, the norm of the equality multiplier after the step; 0.0 when the problem has no x_equality.

on_dual_newton_step(inner_nit, elapsed_ms, gradient_norm)[source]#

Report a completed Newton step of a Lagrange dual minimization.

Evaluating the dual means minimizing the Lagrangian over x, which the barrier method does with a few damped Newton steps. During the per-centering dual evaluation these steps fall between on_dual_eval_start and on_dual_eval_done; other dual evaluations emit them too, as does StationaritySolver when it minimizes a block Lagrangian to certify a bound on the saddle value.

Parameters:
  • inner_nit (int) – Step within the dual minimization, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • gradient_norm (float) – ‖∇_x L‖, the norm of the Lagrangian gradient at the start of the step, the quantity the minimization drives toward zero.

on_btls(outer_nit, inner_nit, btls_s, improvement, expected_improvement)[source]#

Report a completed backtracking line search.

Called by the barrier method after each line search, but only when want_btls_details returns True, since filling in improvement costs extra barrier-objective evaluations.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • btls_s (float) – The accepted step size s.

  • improvement (float) – Actual decrease of the barrier objective, f_t(x) - f_t(x + s Δx).

  • expected_improvement (float) – Reference decrease α β λ^2 / (1 + λ), where λ is the Newton decrement and α and β are the Armijo parameters.

on_hsd_start(solver)[source]#

Report that the homogeneous self-dual loop is about to begin.

Emitted by HsdSolver before its long-step path-following loop.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_hsd_iteration(nit, mu, rel_pres, rel_dres, tau, kappa, elapsed_ms)[source]#

Report a completed homogeneous self-dual iteration.

Emitted by HsdSolver after each iteration’s Newton step. The residual metrics are those measured at the top of the iteration, before the step, while tau and kappa are post-step. An iteration that converges, or whose step fails at the cone boundary, ends the loop without emitting this event.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • mu (float) – Complementarity gap μ at the top of the iteration, before its Newton step.

  • rel_pres (float) – Relative primal residual ‖r_p‖ / (1 + ‖b‖) at the top of the iteration.

  • rel_dres (float) – Relative dual residual ‖r_d‖ / (1 + ‖c‖) at the top of the iteration.

  • tau (float) – Homogenizing variable τ after the step.

  • kappa (float) – Homogenizing variable κ after the step.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

on_hsd_done(solver, nits, status, elapsed_ms)[source]#

Report that the homogeneous self-dual loop has terminated.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations completed, each with one Newton step.

  • status (int) – Integer status code: 0 converged to the outer tolerance, 1 reached only the soft tolerance, 2 did not converge.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

on_pd_start(solver, num_vars=None, num_ineq=None, tol=None)[source]#

Report that a primal-dual loop is about to begin.

PrimalDualSolver’s inequality-only (Mehrotra predictor-corrector) path and both paths of PrimalDualStationaritySolver supply the problem dimensions and tolerance; PrimalDualSolver’s equality path does not.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • num_vars (int | None) – Number of decision variables, when supplied.

  • num_ineq (int | None) – Number of inequality constraints, when supplied.

  • tol (float | None) – Outer convergence tolerance, when supplied.

on_pd_iteration(nit, eta, dual_norm, pri_norm, residual_norm, t, step, elapsed_ms, sigma=None, rho=None, damping=0.0, cent_norm=None, rt_norm=None, dir_ms=None, rt_new=None)[source]#

Report a completed primal-dual iteration.

Emitted after each accepted step, with the residual metrics measured at the top of the iteration. An iteration that converges or stops breaks before taking a step and emits nothing, so the number of these events equals the number of accepted steps.

Which optional fields are populated depends on the path:

  • PrimalDualSolver’s inequality-only (Mehrotra predictor-corrector) path supplies all of them, rt_new only when want_pd_step_details returns True.

  • PrimalDualStationaritySolver supplies sigma only.

  • PrimalDualSolver’s equality path supplies none, leaving each at its default.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • eta (float) – Surrogate duality gap η = -f^T λ at the top of the iteration.

  • dual_norm (float) – ‖r_dual‖_2, the dual (stationarity) residual norm at the top of the iteration.

  • pri_norm (float) – ‖A x - b‖_2, the equality residual norm; 0.0 when the problem has no equality constraints.

  • residual_norm (float) – The proxy sqrt(‖r_dual‖^2 + ‖A x - b‖^2 + η^2), kept for the result history.

  • t (float) – Surrogate barrier parameter μ m / η, where m counts the inequality constraints and μ is the barrier multiplier. The two-block solver omits μ and reports 0.0 when η ≤ 0.

  • step (float) – Step length actually taken.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

  • sigma (float | None) – Mehrotra centering parameter (in the two-block solver, the mean of its two blocks’ values).

  • rho (float | None) – Ratio of the actual to the predicted residual reduction; None when the step was undamped and the ratio test was skipped.

  • damping (float) – Levenberg damping used for the accepted step.

  • cent_norm (float | None) – ‖r_cent‖_2, the centrality residual norm.

  • rt_norm (float | None) – ‖[r_dual; r_cent]‖_2, the KKT residual at barrier parameter t, before the step.

  • dir_ms (float | None) – Time to compute the search direction, in milliseconds.

  • rt_new (float | None) – The same KKT residual after the step, at the same t; computed only when want_pd_step_details returns True, otherwise None.

want_pd_step_details()[source]#

Return whether primal-dual solvers should compute the post-step KKT residual.

Computing rt_new for on_pd_iteration costs one extra residual evaluation per iteration, so PrimalDualSolver skips it unless this returns True. LoggingTrace returns True exactly when the cvxium.pd_solver logger is enabled at DEBUG; collectors that want the field, such as ListTrace, return True.

Returns:

want – False here.

Return type:

bool

on_pd_damping_engaged(nit, damping, retries)[source]#

Report that Levenberg damping had to grow to find a feasible step.

Emitted by PrimalDualSolver’s inequality-only path, only on iterations where the damping had to be grown to recover a feasible step: the diagnostic signature of a nearly singular modified Hessian.

Parameters:
  • nit (int) – Iteration, 0-indexed, as in on_pd_iteration.

  • damping (float) – Levenberg damping of the accepted step.

  • retries (int) – Number of times the damping was grown before a feasible step was found.

on_pd_done(solver, nits, status, elapsed_ms, reason='', duality_gap=None)[source]#

Report that a primal-dual loop has terminated.

The per-iteration gap is the cheap surrogate η; the true dual is evaluated only once, at termination, and only on the path that reports duality_gap.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations started, including a final one that stopped without taking a step.

  • status (int) – Integer status code. 0 means converged; the meaning of 1 and 2 depends on the solver. For PrimalDualSolver, 1 is a stall or the iteration cap, and 2 a feasibility stop or certified infeasibility. For PrimalDualStationaritySolver, 1 is the iteration cap or another non-converged break, and 2 acceptance at the soft tolerance.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

  • reason (str) – Human-readable termination cause; empty when the solver supplies none (as on PrimalDualSolver’s equality path).

  • duality_gap (float | None) – True duality gap objective - dual, evaluated once at termination. Supplied only by PrimalDualSolver’s inequality-only path on a normal exit; None otherwise.

want_btls_details()[source]#

Return whether barrier solvers should call on_btls.

Populating improvement costs two extra evaluate_barrier_objective calls per inner step, so the solver skips them, and the on_btls call, when this returns False. LoggingTrace returns True exactly when the cvxium.optimization logger is enabled at DEBUG.

Returns:

want – False here.

Return type:

bool

class cvxium.diagnostics.trace.LoggingTrace[source]#

Bases: Trace

Default trace, writing each event as a structured cvxium.* log record.

Each record carries a human-readable message and, in extra, structured fields named with a cvx_ prefix (always including cvx_event), the schema that IterationHandler and the logging contract in USAGE.md rely on. The per-step events of the barrier and saddle solvers (on_newton_step, on_saddle_newton_step, on_dual_newton_step and on_btls) log at DEBUG on cvxium.optimization; every other event logs at INFO. The want_* methods return True exactly when the logger that would show the extra detail is enabled at DEBUG.

on_feasible_initial_guess()[source]#

Log that the initial guess already satisfies the equality constraints.

Writes an INFO record on cvxium.linear_programs.

on_svd_done(elapsed_ms)[source]#

Log the time taken to compute an equality-feasible point.

Writes an INFO record on cvxium.linear_programs.

Parameters:

elapsed_ms (float) – Wall-clock time of the computation, in milliseconds: the SVD of A and the projection that follows it, or, for a sparse A, the saddle-point projection, which forms no SVD.

on_phase1_feasible(solver)[source]#

Log that Phase I returned a point already feasible for this solver.

Writes an INFO record on cvxium.optimization.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_ipm_start(solver)[source]#

Log that the outer barrier loop is about to begin.

Writes an INFO record on cvxium.optimization.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_centering_start(outer_nit, t)[source]#

Log that a centering step is starting.

Writes an INFO record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • t (float) – Barrier parameter for this centering step.

on_centering_done(outer_nit, elapsed_ms, duality_gap)[source]#

Log that a centering step has finished, with its duality gap.

Writes an INFO record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the centering step, in milliseconds.

  • duality_gap (float) – Duality gap at the centered iterate. The barrier method reports the per-step gap objective - dual at the returned iterate; StationaritySolver reports the surrogate gap n_b / t, where n_b counts its barrier terms (0.0 when there are none).

on_dual_eval_start(outer_nit)[source]#

Log that the per-centering Lagrange dual evaluation is starting.

Writes an INFO record on cvxium.optimization.

Parameters:

outer_nit (int) – Outer (centering) iteration, 1-indexed.

on_dual_eval_done(outer_nit, elapsed_ms)[source]#

Log that the per-centering Lagrange dual evaluation has finished.

Writes an INFO record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the dual evaluation, in milliseconds.

on_early_stop(outer_nit)[source]#

Log that a solve is stopping before its outer loop runs to completion.

Writes an INFO record on cvxium.optimization, whichever solver emitted the event.

Parameters:

outer_nit (int) – Iteration at which the solve stopped, 1-indexed: the outer (centering) iteration of a barrier solve, or the iteration count of a primal-dual solve.

on_converged(outer_nit, duality_gap)[source]#

Log that the outer loop met its gap tolerance and is stopping.

Writes an INFO record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer iteration at which the tolerance was met, 1-indexed.

  • duality_gap (float) – The gap that met the tolerance: the best-bounds certificate in the barrier method, the surrogate gap in StationaritySolver.

on_ipm_done(solver, elapsed_ms)[source]#

Log that the outer barrier loop has finished.

Writes an INFO record on cvxium.optimization.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • elapsed_ms (float) – Wall-clock time of the outer loop, in milliseconds.

on_newton_step(outer_nit, inner_nit, elapsed_ms, suboptimality, lambda_norm, quadratic_convergence_threshold)[source]#

Log a completed Newton step of a barrier centering step.

Writes a DEBUG record on cvxium.optimization. The message shows the decrement and flags the quadratic-convergence step; lambda_norm and the flag are not among the structured fields.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • elapsed_ms (float) – Wall-clock time to compute the Newton step, in milliseconds.

  • suboptimality (float) – Estimated suboptimality λ^2 / 2 of the iterate for the centering problem, where λ is the Newton decrement.

  • lambda_norm (float) – The Newton decrement λ at the start of the step.

  • quadratic_convergence_threshold (bool) – True only on the first inner step of the centering step whose Newton decrement satisfies λ ≤ η, where η = (1 - 2α) / 4 and α is the Armijo parameter: the step at which Newton’s method enters its quadratically convergent phase.

on_saddle_newton_step(outer_nit, inner_nit, elapsed_ms, residual_norm, lambda_norm)[source]#

Log a completed Newton step of a two-block saddle centering step.

Writes a DEBUG record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Accepted inner step within the centering, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • residual_norm (float) – ‖r(x, y, t, λ)‖_2, the norm of the residual the step drives toward zero, measured at the start of the step.

  • lambda_norm (float) – ‖λ‖_2, the norm of the equality multiplier after the step; 0.0 when the problem has no x_equality.

on_dual_newton_step(inner_nit, elapsed_ms, gradient_norm)[source]#

Log a completed Newton step of a Lagrange dual minimization.

Writes a DEBUG record on cvxium.optimization.

Parameters:
  • inner_nit (int) – Step within the dual minimization, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • gradient_norm (float) – ‖∇_x L‖, the norm of the Lagrangian gradient at the start of the step, the quantity the minimization drives toward zero.

on_btls(outer_nit, inner_nit, btls_s, improvement, expected_improvement)[source]#

Log a completed backtracking line search.

Writes a DEBUG record on cvxium.optimization.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • btls_s (float) – The accepted step size s.

  • improvement (float) – Actual decrease of the barrier objective, f_t(x) - f_t(x + s Δx).

  • expected_improvement (float) – Reference decrease α β λ^2 / (1 + λ), where λ is the Newton decrement and α and β are the Armijo parameters.

on_hsd_start(solver)[source]#

Log that the homogeneous self-dual loop is about to begin.

Writes an INFO record on cvxium.hsd_solver.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_hsd_iteration(nit, mu, rel_pres, rel_dres, tau, kappa, elapsed_ms)[source]#

Log a completed homogeneous self-dual iteration.

Writes an INFO record on cvxium.hsd_solver. tau and kappa appear only in the structured fields, not the message.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • mu (float) – Complementarity gap μ at the top of the iteration, before its Newton step.

  • rel_pres (float) – Relative primal residual ‖r_p‖ / (1 + ‖b‖) at the top of the iteration.

  • rel_dres (float) – Relative dual residual ‖r_d‖ / (1 + ‖c‖) at the top of the iteration.

  • tau (float) – Homogenizing variable τ after the step.

  • kappa (float) – Homogenizing variable κ after the step.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

on_hsd_done(solver, nits, status, elapsed_ms)[source]#

Log that the homogeneous self-dual loop has terminated.

Writes an INFO record on cvxium.hsd_solver.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations completed, each with one Newton step.

  • status (int) – Integer status code: 0 converged to the outer tolerance, 1 reached only the soft tolerance, 2 did not converge.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

on_pd_start(solver, num_vars=None, num_ineq=None, tol=None)[source]#

Log that a primal-dual loop is about to begin.

Writes an INFO record on cvxium.pd_solver; the message shows the dimensions and tolerance when they are supplied.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • num_vars (int | None) – Number of decision variables, when supplied.

  • num_ineq (int | None) – Number of inequality constraints, when supplied.

  • tol (float | None) – Outer convergence tolerance, when supplied.

on_pd_iteration(nit, eta, dual_norm, pri_norm, residual_norm, t, step, elapsed_ms, sigma=None, rho=None, damping=0.0, cent_norm=None, rt_norm=None, dir_ms=None, rt_new=None)[source]#

Log a completed primal-dual iteration in one of three formats.

Every format writes INFO records on cvxium.pd_solver, and the first record of each carries all the arguments as structured fields. The format is chosen by what the caller supplied and by the logger’s level:

  • No rt_norm or cent_norm: one compact line (_log_pd_iter_equality). This covers PrimalDualSolver’s equality path and also PrimalDualStationaritySolver, which supplies sigma but no KKT residual breakdown.

  • rt_norm supplied, logger not enabled at DEBUG: one summary line (_log_pd_iter_mpc_compact).

  • rt_norm supplied, logger enabled at DEBUG: a header line and one line per quantity (_log_pd_iter_mpc_verbose).

The step length is printed in fixed point when it is at least 1e-3, and in scientific notation otherwise.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • eta (float) – Surrogate duality gap η = -f^T λ at the top of the iteration.

  • dual_norm (float) – ‖r_dual‖_2, the dual (stationarity) residual norm at the top of the iteration.

  • pri_norm (float) – ‖A x - b‖_2, the equality residual norm; 0.0 when the problem has no equality constraints.

  • residual_norm (float) – The proxy sqrt(‖r_dual‖^2 + ‖A x - b‖^2 + η^2), kept for the result history.

  • t (float) – Surrogate barrier parameter μ m / η, where m counts the inequality constraints and μ is the barrier multiplier. The two-block solver omits μ and reports 0.0 when η ≤ 0.

  • step (float) – Step length actually taken.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

  • sigma (float | None) – Mehrotra centering parameter (in the two-block solver, the mean of its two blocks’ values).

  • rho (float | None) – Ratio of the actual to the predicted residual reduction; None when the step was undamped and the ratio test was skipped.

  • damping (float) – Levenberg damping used for the accepted step.

  • cent_norm (float | None) – ‖r_cent‖_2, the centrality residual norm.

  • rt_norm (float | None) – ‖[r_dual; r_cent]‖_2, the KKT residual at barrier parameter t, before the step.

  • dir_ms (float | None) – Time to compute the search direction, in milliseconds.

  • rt_new (float | None) – The same KKT residual after the step, at the same t; computed only when want_pd_step_details returns True, otherwise None.

want_pd_step_details()[source]#

Return whether the post-step KKT residual would be logged.

Returns:

want – True exactly when the cvxium.pd_solver logger is enabled at DEBUG, the level at which on_pd_iteration shows rt_new.

Return type:

bool

on_pd_damping_engaged(nit, damping, retries)[source]#

Log that Levenberg damping had to grow to find a feasible step.

Writes an INFO record on cvxium.pd_solver.

Parameters:
  • nit (int) – Iteration, 0-indexed, as in on_pd_iteration.

  • damping (float) – Levenberg damping of the accepted step.

  • retries (int) – Number of times the damping was grown before a feasible step was found.

on_pd_done(solver, nits, status, elapsed_ms, reason='', duality_gap=None)[source]#

Log that a primal-dual loop has terminated.

Writes an INFO record on cvxium.pd_solver; the message appends the true duality gap and the reason when they are supplied.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations started, including a final one that stopped without taking a step.

  • status (int) – Integer status code. 0 means converged; the meaning of 1 and 2 depends on the solver. For PrimalDualSolver, 1 is a stall or the iteration cap, and 2 a feasibility stop or certified infeasibility. For PrimalDualStationaritySolver, 1 is the iteration cap or another non-converged break, and 2 acceptance at the soft tolerance.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

  • reason (str) – Human-readable termination cause; empty when the solver supplies none (as on PrimalDualSolver’s equality path).

  • duality_gap (float | None) – True duality gap objective - dual, evaluated once at termination. Supplied only by PrimalDualSolver’s inequality-only path on a normal exit; None otherwise.

want_btls_details()[source]#

Return whether line-search records would be logged.

Returns:

want – True exactly when the cvxium.optimization logger is enabled at DEBUG, the level at which on_btls logs.

Return type:

bool

class cvxium.diagnostics.trace.ListTrace[source]#

Bases: Trace

In-memory trace that collects each event as a dict.

Needs no logging configuration, and records every argument of every hook, a superset of the structured fields that IterationHandler extracts from LoggingTrace records. Both want_* methods return True, so the solver computes the extra diagnostics on every step: two additional evaluate_barrier_objective calls per barrier Newton step (to populate on_btls) and one additional KKT residual evaluation per primal-dual iteration (to populate rt_new). That is not free in tight loops; prefer LoggingTrace on performance-critical paths.

Each row is a dict with an event key naming the hook (its name without the on_ prefix), a wall-clock time in seconds since the epoch, and one key per argument of the hook, named as in the hook’s signature:

  • feasible_initial_guess: no further keys.

  • svd_done: elapsed_ms.

  • phase1_feasible, ipm_start, hsd_start: solver.

  • centering_start: outer_nit, t.

  • centering_done: outer_nit, elapsed_ms, duality_gap.

  • dual_eval_start, early_stop: outer_nit.

  • dual_eval_done: outer_nit, elapsed_ms.

  • converged: outer_nit, duality_gap.

  • ipm_done: solver, elapsed_ms.

  • newton_step: outer_nit, inner_nit, elapsed_ms, suboptimality, lambda_norm, quadratic_convergence_threshold.

  • saddle_newton_step: outer_nit, inner_nit, elapsed_ms, residual_norm, lambda_norm.

  • dual_newton_step: inner_nit, elapsed_ms, gradient_norm.

  • btls: outer_nit, inner_nit, btls_s, improvement, expected_improvement.

  • hsd_iteration: nit, mu, rel_pres, rel_dres, tau, kappa, elapsed_ms.

  • hsd_done: solver, nits, status, elapsed_ms.

  • pd_start: solver, num_vars, num_ineq, tol.

  • pd_iteration: nit, eta, dual_norm, pri_norm, residual_norm, t, step, elapsed_ms, sigma, rho, damping, cent_norm, rt_norm, dir_ms, rt_new.

  • pd_damping_engaged: nit, damping, retries.

  • pd_done: solver, nits, status, elapsed_ms, reason, duality_gap.

Optional arguments the solver did not supply are recorded with their defaults (usually None).

records()[source]#

Return the accumulated records as a list of dicts.

The outer list is a fresh copy, so appending to or reordering it does not affect the trace. The dicts inside are the objects the trace holds, so mutating one (for example, trace.records()[0]["event"] = "X") changes the trace’s record too. Treat them as read-only, or copy.deepcopy the result before mutating it.

Returns:

records – One dict per event, in the order the events were emitted.

Return type:

list[dict[str, Any]]

clear()[source]#

Discard every accumulated record.

want_btls_details()[source]#

Return True, so that the solver calls on_btls on every inner step.

Returns:

want – Always True.

Return type:

bool

on_feasible_initial_guess()[source]#

Record that the initial guess already satisfies A x = b.

Appends a feasible_initial_guess row with no further keys.

on_svd_done(elapsed_ms)[source]#

Record the time taken to compute an equality-feasible point.

Appends a svd_done row carrying each argument under its own name.

Parameters:

elapsed_ms (float) – Wall-clock time of the computation, in milliseconds: the SVD of A and the projection that follows it, or, for a sparse A, the saddle-point projection, which forms no SVD.

on_phase1_feasible(solver)[source]#

Record that Phase I returned a point feasible for this solver.

Appends a phase1_feasible row carrying each argument under its own name.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_ipm_start(solver)[source]#

Record that the outer barrier loop is about to begin.

Appends a ipm_start row carrying each argument under its own name.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_centering_start(outer_nit, t)[source]#

Record that a centering step is starting.

Appends a centering_start row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • t (float) – Barrier parameter for this centering step.

on_centering_done(outer_nit, elapsed_ms, duality_gap)[source]#

Record that a centering step has finished.

Appends a centering_done row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the centering step, in milliseconds.

  • duality_gap (float) – Duality gap at the centered iterate. The barrier method reports the per-step gap objective - dual at the returned iterate; StationaritySolver reports the surrogate gap n_b / t, where n_b counts its barrier terms (0.0 when there are none).

on_dual_eval_start(outer_nit)[source]#

Record that the per-centering dual evaluation is starting.

Appends a dual_eval_start row carrying each argument under its own name.

Parameters:

outer_nit (int) – Outer (centering) iteration, 1-indexed.

on_dual_eval_done(outer_nit, elapsed_ms)[source]#

Record that the per-centering dual evaluation has finished.

Appends a dual_eval_done row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the dual evaluation, in milliseconds.

on_early_stop(outer_nit)[source]#

Record that a solve is stopping before its outer loop completes.

Appends a early_stop row carrying each argument under its own name.

Parameters:

outer_nit (int) – Iteration at which the solve stopped, 1-indexed: the outer (centering) iteration of a barrier solve, or the iteration count of a primal-dual solve.

on_converged(outer_nit, duality_gap)[source]#

Record that the outer loop met its gap tolerance.

Appends a converged row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer iteration at which the tolerance was met, 1-indexed.

  • duality_gap (float) – The gap that met the tolerance: the best-bounds certificate in the barrier method, the surrogate gap in StationaritySolver.

on_ipm_done(solver, elapsed_ms)[source]#

Record that the outer barrier loop has finished.

Appends a ipm_done row carrying each argument under its own name.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • elapsed_ms (float) – Wall-clock time of the outer loop, in milliseconds.

on_newton_step(outer_nit, inner_nit, elapsed_ms, suboptimality, lambda_norm, quadratic_convergence_threshold)[source]#

Record a completed Newton step of a barrier centering step.

Appends a newton_step row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • elapsed_ms (float) – Wall-clock time to compute the Newton step, in milliseconds.

  • suboptimality (float) – Estimated suboptimality λ^2 / 2 of the iterate for the centering problem, where λ is the Newton decrement.

  • lambda_norm (float) – The Newton decrement λ at the start of the step.

  • quadratic_convergence_threshold (bool) – True only on the first inner step of the centering step whose Newton decrement satisfies λ ≤ η, where η = (1 - 2α) / 4 and α is the Armijo parameter: the step at which Newton’s method enters its quadratically convergent phase.

on_saddle_newton_step(outer_nit, inner_nit, elapsed_ms, residual_norm, lambda_norm)[source]#

Record a completed Newton step of a saddle centering step.

Appends a saddle_newton_step row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Accepted inner step within the centering, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • residual_norm (float) – ‖r(x, y, t, λ)‖_2, the norm of the residual the step drives toward zero, measured at the start of the step.

  • lambda_norm (float) – ‖λ‖_2, the norm of the equality multiplier after the step; 0.0 when the problem has no x_equality.

on_dual_newton_step(inner_nit, elapsed_ms, gradient_norm)[source]#

Record a completed Newton step of a dual minimization.

Appends a dual_newton_step row carrying each argument under its own name.

Parameters:
  • inner_nit (int) – Step within the dual minimization, 1-indexed.

  • elapsed_ms (float) – Wall-clock time of the step, including its line search, in milliseconds.

  • gradient_norm (float) – ‖∇_x L‖, the norm of the Lagrangian gradient at the start of the step, the quantity the minimization drives toward zero.

on_btls(outer_nit, inner_nit, btls_s, improvement, expected_improvement)[source]#

Record a completed backtracking line search.

Appends a btls row carrying each argument under its own name.

Parameters:
  • outer_nit (int) – Outer (centering) iteration, 1-indexed.

  • inner_nit (int) – Newton iteration within the centering step, 1-indexed.

  • btls_s (float) – The accepted step size s.

  • improvement (float) – Actual decrease of the barrier objective, f_t(x) - f_t(x + s Δx).

  • expected_improvement (float) – Reference decrease α β λ^2 / (1 + λ), where λ is the Newton decrement and α and β are the Armijo parameters.

on_hsd_start(solver)[source]#

Record that the homogeneous self-dual loop is about to begin.

Appends a hsd_start row carrying each argument under its own name.

Parameters:

solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

on_hsd_iteration(nit, mu, rel_pres, rel_dres, tau, kappa, elapsed_ms)[source]#

Record a completed homogeneous self-dual iteration.

Appends a hsd_iteration row carrying each argument under its own name.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • mu (float) – Complementarity gap μ at the top of the iteration, before its Newton step.

  • rel_pres (float) – Relative primal residual ‖r_p‖ / (1 + ‖b‖) at the top of the iteration.

  • rel_dres (float) – Relative dual residual ‖r_d‖ / (1 + ‖c‖) at the top of the iteration.

  • tau (float) – Homogenizing variable τ after the step.

  • kappa (float) – Homogenizing variable κ after the step.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

on_hsd_done(solver, nits, status, elapsed_ms)[source]#

Record that the homogeneous self-dual loop has terminated.

Appends a hsd_done row carrying each argument under its own name.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations completed, each with one Newton step.

  • status (int) – Integer status code: 0 converged to the outer tolerance, 1 reached only the soft tolerance, 2 did not converge.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

on_pd_start(solver, num_vars=None, num_ineq=None, tol=None)[source]#

Record that a primal-dual loop is about to begin.

Appends a pd_start row carrying each argument under its own name.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • num_vars (int | None) – Number of decision variables, when supplied.

  • num_ineq (int | None) – Number of inequality constraints, when supplied.

  • tol (float | None) – Outer convergence tolerance, when supplied.

on_pd_iteration(nit, eta, dual_norm, pri_norm, residual_norm, t, step, elapsed_ms, sigma=None, rho=None, damping=0.0, cent_norm=None, rt_norm=None, dir_ms=None, rt_new=None)[source]#

Record a completed primal-dual iteration.

Appends a pd_iteration row carrying each argument under its own name.

Parameters:
  • nit (int) – Iteration, 0-indexed within the loop.

  • eta (float) – Surrogate duality gap η = -f^T λ at the top of the iteration.

  • dual_norm (float) – ‖r_dual‖_2, the dual (stationarity) residual norm at the top of the iteration.

  • pri_norm (float) – ‖A x - b‖_2, the equality residual norm; 0.0 when the problem has no equality constraints.

  • residual_norm (float) – The proxy sqrt(‖r_dual‖^2 + ‖A x - b‖^2 + η^2), kept for the result history.

  • t (float) – Surrogate barrier parameter μ m / η, where m counts the inequality constraints and μ is the barrier multiplier. The two-block solver omits μ and reports 0.0 when η ≤ 0.

  • step (float) – Step length actually taken.

  • elapsed_ms (float) – Wall-clock time of the iteration, in milliseconds.

  • sigma (float | None) – Mehrotra centering parameter (in the two-block solver, the mean of its two blocks’ values).

  • rho (float | None) – Ratio of the actual to the predicted residual reduction; None when the step was undamped and the ratio test was skipped.

  • damping (float) – Levenberg damping used for the accepted step.

  • cent_norm (float | None) – ‖r_cent‖_2, the centrality residual norm.

  • rt_norm (float | None) – ‖[r_dual; r_cent]‖_2, the KKT residual at barrier parameter t, before the step.

  • dir_ms (float | None) – Time to compute the search direction, in milliseconds.

  • rt_new (float | None) – The same KKT residual after the step, at the same t; computed only when want_pd_step_details returns True, otherwise None.

want_pd_step_details()[source]#

Return True, so that primal-dual solvers compute the post-step residual.

Returns:

want – Always True.

Return type:

bool

on_pd_damping_engaged(nit, damping, retries)[source]#

Record that Levenberg damping had to grow.

Appends a pd_damping_engaged row carrying each argument under its own name.

Parameters:
  • nit (int) – Iteration, 0-indexed, as in on_pd_iteration.

  • damping (float) – Levenberg damping of the accepted step.

  • retries (int) – Number of times the damping was grown before a feasible step was found.

on_pd_done(solver, nits, status, elapsed_ms, reason='', duality_gap=None)[source]#

Record that a primal-dual loop has terminated.

Appends a pd_done row carrying each argument under its own name.

Parameters:
  • solver (str) – Human-readable solver name: the label configured in the solver’s settings, or by default its class name.

  • nits (int) – Number of iterations started, including a final one that stopped without taking a step.

  • status (int) – Integer status code. 0 means converged; the meaning of 1 and 2 depends on the solver. For PrimalDualSolver, 1 is a stall or the iteration cap, and 2 a feasibility stop or certified infeasibility. For PrimalDualStationaritySolver, 1 is the iteration cap or another non-converged break, and 2 acceptance at the soft tolerance.

  • elapsed_ms (float) – Wall-clock time of the whole loop, in milliseconds.

  • reason (str) – Human-readable termination cause; empty when the solver supplies none (as on PrimalDualSolver’s equality path).

  • duality_gap (float | None) – True duality gap objective - dual, evaluated once at termination. Supplied only by PrimalDualSolver’s inequality-only path on a normal exit; None otherwise.

class cvxium.diagnostics.trace.DataFrameTrace[source]#

Bases: ListTrace

List trace that converts its records to a pandas DataFrame.

Adds to_dataframe, which gives one row per event with sparse columns (NaN where an event does not carry a field), like IterationHandler.to_dataframe. pandas is needed only when to_dataframe is called, not at construction.

to_dataframe()[source]#

Convert the accumulated records to a pandas DataFrame.

Requires pandas, which Cvxium does not otherwise depend on; it is imported only here.

Returns:

df – One row per recorded event. Columns are the union of the keys across records: time and event always, plus the event fields listed in ListTrace, such as outer_nit, inner_nit, elapsed_ms, suboptimality, t, btls_s and solver. A column with no data for a given event holds NaN in that row.

Return type:

pd.DataFrame

Raises:

ImportError – When pandas is not installed.

Logging Handlers#

Logging handlers and log configuration for Cvxium solvers.

Cvxium solvers narrate their progress through the standard logging module, attaching structured fields (named with a cvx_ prefix) to each record. This module provides two ways to consume that output. IterationHandler collects the structured fields into a list of dicts, or a pandas DataFrame, for analysis after a solve. enable_logging routes one or more logger namespaces to a single file or stderr handler, replacing the usual handler boilerplate and making repeated calls idempotent.

class cvxium.diagnostics.handlers.IterationHandler(level=0)[source]#

Bases: Handler

Logging handler that accumulates per-iteration solver events.

Captures the structured data that Cvxium solvers attach to their log records into a list of dicts, one per record. Each dict holds the record’s creation time and message, plus every recognized cvx_ field present on the record, keyed without the prefix: the event type, the solver, iteration counters, timing, and the numerical diagnostics of that event. Call to_dataframe for a pandas DataFrame (requires pandas), or records for the raw list of dicts.

Parameters:

level (int) – Threshold passed to logging.Handler; records below it are ignored.

Examples

Attach before solving, then inspect afterwards:

import logging
from cvxium import IterationHandler

handler = IterationHandler()
logging.getLogger("cvxium").addHandler(handler)
logging.getLogger("cvxium").setLevel(logging.DEBUG)

solver.solve()

df = handler.to_dataframe()
# df has columns: time, message, event, outer_nit, inner_nit, elapsed_ms, ...
emit(record)[source]#

Store one log record as a dict.

The dict holds the record’s creation time (time) and formatted message (message), plus each field of _CVX_FIELDS that the record carries with a value other than None, keyed without its cvx_ prefix. Fields not listed in _CVX_FIELDS are dropped.

Parameters:

record (logging.LogRecord) – The record to store.

records()[source]#

Return the accumulated records as a list of dicts.

Returns:

records – A shallow copy of the accumulated list, one dict per record, in arrival order. Appending to or removing from it does not affect the handler.

Return type:

list[dict[str, Any]]

clear()[source]#

Discard every accumulated record.

to_dataframe()[source]#

Convert the accumulated records to a pandas DataFrame.

Requires pandas, which Cvxium does not otherwise depend on; it is imported only here.

Returns:

df – One row per log record. Columns are the union of the keys across records: time and message always, plus fields such as event, solver, outer_nit, inner_nit, elapsed_ms, suboptimality, t, btls_s, improvement, and expected_improvement. A column with no data for a given event type holds NaN in that row.

Return type:

pd.DataFrame

Raises:

ImportError – When pandas is not installed.

cvxium.diagnostics.handlers.enable_logging(path=None, level=20, namespaces=('cvxium',), mode='w')[source]#

Send one or more logger namespaces to a single handler.

Replaces a dozen lines of handler boilerplate. The part worth centralizing is not the file handler but setting propagate to False and resetting the handlers: the first stops records from also reaching the root logger (which would duplicate every line in a notebook), and the second makes calling this twice idempotent rather than cumulative.

When more than one namespace is passed, sharing one handler across them is the point. They are separate logger trees, so the only thing putting their records in order is that they arrive at the same place: the log is then chronological, and a solver’s iterations sit underneath the line naming the problem being solved.

Parameters:
  • path (str | os.PathLike[str] | None) – Log file; ~ is expanded. None logs to stderr instead, which suits a terminal but not a notebook.

  • level (int) – Threshold for both the handler and each namespace. logging.INFO gives the narration; logging.DEBUG adds per-iteration solver detail, which runs to thousands of lines on a large problem. Set unconditionally on every call, unlike the NOTSET-guarded default in __init__.py. That guard exists so a level set before import survives it; here the caller is asking for exactly this level, so a level from an earlier call does not survive a later one that omits level.

  • namespaces (Sequence[str]) – Logger names to attach to. Defaults to Cvxium alone; a library built on Cvxium passes its own name alongside the ones it depends on. Repeated names are dropped, keeping the first occurrence. Must not be a bare str, which satisfies Sequence[str] but would iterate character by character; the function raises TypeError for one.

  • mode (str) – File mode. "w" truncates on each call, usually what is wanted when the question is what happened this time; "a" appends. Must be left at "w" when path is None, since stderr has no file mode; any other value raises ValueError.

Returns:

handler – The attached handler, a logging.FileHandler or logging.StreamHandler, for a caller that wants to remove it again.

Return type:

logging.Handler

Raises:
  • TypeError – When namespaces is a bare str rather than a sequence of names.

  • ValueError – When mode is not "w" while path is None.

  • OSError – Propagated from logging.FileHandler when path cannot be opened. It is raised before any logger is touched, so the previous configuration stays intact.

Notes

Each call proceeds in three steps:

  1. Build the new handler, before tearing anything down, so that a bad path leaves the previous configuration in place.

  2. Detach (see _detach) each namespace that the previous call configured and this call omits. Its handler is shared with namespaces that are in this call and is about to be closed, so leaving it attached would send the namespace’s next record to a closed handler.

  3. For each namespace in this call, close and remove every existing handler (including one this module attached earlier, and the placeholder NullHandler that __init__.py puts on cvxium), set propagate to False, set the level, and attach the new handler.

Examples

Narration only, to a file:

Cvxium.enable_logging("~/cvxium.log")

Every inner iteration, which runs to thousands of lines:

Cvxium.enable_logging("~/cvxium.log", level=logging.DEBUG)