import dataclasses
from .utils import handle_internal_errors as handle_internal_errors
from abc import ABC
from collections.abc import Sequence
from opentelemetry.metrics import CallbackT as CallbackT, Counter, Histogram, Instrument, Meter, MeterProvider, ObservableCounter, ObservableGauge, ObservableUpDownCounter, UpDownCounter, _Gauge as Gauge
from opentelemetry.util.types import Attributes
from threading import Lock
from typing import Any, Generic, TypeVar
from weakref import WeakSet

@dataclasses.dataclass
class ProxyMeterProvider(MeterProvider):
    provider: MeterProvider
    meters: WeakSet[_ProxyMeter] = dataclasses.field(default_factory=WeakSet)
    lock: Lock = dataclasses.field(default_factory=Lock)
    suppressed_scopes: set[str] = dataclasses.field(default_factory=set)
    def get_meter(self, name: str, version: str | None = None, schema_url: str | None = None, attributes: Attributes | None = None) -> Meter: ...
    def suppress_scopes(self, *scopes: str) -> None: ...
    def set_meter_provider(self, meter_provider: MeterProvider) -> None: ...
    def shutdown(self, timeout_millis: float = 30000) -> None: ...
    def force_flush(self, timeout_millis: float = 30000) -> None: ...

class _ProxyMeter(Meter):
    def __init__(self, meter: Meter, name: str, version: str | None, schema_url: str | None) -> None: ...
    def set_meter(self, meter_provider: MeterProvider) -> None:
        """Called when a real meter provider is set on the creating _ProxyMeterProvider.

        Creates a real backing meter for this instance and notifies all created
        instruments so they can create real backing instruments.
        """
    def create_counter(self, name: str, unit: str = '', description: str = '') -> Counter: ...
    def create_up_down_counter(self, name: str, unit: str = '', description: str = '') -> UpDownCounter: ...
    def create_observable_counter(self, name: str, callbacks: Sequence[CallbackT] | None = None, unit: str = '', description: str = '') -> ObservableCounter: ...
    def create_histogram(self, name: str, unit: str = '', description: str = '', **kwargs: Any) -> Histogram: ...
    def create_gauge(self, name: str, unit: str = '', description: str = '') -> Gauge: ...
    def create_observable_gauge(self, name: str, callbacks: Sequence[CallbackT] | None = None, unit: str = '', description: str = '') -> ObservableGauge: ...
    def create_observable_up_down_counter(self, name: str, callbacks: Sequence[CallbackT] | None = None, unit: str = '', description: str = '') -> ObservableUpDownCounter: ...
InstrumentT = TypeVar('InstrumentT', bound=Instrument)

class _ProxyInstrument(ABC, Generic[InstrumentT]):
    def __init__(self, meter: Meter, **kwargs: Any) -> None: ...
    def on_meter_set(self, meter: Meter) -> None:
        """Called when a real meter is set on the creating _ProxyMeter."""

class _ProxyCounter(_ProxyInstrument[Counter], Counter):
    def add(self, amount: int | float, attributes: Attributes | None = None, *args: Any, **kwargs: Any) -> None: ...

class _ProxyHistogram(_ProxyInstrument[Histogram], Histogram):
    def record(self, amount: int | float, attributes: Attributes | None = None, *args: Any, **kwargs: Any) -> None: ...

class _ProxyObservableCounter(_ProxyInstrument[ObservableCounter], ObservableCounter): ...
class _ProxyObservableGauge(_ProxyInstrument[ObservableGauge], ObservableGauge): ...
class _ProxyObservableUpDownCounter(_ProxyInstrument[ObservableUpDownCounter], ObservableUpDownCounter): ...

class _ProxyUpDownCounter(_ProxyInstrument[UpDownCounter], UpDownCounter):
    def add(self, amount: int | float, attributes: Attributes | None = None, *args: Any, **kwargs: Any) -> None: ...

class _ProxyGauge(_ProxyInstrument[Gauge], Gauge):
    def set(self, amount: int | float, attributes: Attributes | None = None, *args: Any, **kwargs: Any) -> None: ...
