Tracking API
User and permission management lives in Users and permissions.
Projects
DearDiary.get_project — Function
get_project(id::AbstractString)::Optional{Project}Get a Project by id.
Arguments
id::AbstractString: The id of the project to query.
Returns
A Project object. If the record does not exist, return nothing.
get_project(client::Client, id::AbstractString)::Optional{Project}Fetch a Project via GET /project/{id} on the API behind client. Returns nothing when the server replies 404 (record missing or viewer lacks ReadPermission) and raises ClientError for other failures.
DearDiary.get_projects — Function
get_projects(user::User)::Array{Project,1}Return the projects visible to user.
Admins see every project. Non-admins see only projects where they have a UserPermission record with ReadPermission granted; projects without a matching permission row are omitted entirely so the dashboard never shows cards the viewer cannot open.
Arguments
user::User: The viewer.
Returns
An array of Project objects scoped to the user's read access.
get_projects(client::Client)::Array{Project,1}List every Project the authenticated viewer can read via GET /project/. Admins receive every project; non-admins receive only those with ReadPermission granted.
DearDiary.create_project — Function
create_project(user_id::AbstractString, name::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Create a Project.
Arguments
user_id::AbstractString: The id of the user creating the project. The user must have admin privileges.name::AbstractString: The name of the project.
Returns
- The created project ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
create_project(name::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Create a Project. Uses the "default" user to create the project.
Arguments
name::AbstractString: The name of the project.
Returns
- The created project ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
create_project(client::Client, name::AbstractString)::StringCreate a Project named name via POST /project/. The route requires an admin viewer; non-admin callers receive 403 ADMIN_REQUIRED. Returns the new project id.
DearDiary.update_project — Function
update_project(id::AbstractString, name::Optional{AbstractString}, description::Optional{AbstractString})::Type{<:UpsertResult}Update a Project record.
Arguments
id::AbstractString: The id of the project to update.name::Optional{AbstractString}: The new name for the project.description::Optional{AbstractString}: The new description for the project.
Returns
An UpsertResult. Updated if the record was successfully updated (or no changes were made), Duplicate if the record already exists, Unprocessable if the record violates a constraint, and Error if an error occurred while updating the record.
update_project(client::Client, id::AbstractString; name=nothing, description=nothing)::NothingPatch a Project via PATCH /project/{id}. Any keyword left as nothing is left untouched server-side. Admin-only. Raises ClientError on failure.
DearDiary.delete_project — Function
delete_project(id::AbstractString)::BoolDelete a Project record together with everything it owns: its model registry (Model and ModelVersion rows), its Experiment records with their iterations and artifacts, its UserPermission rows, and its tag associations.
Arguments
id::AbstractString: The id of the project to delete.
Returns
true if the record was successfully deleted, false otherwise.
delete_project(client::Client, id::AbstractString)::NothingDelete a Project via DELETE /project/{id}. The project's model registry, experiments (with their iterations and artifacts), UserPermission rows, and tag attachments go with it. Admin-only. Raises ClientError on failure.
Experiments
DearDiary.get_experiment — Function
get_experiment(id::AbstractString)::Optional{Experiment}Get an Experiment by id.
Arguments
id::AbstractString: The id of the experiment to query.
Returns
An Experiment object. If the record does not exist, return nothing.
get_experiment(client::Client, id::AbstractString)::Optional{Experiment}Fetch an Experiment via GET /experiment/{id}. Returns nothing when the server replies 404 (record missing or viewer lacks ReadPermission on the owning project) and raises ClientError for other failures.
DearDiary.get_experiments — Function
get_experiments(project_id::AbstractString)::Array{Experiment, 1}Get all Experiment for a given project.
Arguments
project_id::AbstractString: The id of the project to query.
Returns
An array of Experiment objects.
get_experiments(project_id::AbstractString, page::Pagination)::PaginatedResponse{Experiment}Get a page of Experiment records for a project, with total count populated.
Arguments
project_id::AbstractString: The id of the project to query.page::Pagination: The page bounds (limit + offset).
Returns
A PaginatedResponse of Experiment.
get_experiments(client::Client, project_id::AbstractString)::Array{Experiment,1}Returns the first page (default limit) of Experiment records under project_id, discarding the pagination envelope.
get_experiments(client::Client, project_id::AbstractString, page::Pagination)::PaginatedResponse{Experiment}Fetch a page of Experiment records under project_id via GET /experiment/project/{project_id}?limit=…&offset=…. Requires ReadPermission on the project.
DearDiary.create_experiment — Function
create_experiment(project_id::AbstractString, status_id::Integer, name::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Create an Experiment.
Arguments
project_id::AbstractString: The id of the project to create the experiment for.status_id::Integer: The status of the experiment.name::AbstractString: The name of the experiment.
Returns
- The created experiment ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
create_experiment(project_id::AbstractString, status::ExperimentStatus, name::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Create an Experiment.
Arguments
project_id::AbstractString: The id of the project to create the experiment for.status::ExperimentStatus: The status of the experiment.name::AbstractString: The name of the experiment.
Returns
- The created experiment ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
create_experiment(client::Client, project_id::AbstractString, status_id::Integer, name::AbstractString)::StringCreate an Experiment under project_id via POST /experiment/project/{project_id}. status_id must equal Integer(IN_PROGRESS); the server rejects experiments that start already terminated. Requires CreatePermission on the project. Returns the new experiment id.
create_experiment(client::Client, project_id::AbstractString, status::ExperimentStatus, name::AbstractString)::StringExperimentStatus-typed overload of create_experiment. The server only accepts IN_PROGRESS; the other variants exist for symmetry with the local API.
DearDiary.update_experiment — Function
update_experiment(id::AbstractString, status_id::Optional{Integer}, name::Optional{AbstractString}, description::Optional{AbstractString}, end_date::Optional{DateTime})::Type{<:UpsertResult}Update an Experiment record. Setting the status back to IN_PROGRESS clears a previously recorded end_date.
Arguments
id::AbstractString: The id of the experiment to update.status_id::Optional{Integer}: The status of the experiment. Must be a validExperimentStatusvalue; passingnothingreturnsUnprocessable.name::Optional{AbstractString}: The new name of the experiment.description::Optional{AbstractString}: The new description of the experiment.end_date::Optional{DateTime}: The new end date of the experiment.
Returns
An UpsertResult. Updated if the record was successfully updated (or no changes were made), Duplicate if the record already exists, Unprocessable if the record violates a constraint, and Error if an error occurred while updating the record.
update_experiment(id::AbstractString, status::ExperimentStatus, name::Optional{AbstractString}, description::Optional{AbstractString}, end_date::Optional{DateTime})::Type{<:UpsertResult}Update an Experiment record.
Arguments
id::AbstractString: The id of the experiment to update.status::ExperimentStatus: The new status of the experiment.name::Optional{AbstractString}: The new name of the experiment.description::Optional{AbstractString}: The new description of the experiment.end_date::Optional{DateTime}: The new end date of the experiment.
Returns
An UpsertResult. Updated if the record was successfully updated (or no changes were made), Duplicate if the record already exists, Unprocessable if the record violates a constraint, and Error if an error occurred while updating the record.
update_experiment(client::Client, id::AbstractString; status_id=nothing, name=nothing, description=nothing, end_date=nothing)::NothingPatch an Experiment via PATCH /experiment/{id}. The server validates status_id on every call, so pass the current status (or use the ExperimentStatus-typed overload) when only the other fields change; a missing status fails with ClientError "INVALID_PAYLOAD". The remaining keywords left as nothing are left untouched server-side. Reopening (status_id == Integer(IN_PROGRESS) on a row that has an end_date) clears end_date automatically. Requires UpdatePermission on the owning project.
update_experiment(client::Client, id::AbstractString, status::ExperimentStatus; name=nothing, description=nothing, end_date=nothing)::NothingExperimentStatus-typed overload of update_experiment.
DearDiary.delete_experiment — Function
delete_experiment(id::AbstractString)::BoolDelete an Experiment record together with its Iteration and Resource records and its tag associations.
The delete is refused (returns false) while a ModelVersion is registered from one of the experiment's iterations or points at one of its artifacts.
Arguments
id::AbstractString: The id of the experiment to delete.
Returns
true if the record was successfully deleted, false otherwise.
delete_experiment(client::Client, id::AbstractString)::NothingDelete an Experiment (and its Iterations + Resources) via DELETE /experiment/{id}. Requires DeletePermission on the owning project.
The server refuses with 409 and code "CONFLICT" while a ModelVersion is registered from one of the experiment's iterations or points at one of its artifacts; delete those versions first.
Iterations
DearDiary.get_iteration — Function
get_iteration(id::AbstractString)::Optional{Iteration}Get an Iteration by id.
Arguments
id::AbstractString: The id of the iteration to query.
Returns
An Iteration object. If the record does not exist, return nothing.
get_iteration(client::Client, id::AbstractString)::Optional{Iteration}Fetch an Iteration via GET /iteration/{id}. Returns nothing when the server replies 404 and raises ClientError for other failures. Requires ReadPermission on the iteration's project.
DearDiary.get_iterations — Function
get_iterations(experiment_id::AbstractString)::Array{Iteration, 1}Get all Iteration for a given experiment.
Arguments
experiment_id::AbstractString: The id of the experiment to query.
Returns
An array of Iteration objects.
get_iterations(experiment_id::AbstractString, page::Pagination)::PaginatedResponse{Iteration}Get a page of Iteration records for an experiment, with total count populated.
Arguments
experiment_id::AbstractString: The id of the experiment to query.page::Pagination: The page bounds (limit + offset).
Returns
A PaginatedResponse of Iteration.
get_iterations(client::Client, experiment_id::AbstractString)::Array{Iteration,1}Returns the first page (default limit) of Iteration records under experiment_id, discarding the pagination envelope.
get_iterations(client::Client, experiment_id::AbstractString, page::Pagination)::PaginatedResponse{Iteration}Fetch a page of Iteration records under experiment_id via GET /iteration/experiment/{experiment_id}?limit=…&offset=….
DearDiary.get_child_iterations — Function
get_child_iterations(parent_id::AbstractString)::Array{Iteration, 1}Return the direct children of parent_id: iterations whose parent_iteration_id points at it, ordered by creation date ascending. Returns an empty array when no children exist.
Arguments
parent_id::AbstractString: The id of the parent iteration.
Returns
An array of child Iteration objects.
get_child_iterations(client::Client, parent_id::AbstractString)::Array{Iteration,1}Fetch the direct children of parent_id via GET /iteration/{parent_id}/children. Returns an empty array when no children exist. Requires ReadPermission on the iteration's project.
DearDiary.create_iteration — Function
create_iteration(experiment_id::AbstractString; parent_iteration_id=nothing)::NamedTuple{id::Optional{String},status::DataType}Create an Iteration.
When parent_iteration_id is supplied, the new row is a child run, used to model HPO trials, nested-CV folds, or distributed-worker fan-outs. The parent must already exist and must belong to the same experiment_id; cross-experiment lineage is rejected with Unprocessable.
Arguments
experiment_id::AbstractString: The id of the experiment to create the iteration for.parent_iteration_id::Optional{AbstractString}: When set, the id of the parent iteration.
Returns
- The created iteration ID, or
nothingon failure. - An
UpsertResult.
create_iteration(client::Client, experiment_id::AbstractString; parent_iteration_id=nothing)::IterationOpen a fresh Iteration under experiment_id via POST /iteration/experiment/{experiment_id} and fetch the freshly-created row so the caller can immediately use its id and created_date. The parent experiment must be IN_PROGRESS. Requires CreatePermission on the owning project.
When parent_iteration_id is supplied, the new row is registered as a child of the given iteration (HPO trial, distributed worker, nested CV fold). The parent must belong to the same experiment_id.
DearDiary.update_iteration — Function
update_iteration(id::AbstractString, notes::Optional{AbstractString}, end_date::Optional{DateTime}; status_id=nothing, error_message=nothing)::Type{<:UpsertResult}Update an Iteration record.
Once an iteration has been finalised (end_date is set), the row is locked: further updates return Unprocessable. The intended terminal-state flow is to pass end_date, status_id, and (when applicable) error_message together in a single call.
Arguments
id::AbstractString: The id of the iteration to update.notes::Optional{AbstractString}: The new notes for the iteration.end_date::Optional{DateTime}: The new end date for the iteration.status_id::Optional{Integer}: The newIterationStatusvalue. Must be one of the four valid integers (1..4) ornothing.error_message::Optional{AbstractString}: The captured exception text when the iteration ended in aFAILEDstate.
Returns
An UpsertResult.
update_iteration(id::AbstractString, notes::Optional{AbstractString}, end_date::Optional{DateTime}, status::IterationStatus; error_message=nothing)::Type{<:UpsertResult}IterationStatus-typed overload of update_iteration.
update_iteration(client::Client, id::AbstractString; notes=nothing, end_date=nothing, status=nothing, error_message=nothing)::NothingPatch an Iteration via PATCH /iteration/{id}. Any keyword left as nothing is left untouched server-side. Once an iteration has an end_date set, the server locks it: further updates fail with ClientError "INVALID_PAYLOAD". Requires UpdatePermission on the owning project.
status accepts an IterationStatus enum value; the integer is sent on the wire.
DearDiary.delete_iteration — Function
delete_iteration(id::AbstractString)::BoolDelete an Iteration record together with its Parameter and Metric records and its tag associations. Children whose parent_iteration_id points at this row have their reference set to NULL before the delete; they continue to exist as standalone iterations until explicitly deleted.
The delete is refused (returns false) while a ModelVersion is registered from the iteration; delete those versions first so the registry never points at a missing run.
Arguments
id::AbstractString: The id of the iteration to delete.
Returns
true if the record was successfully deleted, false otherwise.
delete_iteration(client::Client, id::AbstractString)::NothingDelete an Iteration (and its Parameters + Metrics) via DELETE /iteration/{id}. Child iterations survive with their parent reference cleared. Requires DeletePermission on the owning project.
The server refuses with 409 and code "CONFLICT" while a ModelVersion is registered from the iteration; delete those versions first.
DearDiary.with_iteration — Function
with_iteration(f::Function, experiment_id::AbstractString; parent_iteration_id=nothing, snapshot=parent_iteration_id |> isnothing)Open a fresh Iteration under experiment_id via create_iteration, pass it to f, and finalise the iteration's end_date and status_id regardless of whether the body returns normally or throws. On a clean return the iteration is marked SUCCEEDED; on an exception it is marked FAILED with the captured exception text in error_message, and the exception is rethrown so the caller still sees it.
By default the function calls snapshot_environment! on the new iteration right after creation, but only when it has no parent. Driver runs capture the env; child runs inherit it. Pass snapshot=true to force a per-child capture (each child gets its own snapshot, useful when workers run in different processes) or snapshot=false to skip entirely.
Arguments
f::Function: A unary function that receives the freshly-createdIteration.experiment_id::AbstractString: The id of theExperimentthat owns the iteration.parent_iteration_id::Optional{AbstractString}: When set, the new iteration is registered as a child of the given parent, useful for HPO sweeps and distributed-worker fan-outs.snapshot::Bool: Whether to callsnapshot_environment!after creation. Defaults totruefor driver iterations andfalsefor children.
Returns
Whatever f returns.
with_iteration(f::Function, client::Client, experiment_id::AbstractString; parent_iteration_id=nothing, snapshot=parent_iteration_id |> isnothing)Open a fresh Iteration under experiment_id, invoke f(iteration), and finalise the iteration regardless of whether the body returns normally or throws. On a clean return the iteration is marked SUCCEEDED; on an exception it is marked FAILED with the captured exception text in error_message, and the exception is rethrown so the caller still sees it.
By default the helper attaches an EnvironmentSnapshot to the new iteration immediately after creation, but only when it has no parent: driver runs capture the env, child runs inherit it. Pass snapshot=true to force a per-child capture or snapshot=false to skip entirely.
When parent_iteration_id is supplied, the new iteration is registered as a child of the given parent, useful for HPO sweeps and distributed-worker fan-outs.
Example
client = DearDiary.connect("http://127.0.0.1:9000"; username="default", password="default")
result = with_iteration(client, experiment_id) do iter
create_parameter(client, iter.id, "lr", 1e-3)
for epoch in 1:10
create_metric(client, iter.id, "loss", train_step!(model))
end
model
endTags
DearDiary.get_tag — Function
get_tag(id::AbstractString)::Optional{Tag}Get a Tag by id.
Arguments
id::AbstractString: The id of the tag to query.
Returns
A Tag object. If the record does not exist, return nothing.
get_tag(client::Client, id::AbstractString)::Optional{Tag}Fetch a Tag by id via GET /tag/{id}. Returns nothing when the server replies 404 and raises ClientError for other failures. Admin-only route.
The value-based local lookup (get_tag_by_value) has no REST counterpart; iterate the parent-scoped get_tags listings to discover a tag by its value.
DearDiary.get_tag_by_value — Function
get_tag_by_value(value::AbstractString)::Optional{Tag}Get a Tag by value. Distinct from get_tag because ids and values are both strings, so the two lookups cannot share a method told apart by argument type.
Arguments
value::AbstractString: The value of the tag to query.
Returns
A Tag object. If the record does not exist, return nothing.
DearDiary.get_tags — Function
get_tags(::Type{<:Project}, project_id::AbstractString)::Array{Tag, 1}Get all Tag for a given project.
Arguments
::Type{<:Project}: The project type.project_id::AbstractString: The id of the project to query.
Returns
An array of Tag objects.
get_tags(::Type{<:Experiment}, experiment_id::AbstractString)::Array{Tag, 1}Get all Tag for a given experiment.
Arguments
::Type{<:Experiment}: The experiment type.experiment_id::AbstractString: The id of the experiment to query.
Returns
An array of Tag objects.
get_tags(::Type{<:Iteration}, iteration_id::AbstractString)::Array{Tag, 1}Get all Tag for a given iteration.
Arguments
::Type{<:Iteration}: The iteration type.iteration_id::AbstractString: The id of the iteration to query.
Returns
An array of Tag objects.
get_tags(client::Client, ::Type{T}, parent_id::AbstractString)::Array{Tag,1} where {T<:Union{Project,Experiment,Iteration}}List every Tag attached to parent_id of kind T, via GET /tag/{kind}/{parent_id}. Requires ReadPermission on the owning project.
DearDiary.create_tag — Function
create_tag(value::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Create a Tag.
Arguments
value::AbstractString: The value of the tag.
Returns
- The created tag ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
DearDiary.add_tag — Function
add_tag(::Type{<:Project}, project_id::AbstractString, tag_value::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Add a tag to a project.
Arguments
::Type{<:Project}: The project type.project_id::AbstractString: The id of the project to add the tag to.tag_value::AbstractString: The value of the tag to add.
Returns
- The created project_tag association ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
add_tag(::Type{<:Experiment}, experiment_id::AbstractString, tag_value::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Add a tag to an experiment.
Arguments
::Type{<:Experiment}: The experiment type.experiment_id::AbstractString: The id of the experiment to add the tag to.tag_value::AbstractString: The value of the tag to add.
Returns
- The created experiment_tag association ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
add_tag(::Type{<:Iteration}, iteration_id::AbstractString, tag_value::AbstractString)::NamedTuple{id::Optional{String},status::DataType}Add a tag to an iteration.
Arguments
::Type{<:Iteration}: The iteration type.iteration_id::AbstractString: The id of the iteration to add the tag to.tag_value::AbstractString: The value of the tag to add.
Returns
- The created iteration_tag association ID. If an error occurs,
nothingis returned. - An
UpsertResult.Createdif the record was successfully created,Duplicateif the record already exists,Unprocessableif the record violates a constraint, andErrorif an error occurred while creating the record.
add_tag(client::Client, ::Type{T}, parent_id::AbstractString, value::AbstractString)::String where {T<:Union{Project,Experiment,Iteration}}Attach a tag value to parent_id of kind T, via POST /tag/{kind}/{parent_id}. The server upserts the underlying Tag row if it does not exist already. Returns the association id. Requires CreatePermission on the owning project; for iterations the parent must not be terminated.
The local standalone create_tag(value) has no REST counterpart; tags only exist attached to a parent.
DearDiary.delete_tag — Function
delete_tag(id::AbstractString)::BoolDelete a Tag record. Refused (returns false) while the tag is still attached to a project, experiment, or iteration, since the association rows reference it.
Arguments
id::AbstractString: The id of the tag to delete.
Returns
true if the record was successfully deleted, false otherwise.
delete_tag(client::Client, id::AbstractString)::NothingDelete a Tag via DELETE /tag/{id}. Admin-only. Only a tag attached to nothing can be removed: the REST API has no detach endpoint, so a tag still attached to a project, experiment, or iteration is refused and surfaces as ClientError "SERVER_ERROR".