# How to overwrite logging output for custom string types

**URL:** <https://discourse.julialang.org/t/how-to-overwrite-logging-output-for-custom-string-types/26865>\
**Category:** General Usage\
**Created:** [July 26, 2019, 7:45pm UTC](https://discourse.julialang.org/t/how-to-overwrite-logging-output-for-custom-string-types/26865 "2019-07-26T19:45:35Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [July 26, 2019, 7:45pm UTC](https://discourse.julialang.org/t/how-to-overwrite-logging-output-for-custom-string-types/26865/1 "2019-07-26T19:45:36Z")

</div>

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:

```julia
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:

```julia
secret_pass = ******
[ Info: 12345
******

```

What should be overwritten in order to affect logging output?

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [July 26, 2019, 10:15pm UTC](https://discourse.julialang.org/t/how-to-overwrite-logging-output-for-custom-string-types/26865/2 "2019-07-26T22:15:16Z")

</div>

`string`, apparently:

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

julia> @info secret_pass
[ Info: ***

```

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [July 27, 2019, 5:30am UTC](https://discourse.julialang.org/t/how-to-overwrite-logging-output-for-custom-string-types/26865/3 "2019-07-27T05:30:06Z")

</div>

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.

```julia
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:

```julia
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)

```
