How to overwrite logging output for custom string types

I’ve been playing with creating a custom Password string type which would be securely logged and printed in obfuscated form.

I came up with:

struct Password <: AbstractString
  contents::String 
end

Base.show(io::IO, p::Password) = print(io, "*******")
Base.print(p::Password) = print("******")

Base.iterate(p::Password) = iterate(p.contents)
Base.iterate(p::Password, i::Int) = iterate(p.contents, i)
Base.ncodeunits(p::Password) = ncodeunits(p.contents)
Base.isvalid(p::Password, i::Int) = isvalid(p.contents, i)

secret_pass = Password("12345")

@show secret_pass
@info secret_pass
print(secret_pass)

Works fine with the exception of @info. Output here:

secret_pass = ******
[ Info: 12345
******

What should be overwritten in order to affect logging output?

string, apparently:

julia> Base.string(p::Password) = "***"

julia> @info secret_pass
[ Info: ***
1 Like

Thank you.

Interesting, I would’ve expected logging to rely on the show or print family of functions. Also, it looks like println does not use print either as it needs to be explicitly overwritten, which is surprising.
Finally, I was under the impression that string concatenation uses string but it looks I was wrong.

struct Password <: AbstractString
  contents::String
end

Base.show(io::IO, p::Password) = print(io, "******")
Base.print(p::Password) = print("******")
Base.println(p::Password) = print("******\n")
Base.string(p::Password) = "******"

Base.iterate(p::Password) = iterate(p.contents)
Base.iterate(p::Password, i::Int) = iterate(p.contents, i)
Base.ncodeunits(p::Password) = ncodeunits(p.contents)
Base.isvalid(p::Password, i::Int) = isvalid(p.contents, i)

secret_pass = Password("12345")

@show secret_pass
@warn secret_pass
@info secret_pass
println(secret_pass)
dump(secret_pass)
println("SELECT * FROM USERS WHERE username = 'foo' AND password = " * secret_pass)
println("SELECT * FROM USERS WHERE username = 'foo' AND password = MD5($secret_pass)")

Output:

secret_pass = ******
┌ Warning: ******
└ @ Main ~/Dropbox/Projects/PasswordType.jl:20
[ Info: ******
******
Password
  contents: String "12345"
SELECT * FROM USERS WHERE username = 'foo' AND password = 12345
SELECT * FROM USERS WHERE username = 'foo' AND password = MD5(12345)