Skip to content

Commit 5e6cde0

Browse files
authored
Adding MLFlow new methods, Julia LTS checks and tests (#28)
* up logbatch function and creating a new type for parameters * adding julia 1.6 in the CI pipeline * adding an IOBuffer test
1 parent 6e13f32 commit 5e6cde0

File tree

8 files changed

+168
-18
lines changed

8 files changed

+168
-18
lines changed

.github/workflows/CI.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ jobs:
2525
fail-fast: false
2626
matrix:
2727
version:
28-
# - '1.0'
29-
# - '1.7'
30-
- 'nightly'
28+
- '1.6'
29+
- '1'
3130
os:
3231
- ubuntu-latest
3332
arch:

docs/src/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ deleterun
4141
searchruns
4242
logparam
4343
logmetric
44+
logbatch
4445
logartifact
4546
listartifacts
4647
```

src/MLFlowClient.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export
3030
MLFlowRunStatus,
3131
MLFlowRunInfo,
3232
MLFlowRunDataMetric,
33+
MLFlowRunDataParam,
3334
MLFlowRunData,
3435
MLFlowRun,
3536
get_info,
@@ -56,6 +57,7 @@ export
5657
getexperiment,
5758
getorcreateexperiment,
5859
deleteexperiment,
60+
restoreexperiment,
5961
searchexperiments
6062

6163
include("runs.jl")
@@ -68,6 +70,7 @@ export
6870

6971
include("loggers.jl")
7072
export
73+
logbatch,
7174
logparam,
7275
logmetric,
7376
logartifact,

src/experiments.jl

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Deletes an MLFlow experiment.
121121
function deleteexperiment(mlf::MLFlow, experiment_id::Integer)
122122
endpoint = "experiments/delete"
123123
try
124-
result = mlfpost(mlf, endpoint; experiment_id=experiment_id)
124+
mlfpost(mlf, endpoint; experiment_id=experiment_id)
125125
catch e
126126
if isa(e, HTTP.ExceptionRequest.StatusError) && e.status == 404
127127
# experiment already deleted
@@ -131,6 +131,7 @@ function deleteexperiment(mlf::MLFlow, experiment_id::Integer)
131131
end
132132
true
133133
end
134+
134135
"""
135136
deleteexperiment(mlf::MLFlow, experiment::MLFlowExperiment)
136137
@@ -146,6 +147,36 @@ Dispatches to `deleteexperiment(mlf::MLFlow, experiment_id::Integer)`.
146147
deleteexperiment(mlf::MLFlow, experiment::MLFlowExperiment) =
147148
deleteexperiment(mlf, experiment.experiment_id)
148149

150+
"""
151+
restoreexperiment(mlf::MLFlow, experiment_id::Integer)
152+
153+
Restores a deleted MLFlow experiment.
154+
155+
# Arguments
156+
- `mlf`: [`MLFlow`](@ref) configuration.
157+
- `experiment_id`: experiment identifier.
158+
159+
# Returns
160+
161+
`true` if successful. Otherwise, raises exception.
162+
"""
163+
function restoreexperiment(mlf::MLFlow, experiment_id::Integer)
164+
endpoint = "experiments/restore"
165+
try
166+
mlfpost(mlf, endpoint; experiment_id=experiment_id)
167+
catch e
168+
if isa(e, HTTP.ExceptionRequest.StatusError) && e.status == 404
169+
# experiment already restored
170+
return true
171+
end
172+
throw(e)
173+
end
174+
true
175+
end
176+
177+
restoreexperiment(mlf::MLFlow, experiment::MLFlowExperiment) =
178+
restoreexperiment(mlf, experiment.experiment_id)
179+
149180
"""
150181
searchexperiments(mlf::MLFlow)
151182

src/loggers.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function logparam(mlf::MLFlow, run::Union{String,MLFlowRun,MLFlowRunInfo}, kv)
2626
end
2727
end
2828

29+
2930
"""
3031
logmetric(mlf::MLFlow, run, key, value::T; timestamp, step) where T<:Real
3132
logmetric(mlf::MLFlow, run, key, values::AbstractArray{T}; timestamp, step) where T<:Real
@@ -194,3 +195,37 @@ listartifacts(mlf::MLFlow, run::MLFlowRun; kwargs...) =
194195
listartifacts(mlf, run.info.run_id; kwargs...)
195196
listartifacts(mlf::MLFlow, run_info::MLFlowRunInfo; kwargs...) =
196197
listartifacts(mlf, run_info.run_id; kwargs...)
198+
199+
"""
200+
logbatch(mlf::MLFlow, run_id::String, metrics, params, tags)
201+
202+
Logs a batch of metrics, parameters and tags to an experiment run.
203+
204+
# Arguments
205+
- `mlf::MLFlow`: [`MLFlow`](@ref) onfiguration.
206+
- `run_id::String`: ID of the run to log to.
207+
- `metrics`: a vector of [`MLFlowRunDataMetric`](@ref) or a vector of
208+
NamedTuples of `(name, value, timestamp)`.
209+
- `params`: a vector of [`MLFlowRunDataParam`](@ref) or a vector of NamedTuples
210+
of `(name, value)`.
211+
- `tags`: a vector of strings.
212+
"""
213+
logbatch(mlf::MLFlow, run_id::String; tags=String[], metrics=Any[],
214+
params=Any[]) = logbatch(mlf, run_id, tags, metrics, params)
215+
function logbatch(mlf::MLFlow, run_id::String,
216+
tags::Union{AbstractVector{<:String}, AbstractVector{Any}},
217+
metrics::Union{AbstractVector{<:MLFlowRunDataMetric}, AbstractVector{Any}},
218+
params::Union{AbstractVector{<:MLFlowRunDataParam}, AbstractVector{Any}})
219+
endpoint = "runs/log-batch"
220+
mlfpost(mlf, endpoint;
221+
run_id=run_id, metrics=metrics, params=params, tags=tags)
222+
end
223+
function logbatch(mlf::MLFlow, run_id::String,
224+
tags::Union{AbstractVector{<:String}, AbstractVector{Any}},
225+
metrics::Union{AbstractVector{<:AbstractDict}, AbstractVector{Any}},
226+
params::Union{AbstractVector{<:AbstractDict}, AbstractVector{Any}})
227+
endpoint = "runs/log-batch"
228+
mlfpost(mlf, endpoint; run_id=run_id,
229+
metrics=MLFlowRunDataMetric.(metrics),
230+
params=MLFlowRunDataParam.(params), tags=tags)
231+
end

src/types/runs.jl

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,39 @@ function MLFlowRunDataMetric(d::Dict{String,Any})
114114
end
115115
Base.show(io::IO, t::MLFlowRunDataMetric) = show(io, ShowCase(t, new_lines=true))
116116

117+
"""
118+
MLFlowRunDataParam
119+
120+
Represents a parameter.
121+
122+
# Fields
123+
- `key::String`: parameter identifier.
124+
- `value::String`: parameter value.
125+
126+
# Constructors
127+
- `MLFlowRunDataParam(d::Dict{String,String})`
128+
129+
"""
130+
131+
struct MLFlowRunDataParam
132+
key::String
133+
value::String
134+
end
135+
function MLFlowRunDataParam(d::Dict{String,String})
136+
key = d["key"]
137+
value = d["value"]
138+
MLFlowRunDataParam(key, value)
139+
end
140+
Base.show(io::IO, t::MLFlowRunDataParam) = show(io, ShowCase(t, new_lines=true))
141+
117142
"""
118143
MLFlowRunData
119144
120145
Represents run data.
121146
122147
# Fields
123148
- `metrics::Dict{String,MLFlowRunDataMetric}`: run metrics.
124-
- `params::Dict{String,String}`: run parameters.
149+
- `params::Dict{String,MLFlowRunDataParam}`: run parameters.
125150
- `tags`: list of run tags.
126151
127152
# Constructors
@@ -131,24 +156,23 @@ Represents run data.
131156
"""
132157
struct MLFlowRunData
133158
metrics::Dict{String,MLFlowRunDataMetric}
134-
params::Union{Dict{String,String},Missing}
159+
params::Union{Dict{String,MLFlowRunDataParam},Missing}
135160
tags
136161
end
137162
function MLFlowRunData(data::Dict{String,Any})
138163
metrics = Dict{String,MLFlowRunDataMetric}()
139164
if haskey(data, "metrics")
140165
for metric in data["metrics"]
141-
v = MLFlowRunDataMetric(metric)
142-
metrics[v.key] = v
166+
new_metric = MLFlowRunDataMetric(metric)
167+
metrics[new_metric.key] = new_metric
143168
end
144169
end
170+
params = Dict{String,MLFlowRunDataParam}()
145171
if haskey(data, "params")
146-
params = Dict{String,String}()
147-
for p in data["params"]
148-
params[p["key"]] = p["value"]
172+
for param in data["params"]
173+
new_param = MLFlowRunDataParam(param["key"], param["value"])
174+
params[new_param.key] = new_param
149175
end
150-
else
151-
params = Dict{String,String}()
152176
end
153177
tags = haskey(data, "tags") ? data["tags"] : missing
154178
MLFlowRunData(metrics, params, tags)

test/test_experiments.jl

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
deleteexperiment(mlf, exp)
77
end
88

9-
@testset verbose=true "getexperiment" begin
9+
@testset verbose = true "getexperiment" begin
1010
@ensuremlf
1111
exp = createexperiment(mlf)
1212
experiment = getexperiment(mlf, exp.experiment_id)
@@ -45,13 +45,28 @@ end
4545
@testset "deleteexperiment" begin
4646
@ensuremlf
4747
exp = createexperiment(mlf)
48+
deleteexperiment(mlf, exp)
49+
50+
experiments = searchexperiments(mlf)
51+
@test length(experiments) == 1 # 1 for the default experiment
52+
end
4853

49-
@test deleteexperiment(mlf, exp)
50-
# deleting again to test if the experiment is already deleted
51-
@test deleteexperiment(mlf, exp)
54+
@testset "restoreexperiment" begin
55+
@ensuremlf
56+
exp = createexperiment(mlf)
57+
deleteexperiment(mlf, exp)
58+
59+
experiments = searchexperiments(mlf)
60+
@test length(experiments) == 1 # 1 for the default experiment
61+
62+
restoreexperiment(mlf, exp)
63+
experiments = searchexperiments(mlf)
64+
@test length(experiments) == 2 # the restored experiment and the default one
65+
66+
deleteexperiment(mlf, exp)
5267
end
5368

54-
@testset verbose=true "searchexperiments" begin
69+
@testset verbose = true "searchexperiments" begin
5570
@ensuremlf
5671
n_experiments = 3
5772
for i in 2:n_experiments

test/test_loggers.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,55 @@ end
111111
@test isfile(artifact)
112112
end
113113

114+
@testset "logartifact_using_IOBuffer" begin
115+
io = IOBuffer()
116+
write(io, "testing IOBuffer")
117+
seekstart(io)
118+
artifact = logartifact(mlf, r, tmpfile, io)
119+
@test isfile(artifact)
120+
end
121+
114122
@testset "logartifact_error" begin
115123
@test_broken logartifact(mlf, r, "/etc/shadow")
116124
end
117125

118126
deleteexperiment(mlf, e)
119127
end
120128

129+
@testset verbose=true "logbatch" begin
130+
@ensuremlf
131+
expname = "logbatch-$(UUIDs.uuid4())"
132+
e = getorcreateexperiment(mlf, expname)
133+
runname = "run-$(UUIDs.uuid4())"
134+
r = createrun(mlf, e.experiment_id)
135+
136+
@testset "logbatch_by_types" begin
137+
param_array = [MLFlowRunDataParam("test_param_type", "test")]
138+
metric_array = [MLFlowRunDataMetric("test_metric", 5, 3, 1)]
139+
logbatch(mlf, r.info.run_id; params=param_array, metrics=metric_array)
140+
141+
retrieved_run = searchruns(mlf, e;
142+
filter_params=Dict("test_param_type" => "test"))
143+
@test length(retrieved_run) == 1
144+
@test retrieved_run[1].info.run_id == r.info.run_id
145+
end
146+
147+
@testset "logbatch_by_dicts" begin
148+
param_dict_array = [Dict("key"=>"test_param_dict", "value"=>"test")]
149+
metric_dict_array = [
150+
Dict("key"=>"test_metric", "value"=>5, "step"=>3, "timestamp"=>1)]
151+
logbatch(mlf, r.info.run_id;
152+
params=param_dict_array, metrics=metric_dict_array)
153+
154+
retrieved_run = searchruns(mlf, e;
155+
filter_params=Dict("test_param_dict" => "test"))
156+
@test length(retrieved_run) == 1
157+
@test retrieved_run[1].info.run_id == r.info.run_id
158+
end
159+
160+
deleteexperiment(mlf, e)
161+
end
162+
121163
@testset verbose=true "listartifacts" begin
122164
@ensuremlf
123165
expname = "listartifacts-$(UUIDs.uuid4())"

0 commit comments

Comments
 (0)