Netflix Spectator Python Client
netflix-spectator-py is a thin-client library for reporting metrics from Python applications to SpectatorD and the Netflix Atlas Timeseries Database. It is currently at version 1.1.2 and maintains an active release cadence, providing continuous bug fixes and feature enhancements.
Common errors
-
ResourceWarning: unclosed socket <socket.socket fd=X, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 0)>cause The SpectatorD client opens a UDP or Unix domain socket to send metrics. If a `Registry` (especially `GlobalRegistry` in short-lived scripts) is not explicitly shut down or if the script exits abruptly, the socket may not be closed properly.fixFor explicit `Registry` instances, ensure `.stop()` is called (e.g., in a `finally` block or application shutdown hook). For `GlobalRegistry` in tests or short scripts, consider `spectator.GlobalRegistry.stop()` explicitly, or switch to an explicit `Registry` instance for better lifecycle management. -
ModuleNotFoundError: No module named 'spectator'
cause The `netflix-spectator-py` library is not installed or the Python environment is not correctly configured.fixInstall the library using pip: `pip install netflix-spectator-py`. Ensure you are running your script with the Python interpreter where the library was installed. -
TypeError: 'int' object is not subscriptable (or similar errors with non-string tags)
cause Spectator requires all tag keys and values to be strings. Passing integers, booleans, or other non-string types directly as tag values will cause type errors or silent tag dropping after validation.fixAlways cast tag keys and values to strings: `tags={'status': str(status_code)}` or `id.with_tag('value', str(my_int_value))`.
Warnings
- gotcha When using `netflix-spectator-py` in a multiprocessing environment, especially with 'fork' or 'forkserver' start methods (Linux default), you must create a new `Registry` instance *after* each child process has started. Failing to do so can lead to deadlocks or incorrect metric reporting due to shared socket descriptors and background threads.
- gotcha For high-volume metric reporting (tens of thousands to millions of operations per second), direct per-operation metric updates can lead to high CPU usage for both your application and SpectatorD. This client sends a UDP packet for each update.
- gotcha All tag keys and values for `MeterId` objects must be strings. If non-string values are provided, the `MeterId` class will validate them, potentially dropping or changing invalid values and reporting a warning log. This can lead to unexpected metric dimensions or missing data.
- deprecated The `GlobalRegistry` is a legacy concept inherited from a prior thick-client version. While still functional and supported for backward compatibility, new code should prefer instantiating `Registry` objects directly with an explicit `Config`.
Install
-
pip install netflix-spectator-py
Imports
- Registry
from spectator import Registry
- Config
from spectator import Config
- GlobalRegistry
from spectator.main import GlobalRegistry
from spectator import GlobalRegistry
- StopWatch
from spectator import StopWatch
Quickstart
from spectator import Registry, Config
import time
import os
# Configure with optional extra common tags (e.g., for environment, service)
config = Config(extra_common_tags={'env': os.environ.get('SPECTATOR_ENV', 'dev')})
registry = Registry(config)
# Create and interact with a counter
request_counter = registry.counter('my_service.request_count')
request_counter.increment()
print(f"Request Count: {request_counter.get()}")
# Create and interact with a timer
processing_timer = registry.timer('my_service.processing_latency')
with processing_timer.start():
time.sleep(0.1) # Simulate work
print(f"Processing Latency recorded: {processing_timer.get_count()} events")
# Create and interact with a gauge (manual update)
current_items = registry.gauge('my_service.current_items')
current_items.set(5)
print(f"Current Items: {current_items.get()}")
# Note: Metrics are typically sent to a SpectatorD agent via UDP by default. Ensure SpectatorD is running.