embedl_hub.tracking package#
Public API for the Embedl Hub tracking package.
Top-level re-exports#
Client— Tracking client for projects and runs.RunStatus— The states a run moves through, for filtering listings.RunType— Built-in run-type categories.TrackingFailureWarning— Warning raised in place of an error when a tracking call fails inside a safe scope.TrackingProjectChangedWarning— Warning raised when adopting a run also moved the client to that run’s project.TrackingUsageError— Raised when a tracking call is itself malformed; never downgraded by safe mode.
- class embedl_hub.tracking.Client(api_config: ApiConfig | None = None, *, log_remote_artifacts: bool = True)[source]#
Bases:
objectTracks projects and runs for the Embedl Hub web app.
- property active_run: Run#
- property api_config: ApiConfig#
Get or create the API config from the resolved settings.
- Returns:
The credentials and Hub address this client uses.
- Raises:
RuntimeError – If no API key is configured.
- property api_key: str#
The API key this client authenticates with.
For handing to something else that has to authenticate. Do not print or log it: a key that reaches a terminal, a notebook output or a CI log has to be treated as compromised.
api_key_sourceanswers where the key comes from without exposing it.- Returns:
The key in use.
- Raises:
RuntimeError – If no API key is configured.
- property api_key_source: Literal['env', 'config', 'default'] | None#
Which layer supplied the API key this client uses.
Names where the key was read from — the environment or the config file — rather than the key itself, so it is safe to print. Use
api_keyfor the value.- Returns:
"env"or"config"for a key this client resolved, orNonewhen no layer supplied one: either nothing is configured, or the client was handed an explicit configuration, which comes from the caller rather than from anywhere on this machine.
- property base_url: str#
The address of the Hub this client sends requests to.
Needs no API key: which Hub is configured is not an authentication question, so this answers before
authhas been run.- Returns:
The address, always ending in
/.
- create_run(type: RunType | str, name: str | None = None, parent_run_id: str | None = None, custom_type: str | None = None, description: str | None = None, *, pending: bool = False, safe: bool = False) Run | None[source]#
Create a new run for the current project.
- Parameters:
type – Built-in run type or a custom type label.
name – Optional run display name.
parent_run_id – Optional parent run ID for lineage.
custom_type – Label used when
typeisRunType.CUSTOM.description – Optional run description. The Hub trims it, stores blank input as no description, and accepts at most 1,000 characters.
pending – When
True, the run is created pending rather than running: it exists and can be logged to, and the Hub lists it asRunStatus.PENDINGuntil something starts it. For work launched elsewhere, so the run can be annotated before the job that will run in it exists. Itsstarted_atis provisional until then.safe – When
True, a failure to reach the Hub emits aTrackingFailureWarningand returnsNoneinstead of raising. An invalid run type is a caller mistake, not a Hub failure, so it still raises.
- Returns:
The created run, or
Noneif it could not be created and safe isTrue.- Raises:
ValueError – If a custom run type has no label, whatever safe is set to.
ApiError – If the Hub rejects the request and safe is
False.
- property current_run_log: RunLog | None#
Get the current in-progress
RunLog, orNoneif no run is active.
- get_run_project(run_id: str) Project[source]#
Look up the project a run belongs to.
Needs no project selected first, so a parent run ID is enough to open the next run in the same project. Select the project with
use_project()rather than by name: names are unique per owner only, so a project shared with you may share its name with one of yours:project = client.get_run_project(parent_run_id) client.use_project(project) with client.start_run("train", parent_run_id=parent_run_id): ...
Like
get_devices(), a failure raises rather than warns.- Parameters:
run_id – The run’s ID.
- Returns:
The project the run belongs to.
- Raises:
ValueError – If run_id is blank.
ApiError – If the hub does not know the run, or it is in a project this API key cannot read; either is a 404.
- property latest_run_log: RunLog | None#
Get the most recent completed
RunLog, orNoneif no runs have completed.
- list_runs(*, params: Mapping[str, str] | None = None, statuses: RunStatus | Sequence[RunStatus] | None = None, types: RunType | str | Sequence[RunType | str] | None = None, limit: int | None = None, offset: int | None = None) RunListPage[source]#
List the current project’s runs, newest first.
Find the run a job logged its own ID on, to link the next job to it:
page = client.list_runs(params={"vertex_ai_job_id": job_id}) parent = page.items[0] if page.items else None
Like
get_devices(), a failure raises rather than warns.- Parameters:
params – Parameters the runs must have logged, as name to value. Names and values are normalized the way
log_param()stores them, so what was logged is found again.statuses – Only runs with this status, or one of these.
types – Only runs of this type, or one of these. A string is read as
start_run()reads it: a built-in type name selects that type, any other label selects the custom runs filed under it. Built-in types and labels cannot be combined in one call.limit – Page size; the hub’s default and cap apply.
offset – Runs to skip, for paging.
- Returns:
One page of run summaries with pagination info.
- Raises:
ValueError – If a run type label is blank or contains a comma, built-in types are mixed with labels, a parameter name is blank, a parameter name or value contains a NUL character, or two parameter names are the same once trimmed.
RuntimeError – If no project is set.
ApiError – If the hub rejects the request.
- log_artifact(file_path: Path | str | LoggedArtifact, name: str | None = None, file_name: str | None = None, run_id: str | None = None, *, ctx: HubContext | None = None, device_name: str | None = None, save_to_run_log: bool = True) LoggedArtifact | None[source]#
Log an artifact file for a run and upload it to artifact storage.
Accepts a local path, a remote path, or an existing
LoggedArtifact. Remote artifacts are fetched from the device and uploaded to the Hub whenlog_remote_artifactsisTrue(the default). Set it toFalseto skip remote uploads and speed up execution.If no name is given, the artifact is logged as unnamed. If no file_name is given, the name from the file path is used. If no run_id is given, the current active run is used.
- Parameters:
file_path – Local file path, remote path, or a
LoggedArtifact.name – Optional artifact name.
file_name – Optional file name override.
run_id – Optional run ID (defaults to the active run).
ctx – Hub context, required when file_path is remote or a
LoggedArtifact.device_name – Name of the device that owns the remote artifact. Required for remote paths; ignored for
LoggedArtifact(uses its own device info).save_to_run_log – Whether to also record the artifact in the current
RunLog.
- Returns:
The
LoggedArtifactthat was recorded, orNoneif it failed inside asafe_log()scope.- Raises:
RuntimeError – If a remote artifact is received without a ctx, or a remote path is received without device_name.
TrackingUsageError – If file_name is given but blank — a broken caller rather than a Hub failure, so it is raised even inside a
safe_log()scope.FileTooLargeError – If the file exceeds the maximum allowed upload size.
StorageQuotaExceededError – If the storage quota has been exceeded.
ArtifactUploadError – If the file upload fails.
- log_batch(*, metrics: list[tuple[str, float, int | None]] | None = None, params: list[tuple[str, str]] | None = None, external_links: list[tuple[str, str]] | None = None, save_to_run_log: bool = True) None[source]#
Log multiple metrics and params in a single API call.
This is significantly more efficient than calling
log_metric()andlog_param()in a loop, as it sends all data in one PATCH request instead of one POST per item.- Parameters:
metrics – List of
(name, value, step)tuples. step may beNonefor metrics without a step.params – List of
(name, value)tuples.external_links – List of
(label, url)tuples.save_to_run_log – Whether to also record entries in the current
RunLog. Defaults toTrue.
- log_dashboard(dashboard: Dashboard | Path | str, *, name: str | None = None, description: str | None = None, default: bool = False, opens_run: bool = False) RunDashboard | None[source]#
Attach a dashboard to the current run.
Accepts a
Dashboardor the path of a file written bysave().- Parameters:
dashboard – The dashboard, or the path of its JSON file.
name – The name to store it under on the run. Overrides the name the dashboard carries; required for a file that holds a bare config.
description – Overrides the dashboard’s description.
default – Makes it the run’s default dashboard, the one the run’s Dashboard tab opens on. A run has one.
opens_run – Opens the run itself on it rather than on the run’s details. Implies
default, so there is no need to pass both.
- Returns:
The
RunDashboardthe Hub stored, orNoneif it failed inside asafe_log()scope.- Raises:
DashboardSchemaError – If the file is not a dashboard this SDK reads, the dashboard ends up without a name or with one the Hub would not store, or its sections and panels do not form a valid layout. A broken input rather than a Hub failure, so it is raised even inside a
safe_log()scope.FileNotFoundError – If there is no file at the given path. Degrades to a warning inside a
safe_log()scope.
- log_link(label: str, url: str, *, save_to_run_log: bool = True) LoggedExternalLink | None[source]#
Log an external link for the current run.
- Parameters:
label – The link label.
url – The link target.
save_to_run_log – Whether to also record this entry in the current
RunLog. Defaults toTrue.
- Returns:
The
LoggedExternalLinkthat was recorded, orNoneif it failed inside asafe_log()scope.
- log_metric(name: str, value: float, step: int | None = None, *, save_to_run_log: bool = True) LoggedMetric | None[source]#
Log a metric for the current run.
- Parameters:
name – The metric name.
value – The metric value.
step – Optional step number.
save_to_run_log – Whether to also record this entry in the current
RunLog. Defaults toTrue.
- Returns:
The
LoggedMetricthat was recorded, orNoneif it failed inside asafe_log()scope.
- log_param(name: str, value: str, *, save_to_run_log: bool = True) LoggedParam | None[source]#
Log a parameter for the current run.
- Parameters:
name – The parameter name.
value – The parameter value.
save_to_run_log – Whether to also record this entry in the current
RunLog. Defaults toTrue.
- Returns:
The
LoggedParamthat was recorded, orNoneif it failed inside asafe_log()scope.
- property log_remote_artifacts: bool#
Whether remote artifacts are fetched and uploaded to the Hub.
When
True(the default), callinglog_artifact()with a remote path or a remoteLoggedArtifactwill download the file from the device and upload it to the Embedl Hub.Set to
Falseto skip the download-and-upload step and speed up execution. The artifact is still recorded in the run log, but its contents are not transferred.
- log_tag(name: str, value: str) Tag | None[source]#
Log a tag for the current run.
- Parameters:
name – The tag name.
value – The tag value.
- Returns:
The
Tagthat was recorded, orNoneif it failed inside asafe_log()scope.
- property project: Project#
- property run_history: RunLogHistory#
Get the run history (read-only).
- Returns:
A
RunLogHistorycontaining all completedRunLogentries. The history cannot be modified.
- safe_log() Iterator[Client][source]#
Downgrade logging failures to warnings inside this scope.
Within the scope,
log_param(),log_metric(),log_link(),log_batch(),log_tag(),log_artifact()andlog_dashboard()emit aTrackingFailureWarningand returnNoneinstead of raising, so a Hub outage cannot abort the surrounding script:with client.safe_log(): client.log_metric("accuracy", 0.92)
Scopes nest; leaving one restores the previous state. Only the client’s own logging calls are affected — exceptions raised by your code inside the scope propagate untouched, and calls made outside it raise as usual.
This does not cover starting or ending a run. Pass
safe=Truetostart_run()for that.- Returns:
A context manager yielding this client.
- property safe_logging: bool#
Whether logging calls currently warn instead of raising.
Truewhile execution is inside asafe_log()scope. Read-only — safe mode is entered by scope, never by assignment, so a client handed to library code cannot be permanently disarmed.
- set_project(name: str, *, safe: bool = False) Project | None[source]#
Set or create the current project by name.
- Parameters:
name – The project name. Created on the Hub when it does not already exist.
safe – When
True, a failure emits aTrackingFailureWarningand returnsNoneinstead of raising.
- Returns:
The project, or
Noneif it could not be set and safe isTrue. Either way, a failure leaves the client with no project selected rather than the one selected before, so a later run cannot be filed against the wrong project.- Raises:
TrackingUsageError – If a run is active. Moving the project out from under it would leave the client addressing that run inside a project it is not in, which every log call composes independently and so cannot detect: the requests go to a run that is not there. Raised whatever safe is set to, since this is a caller mistake rather than a Hub failure.
ApiError – If the Hub rejects the request and safe is
False.
- start_run(type: RunType | str, name: str | None = None, parent_run_id: str | None = None, custom_type: str | None = None, description: str | None = None, *, safe: bool = False) Iterator[Run | None][source]#
Start a run and finish it when the context exits.
- Parameters:
type – Built-in run type or a custom type label.
name – Optional run display name.
parent_run_id – Optional parent run ID for lineage.
custom_type – Label used when
typeisRunType.CUSTOM.description – Optional run description. The Hub trims it, stores blank input as no description, and accepts at most 1,000 characters.
safe – When
True, a failure to create or complete the run emits aTrackingFailureWarninginstead of raising. If the run cannot be created the body still runs as though tracking had never been added, with nothing active, and the context manager yieldsNone. Guard the body withsafe_log()as well if it logs —safecovers only the run lifecycle. Exceptions from the body are never suppressed.
- Returns:
An iterator yielding the created run, or
NonewhensafeisTrueand the run could not be created.- Raises:
RuntimeError – If a run is already active, whatever
safeis set to. Runs do not nest; use parent_run_id to record that one run followed another.ValueError – If a custom run type has no label, whatever
safeis set to — that is a mistake in the call, not a Hub failure.ApiError – If the Hub rejects a create or completion request and
safeisFalse.
- update_active_run(status: Literal[RunStatus.FINISHED, RunStatus.KILLED, RunStatus.FAILED] | None = None, ended_at: datetime | None = None, metrics: list[Metric] | None = None, params: list[Parameter] | None = None, external_links: list[ExternalLink] | None = None, parent_run_id: str | _RemoveParent | None = None, description: str | None = None) None[source]#
Update the active run.
Writes metrics, params, links and the description, so it counts as logging: inside a
safe_log()scope a failure warns instead of raising.- Parameters:
status – Optional terminal run status.
ended_at – Optional completion time.
metrics – Metrics to append.
params – Parameters to append.
external_links – External links to append.
parent_run_id – Parent run ID, or
REMOVE_PARENTto clear the parent.description – New run description. Pass a blank or whitespace-only string to clear it. The Hub accepts at most 1,000 characters.
- Returns:
None.- Raises:
ApiError – If the Hub rejects the request and the call is not inside a
safe_log()scope.
- use_inherited_run(*, safe: bool | None = None) Run | None[source]#
Log to the run this process was handed, if it was handed one.
Reads
EMBEDL_HUB_RUNandEMBEDL_HUB_PROJECT, whichembedl-hub execexports for the command it wraps, so a script can record into the run the wrapper already created:embedl-hub exec --type training ./train.py
client = Client() client.use_inherited_run() client.log_metric("loss", 0.1)
A missing
EMBEDL_HUB_RUNis not an error. It is whatexec --safeleaves behind when the Hub could not be reached: the project is set, no run exists, and the command is meant to carry on untracked. So this warns and returnsNonerather than raising, and a script that treats the return value as optional works under both.- Parameters:
safe – As for
use_run(), including that the default defers toEMBEDL_HUB_SAFE, which is set for exactly this case byexec --safe.- Returns:
The adopted run, or
Noneif the environment named none, or if it could not be adopted and safe isTrue.- Raises:
TrackingUsageError – If a run is already active.
ApiError – If the Hub rejects the request and safe is
False.
- use_pending_run(run_id: str, project: str | None = None, *, safe: bool | None = None) Iterator[Run | None][source]#
Start a pending run and finish it when the context exits.
For the job a pending run was created for: something else made the run with
create_run()andpending=True, annotated it, and handed over its ID. This starts it as the work begins and, unlikeuse_run(), takes responsibility for it — the run is completed from how the block ends, exactly asstart_run()completes a run it created:with client.use_pending_run(run_id): client.log_metric("loss", 0.1)
- Parameters:
run_id – The pending run to start.
project – As for
use_run():Nonemeans the selected project, or, with none selected, that the run is looked up by ID alone and its own project becomes the selection; a name switches to that project first.safe – As for
use_run(), including thatNonedefers toEMBEDL_HUB_SAFE. When tolerated, a failure to find or start the run warns, leaves nothing selected, and yieldsNone; the body still runs.
- Returns:
An iterator yielding the run, now running, or
Noneif it could not be started and safe isTrue.- Raises:
TrackingUsageError – If run_id is blank, if a run is already active, or if the run is not pending — it is running or finished, or something else started it while it was being adopted here — since whoever did that owns its outcome; use
use_run()to log to a run something else is running. Raised whatever safe is set to.ApiError – If the Hub rejects a request and safe is
False.
- use_project(project: Project) Project[source]#
Select a project already looked up, without a Hub call.
For a
Projectin hand, such as the oneget_run_project()returns. It selects exactly that project, whereset_project()looks one up by name and cannot tell apart two projects that share one.- Parameters:
project – The project to select.
- Returns:
project, now the current project.
- Raises:
TrackingUsageError – If a run is active; see
set_project().
- use_run(run_id: str, project: str | None = None, *, safe: bool | None = None) Run | None[source]#
Log to a run that already exists, started somewhere else.
For picking up work another process began — most often the run
embedl-hub execcreated for the command it is wrapping. Useuse_inherited_run()for that case, which reads the run and project out of the environment rather than being told them.Adopting a run does not take responsibility for it. Nothing here completes it, and leaving the process does not either: whoever started the run still decides its outcome. Under
execthat is the wrapper, which completes the run from the command’s exit status.- Parameters:
run_id – The run to log to.
project – The project the run is in.
Nonemeans the project already selected, which the run must then be in; with no project selected, the run is looked up by ID alone and its own project becomes the selection. A name switches to that project first and warns withTrackingProjectChangedWarning, because a run belongs to one project and adopting it has to move the client with it.safe – When
True, a failure to reach the Hub emits aTrackingFailureWarningand returnsNoneinstead of raising, leaving nothing adopted. As elsewhere, this covers an unreliable Hub and not a malformed call.None, the default, takes the answer from the environment:embedl-hub exec --safesetsEMBEDL_HUB_SAFEfor the command it wraps, so a script adopting the run that wrapper handed it does not raise where the wrapper itself warned. PassFalseto insist on raising even there.
- Returns:
The adopted run, or
Noneif it could not be adopted and safe isTrue.- Raises:
TrackingUsageError – If run_id is blank, if a run is already active, or if the run has already finished. Raised whatever safe is set to.
ApiError – If the Hub rejects the request and safe is
False.
- class embedl_hub.tracking.RunStatus(value)[source]#
Bases:
Enum- FAILED = 'FAILED'#
- FINISHED = 'FINISHED'#
- KILLED = 'KILLED'#
- PENDING = 'PENDING'#
- RUNNING = 'RUNNING'#
- class embedl_hub.tracking.RunType(value)[source]#
Bases:
Enum- COMPILE = 'COMPILE'#
- CUSTOM = 'CUSTOM'#
- EVAL = 'EVAL'#
- GRAPH = 'GRAPH'#
- INFERENCE = 'INFERENCE'#
- PROFILE = 'PROFILE'#
- exception embedl_hub.tracking.TrackingFailureWarning[source]#
Bases:
UserWarningWarns that a tracking operation failed and was skipped.
Emitted instead of raising when the failing call is covered by a safe scope — a run started with
safe=True, or a logging call made insidesafe_log(). The script continues, and whether the affected data reached the Hub is unknown: a request that failed while the response was being read may already have been committed. Treat it as uncertain rather than lost, since retrying on the assumption it was lost can duplicate it.This is its own category so it can be filtered independently of other warnings. Escalating it to an error is not applied to a failed run completion while an exception is already leaving the
withbody: that exception is the one the caller needs, so it is never replaced:# Silence them warnings.filterwarnings("ignore", category=TrackingFailureWarning) # Or turn them back into errors warnings.filterwarnings("error", category=TrackingFailureWarning)
- exception embedl_hub.tracking.TrackingProjectChangedWarning[source]#
Bases:
UserWarningWarns that selecting a run also changed the active project.
A run belongs to exactly one project, so adopting one from another project has to move the client with it. That is not a failure, and it is not what the caller literally asked for either, so it is said out loud rather than done quietly — a later
log_metricwould otherwise land somewhere the caller did not choose.Its own category, so it can be silenced by a script that switches deliberately without also silencing
TrackingFailureWarning:warnings.filterwarnings( "ignore", category=TrackingProjectChangedWarning )
- exception embedl_hub.tracking.TrackingUsageError[source]#
Bases:
RuntimeErrorRaised when a tracking call itself is malformed.
Safe mode (
safe=True,safe_log()) tolerates an unreliable Hub, not a malformed call, so this is raised even inside a safe scope: a warning the caller cannot act on would just hide the mistake.It is marked with its own class rather than inferred from the exception type, because the type does not carry the distinction — a missing project or absent active run raises
RuntimeErrortoo, and those are degradable, being the downstream consequence of a failure the caller already chose to tolerate.Subclasses
RuntimeErrorso that existing handlers and the:raises RuntimeError:contracts keep working.