geeViz.eeAuth.monitoring¶
Earth Engine usage monitoring — Cloud Monitoring poller.
Reads the earthengine.googleapis.com/project/cpu/usage_time metric
from Cloud Monitoring, aggregates at a caller-chosen bucket size
(grouping_seconds, default 3600 = hourly), and returns
per-workload_tag rows. Attribution is not this module’s concern
— it returns the raw tag string; the caller joins it to whatever
storage they maintain (tag → parts mapping table, users table, etc.)
to recover human-readable identity.
Design constraint: reversible tag encoding within EE’s 63-char workload_tag limit turns out to be infeasible for realistic attribution tuples (see comments in geeViz/eeAuth/tags.py). Rather than half-solve the reversibility problem, this module cleanly stops at “here are the tags and their EECU consumption” — everything upstream (mint the tag from parts + store the mapping) and everything downstream (join back for display, feed a billing ledger) stays with the caller.
Typical wiring:
from geeViz.eeAuth.monitoring import EEUsageMonitor
monitor = EEUsageMonitor(project="my-gcp-project",
cost_per_eecu_hour=0.40)
rows = monitor.poll(start_time=..., end_time=...)
# rows: [{workload_tag, bucket_start, eecu_seconds,
# eecu_hours, cost_usd}, ...]
for row in rows:
parts = my_tag_store.lookup(row["workload_tag"])
my_db.upsert_ee_bucket(**row, **parts)
Cost model: cost_per_eecu_hour × eecu_hours. Google’s public
commercial rate is $0.40/EECU-hour; non-commercial projects bill at 0.
The monitor is agnostic — pass whatever your billing agreement says.
Classes
|
Cloud Monitoring poller for EE workload consumption. |
- class geeViz.eeAuth.monitoring.EEUsageMonitor(project: str, cost_per_eecu_hour: float = 0.4, metric_type: str = 'earthengine.googleapis.com/project/cpu/usage_time')[source]¶
Bases:
objectCloud Monitoring poller for EE workload consumption.
One instance per GCP project. Thread-safe (the underlying
MetricServiceClientis a shared singleton and gRPC channels are concurrent-safe). Cheap to construct — no I/O untilpoll().- Parameters:
project – GCP project id holding the EE metrics (the project billed for EE usage). Typically the
GEE_PROJECT/GOOGLE_CLOUD_PROJECTyour tenant runs against.cost_per_eecu_hour – USD per EECU-hour applied to every returned row. Default $0.40 (Google commercial rate). Set to 0 for noncommercial projects.
metric_type – full Cloud Monitoring metric path. Default is the current EE CPU metric; override if Google renames it or you want to poll a different measurement.
- DEFAULT_METRIC = 'earthengine.googleapis.com/project/cpu/usage_time'¶
- poll(start_time: datetime, end_time: datetime | None = None, grouping_seconds: int = 3600, snap_to: bool = True) list[dict][source]¶
Query Cloud Monitoring for the configured metric between
start_timeandend_time(defaults to NOW), grouped bymetric.workload_tagatgrouping_secondsgranularity.- Parameters:
start_time – timezone-aware datetime — lower bound.
end_time – timezone-aware datetime — upper bound. Defaults to
now(UTC)if omitted.grouping_seconds – bucket size in seconds. Common values:
60(minute),3600(hour, default),86400(day),604800(week). Any positive int is accepted.snap_to – if True (default),
start_timeis floored andend_timeis ceiled to the nearest multiple ofgrouping_secondsfrom the Unix epoch. This keeps bucket boundaries stable across repeated polls (e.g. two pulls of the same window return the same rows) — highly recommended. Pass False to query the raw sub-bucket window (useful for ad-hoc slicing).
Returns one dict per (workload_tag, bucket_start):
{ "workload_tag": "wl_abc123...", "bucket_start": datetime(2026, 8, 12, 14, 0, tzinfo=UTC), "eecu_seconds": 12.34, "eecu_hours": 0.003428, "cost_usd": 0.001371, }
Rows with negative or missing values are floored to 0. Untagged points are skipped — attribution is impossible without a tag.
Returns an empty list on any Cloud Monitoring error (the error is logged). Callers should treat “no rows” as “no usage in window” rather than a hard failure.