Migrations
Migrating to 1.X¶
Version 1.X consists of a major rewrite that cleans up and simplifies the spectator-py thin client
API. It is designed to send metrics through spectatord.
As a result, some functionality has been moved to other modules, or removed. Most uses of the various
meters through the GlobalRegistry will continue to work as expected, although migrating to the new
Registry usage pattern is advised. A key addition is the ability to work directly with complex
MeterId objects, which offers more ways to compose tags.
New¶
Config¶
- Replace the
SidecarConfigwithConfig, and simplify usage. - The
locationconfiguration is clarified, with a default set to thespectatordUDP port, and a new option for picking the default Unix Domain Socket forspectatord. - The
extra_common_tagsconcept is clarified. Any extra common tags provided through theConfigobject are merged with two process-specific tags that may be present in environment variables. - Any
MeterIdorMeterobjects created throughRegistrymethods will contain these extra tags.
Common Tags¶
A few local environment common tags are now automatically added to all Meters. Their values are read from the environment variables.
| Tag | Environment Variable |
|---|---|
| nf.container | TITUS_CONTAINER_NAME |
| nf.process | NETFLIX_PROCESS_NAME |
Tags from environment variables take precedence over tags passed on code when creating the Config.
Note that common tags sourced by spectatord can't be overwritten.
Meters¶
- Implemented new meter types supported by SpectatorD:
AgeGauge,MaxGaugeandMonotonicCounter. See thespectatorddocumentation or the class docstrings for more details. - The
AgeGaugemeter added anow()method, which sets0as the value, so you do not need to remember this special value. - Add
MonotonicCounterUintwith ac_uint64data type, to supportuint64data types. These are not commonly encountered, as they usually only show up in networking metrics, such as bytes/sec in high-volume contexts. When you need it, you need it, else wise, it can be ignored. - The
MonotonicCounterwith afloatdata type continues to exist, for the more common use case. - Note that monotonic counters are convenience meter types provided by
spectatord, because they help you avoid the work of tracking previous values and calculating deltas.
Registry¶
- Add a
new_id()method and*_with_id()methods for all meter types, to support more complex tag operations related toMeterIdobjects. This follows the way they work in the other clients.
Moved¶
Meters¶
- Separate classes for each
Metertype. Relocated to a new module,spectator.meter, and exposed through top-level imports, for convenience. - The
MeterIdclass was moved to thespectator.metermodule and simplified. - The
spectator.histogrammetersPercentileTimerandPercentileDistributionsummary were moved tospectator.meterand are now accessible from theRegistryinterface.
StopWatch¶
- The
StopWatchcontext manager is no longer part of theTimerclass; it is now a standalone class. It has been preserved, because it continues to fulfill the purpose of simplifying howTimerandPercentileTimermeters record their values after exiting a block of code, and there are a few uses of this class across the organization. - The
Clockclass continues to exist, in order to support testing theStopWatchdeterministically.
Before:
import time
from spectator import GlobalRegistry
server_latency = GlobalRegistry.pct_timer("serverLatency")
with server_latency.stopwatch():
time.sleep(5)
After:
import time
from spectator import Registry, StopWatch
registry = Registry()
server_latency = registry.pct_timer("serverLatency")
with StopWatch(server_latency):
time.sleep(5)
Writers¶
- Separate classes for each
Writertype. Relocated to a new module,spectator.writer, and exposed through top-level imports, for convenience.
Removed¶
All the removed items are from the legacy thick client.
spectator.httpis removed. Use the standard library HTTP client, or Requests instead.- The
Meterclasses no longer have_measure()methods. Meters are now stateless and do not store measurements. The individual recording methods will call the writer to send the protocol line tospectatord. spectator.configis simplified and local to this library. There is no longer a need to import the internal configuration library.-
spectator.registryno longer has aclock()method. There are three choices for replacement:- Use
time.time()as a replacement forclock().wall_time(). - Use
time.perf_counter()as a replacement forclock().monotonic_time(). -
Use the
StopWatchContext Manager.import time from spectator import Registry, StopWatch registry = Registry() thread_sleep = registry.timer("thread.sleep") with StopWatch(thread_sleep): time.sleep(5)
- Use
-
spectator.registryno longer has astart()method. TheRegistryis now effectively stateless and there is nothing to start other than opening the output location. spectator.registryno longer has astop()function. Instead, useclose()to close the Registry. Once the registry is closed, it can't be started again. This is intended for final clean up of sockets or file handles.spectator.registryno longer reportsspectator.measurementsmetrics. Instead, you can usespectatordmetrics to troubleshoot metrics delivery.spectator.registryno longer keeps track of the Meters it creates. This means that you can't get a list of all Meters from the Registry. If you need to keep track of Meters, you can do so in your application code.spectator.histogrammetersPercentileTimerandPercentileDistributionSummaryno longer support defining min/max values.
Deprecated¶
- The
GlobalRegistryis a hold-over from the thick-client version of this library, but it has been maintained to help minimize the amount of code change that application owners need to implement when adopting the thin-client version of the library. Replace with direct use ofRegistry. - There are no plans to remove the
GlobalRegistry, until we know that all uses have been removed.
Before:
from spectator import GlobalRegistry
GlobalRegistry.gauge("server.queueSize", ttl_seconds=120).set(10)
After:
from spectator import Registry
registry = Registry()
registry.gauge("server.queueSize", ttl_seconds=120).set(10)
Migration Steps¶
- Make sure you're not relying on any of the removed functionality.
- Update imports for
Config,Registry, and anyMeters andWriters that are used for testing. - If you want to collect runtime metrics, add the spectator-py-runtime-metrics library, and follow the instructions in the README.
- If you use
PercentileDistributionSummaryorPercentileTimer, then update your code to use the respective functions provided by theRegistryto initialize these meters. - Remove the dependency on the
spectator-pyinternal configuration library - it is no longer required. - There is no longer an option to
start()orstop()the Registry at runtime. If you need to configure aRegistrythat doesn't emit metrics for testing purposes, then create aConfigobject with alocationofnone, to configure a no-op writer, and pass it to theRegistry.
Migrating to 0.2¶
- This library no longer publishes directly to the Atlas backends. It now publishes to the
SpectatorD sidecar which is bundled with all standard AMIs and containers. If you must
have the previous direct publishing behavior, because SpectatorD is not yet available on the
platform where your code runs, then you can pin to version
0.1.18. - The internal Netflix configuration companion library is no longer required and this dependency may be dropped from your project.
- The API surface area remains unchanged to avoid breaking library consumers, and standard uses of
GlobalRegistryhelper methods for publishing metrics continue to work as expected. Several helper methods on meter classes are now no-ops, always returning values such as0ornan. If you want to write tests to validate metrics publication, take a look at the tests in this library for a few examples of how that can be done. The core idea is to capture the lines which will be written out to SpectatorD. -
Replace uses of
PercentileDistributionSummarywith direct use of the Registrypct_distribution_summarymethod.# before from spectator import GlobalRegistry from spectator.histogram import PercentileDistributionSummary d = PercentileDistributionSummary(GlobalRegistry, "server.requestSize") d.record(10)# after from spectator import GlobalRegistry GlobalRegistry.pct_distribution_summary("server.requestSize").record(10) -
Replace uses of
PercentileTimerwith direct use of the Registrypct_timermethod.# before from spectator import GlobalRegistry from spectator.histogram import PercentileTimer t = PercentileTimer(GlobalRegistry, "server.requestSize") t.record(0.01)# after from spectator import GlobalRegistry GlobalRegistry.pct_timer("server.requestSize").record(0.1) -
Implemented new meter types supported by SpectatorD:
age_gauge,max_gaugeandmonotonic_counter. See the SpectatorD documentation or the class docstrings for more details.