class_docstr: Add-on to :class:`ContextMeter` that helps in the case where:
  
  - The code to be metered is not easily expressed as a self-contained code block
    e.g. you want to measure latency in the asyncio event loop before and after
    running a task
  - You want to alter the metrics depending on how the code ends; e.g. you want to
    post them differently in case of failure.
  
  Examples
  --------
  >>> ledger = DelayedMetricsLedger()  # Metering starts here
  >>> async def wrapper():
  ...     with ledger.record():
  ...         return await metered_function()
  >>> task = asyncio.create_task(wrapper())
  >>> # (later, elsewhere)
  >>> try:
  ...     await task
  ...     coarse_time = False
  ... except Exception:
  ...     coarse_time = "failed"
  ...     raise
  ... finally:
  ...     # Metering stops here
  ...     for label, value, unit in ledger.finalize(coarse_time):
  ...         # actually log metrics
class_docstr_tok: ["Add-on","to",":","class",":","`","ContextMeter","`","that","helps","in","the","case","where",":","-","The","code","to","be","metered","is","not","easily","expressed","as","a","self-contained","code","block","e.g",".","you","want","to","measure","latency","in","the","asyncio","event","loop","before","and","after","running","a","task","-","You","want","to","alter","the","metrics","depending","on","how","the","code","ends",";","e.g",".","you","want","to","post","them","differently","in","case","of","failure",".","Examples","--","--","--","--",">",">",">","ledger","=","DelayedMetricsLedger","(",")","#","Metering","starts","here",">",">",">","async","def","wrapper","(",")",":","...","with","ledger.record","(",")",":","...","return","await","metered_function","(",")",">",">",">","task","=","asyncio.create_task","(","wrapper","(",")",")",">",">",">","#","(","later",",","elsewhere",")",">",">",">","try",":","...","await","task","...","coarse_time","=","False","...","except","Exception",":","...","coarse_time","=","``","failed","''","...","raise","...","finally",":","...","#","Metering","stops","here","...","for","label",",","value",",","unit","in","ledger.finalize","(","coarse_time",")",":","...","#","actually","log","metrics"]
docstr: Ingest metrics logged with :meth:`ContextMeter.digest_metric` or
  :meth:`ContextMeter.meter` and temporarily store them in :ivar:`metrics`.
  
  Parameters
  ----------
  key: Hashable, optional
      See :meth:`ContextMeter.add_callback`
docstr_tok: ["Ingest","metrics","logged","with",":","meth",":","`","ContextMeter.digest_metric","`","or",":","meth",":","`","ContextMeter.meter","`","and","temporarily","store","them","in",":","ivar",":","`","metrics","`",".","Parameters","--","--","--","--","--","key",":","Hashable",",","optional","See",":","meth",":","`","ContextMeter.add_callback","`"]
code: def record(self, *, key: Hashable | None = None) -> Iterator[None]:
      """Ingest metrics logged with :meth:`ContextMeter.digest_metric` or
      :meth:`ContextMeter.meter` and temporarily store them in :ivar:`metrics`.
  
      Parameters
      ----------
      key: Hashable, optional
          See :meth:`ContextMeter.add_callback`
      """
      with context_meter.add_callback(self._callback, key=key):
          yield
  
imports: from __future__ import annotations
  import asyncio
  import collections
  import threading
  import time
  from collections.abc import Callable, Hashable, Iterator
  from contextlib import contextmanager
  from contextvars import ContextVar
  from dataclasses import dataclass
  from functools import wraps
  from math import nan
  from typing import Literal
  import psutil
  from distributed.compatibility import WINDOWS
label_desc: Use image node_id 3 for calling the DelayedMetricsLedger obj's underlying member method code with example usage: obj.record() without return types