diff --git a/.golangci.yml b/.golangci.yml index 3f7e458..ea36ea3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,15 +2,9 @@ linters: enable: - misspell - revive + - sloglint disable: - # Disable soon to deprecated[1] linters that lead to false - # positives when build tags disable certain files[2] - # 1: https://github.com/golangci/golangci-lint/issues/1841 - # 2: https://github.com/prometheus/node_exporter/issues/1545 - - deadcode - unused - - structcheck - - varcheck issues: exclude-rules: @@ -23,8 +17,6 @@ linters-settings: exclude-functions: # Used in HTTP handlers, any error is handled by the server itself. - (net/http.ResponseWriter).Write - # Never check for logger errors. - - (github.com/go-kit/log.Logger).Log revive: rules: # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter diff --git a/go.mod b/go.mod index 1181eaf..b641a34 100644 --- a/go.mod +++ b/go.mod @@ -1,37 +1,37 @@ module github.com/prometheus-community/smartctl_exporter -go 1.21 +go 1.22 require ( github.com/alecthomas/kingpin/v2 v2.4.0 - github.com/go-kit/log v0.2.1 - github.com/prometheus/client_golang v1.19.0 - github.com/prometheus/common v0.53.0 - github.com/prometheus/exporter-toolkit v0.11.0 + github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/common v0.60.0 + github.com/prometheus/exporter-toolkit v0.13.0 github.com/tidwall/gjson v1.17.1 ) require ( github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/jpillora/backoff v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/mdlayher/vsock v1.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.22.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 5944b51..19685fb 100644 --- a/go.sum +++ b/go.sum @@ -4,51 +4,52 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= +github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= -github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= -github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= -github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/exporter-toolkit v0.13.0 h1:lmA0Q+8IaXgmFRKw09RldZmZdnvu9wwcDLIXGmTPw1c= +github.com/prometheus/exporter-toolkit v0.13.0/go.mod h1:2uop99EZl80KdXhv/MxVI2181fMcwlsumFOqBecGkG0= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -57,31 +58,20 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/main.go b/main.go index 7f55518..35528b9 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ package main import ( + "log/slog" "net/http" "os" "strings" @@ -21,13 +22,11 @@ import ( "time" kingpin "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/prometheus/common/promlog" - "github.com/prometheus/common/promlog/flag" + "github.com/prometheus/common/promslog" + "github.com/prometheus/common/promslog/flag" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag" @@ -46,7 +45,7 @@ type SMARTctlManagerCollector struct { CollectPeriodDuration time.Duration Devices []Device - logger log.Logger + logger *slog.Logger mutex sync.Mutex } @@ -79,7 +78,7 @@ func (i *SMARTctlManagerCollector) Collect(ch chan<- prometheus.Metric) { func (i *SMARTctlManagerCollector) RescanForDevices() { for { time.Sleep(*smartctlRescanInterval) - level.Info(i.logger).Log("msg", "Rescanning for devices") + i.logger.Info("Rescanning for devices") devices := scanDevices(i.logger) i.mutex.Lock() i.Devices = devices @@ -114,7 +113,7 @@ var ( ) // scanDevices uses smartctl to gather the list of available devices. -func scanDevices(logger log.Logger) []Device { +func scanDevices(logger *slog.Logger) []Device { filter := newDeviceFilter(*smartctlDeviceExclude, *smartctlDeviceInclude) json := readSMARTctlDevices(logger) @@ -123,9 +122,9 @@ func scanDevices(logger log.Logger) []Device { for _, d := range scanDevices { deviceName := extractDiskName(strings.TrimSpace(d.Get("info_name").String())) if filter.ignored(deviceName) { - level.Info(logger).Log("msg", "Ignoring device", "name", deviceName) + logger.Info("Ignoring device", "name", deviceName) } else { - level.Info(logger).Log("msg", "Found device", "name", deviceName) + logger.Info("Found device", "name", deviceName) device := Device{ Name: d.Get("name").String(), Info_Name: deviceName, @@ -137,11 +136,11 @@ func scanDevices(logger log.Logger) []Device { return scanDeviceResult } -func filterDevices(logger log.Logger, devices []Device, filters []string) []Device { +func filterDevices(logger *slog.Logger, devices []Device, filters []string) []Device { var filtered []Device for _, d := range devices { for _, filter := range filters { - level.Debug(logger).Log("msg", "filterDevices", "device", d.Info_Name, "filter", filter) + logger.Debug("filterDevices", "device", d.Info_Name, "filter", filter) if strings.Contains(d.Info_Name, filter) { filtered = append(filtered, d) break @@ -157,23 +156,23 @@ func main() { ).Default("/metrics").String() toolkitFlags := webflag.AddFlags(kingpin.CommandLine, ":9633") - promlogConfig := &promlog.Config{} - flag.AddFlags(kingpin.CommandLine, promlogConfig) + promslogConfig := &promslog.Config{} + flag.AddFlags(kingpin.CommandLine, promslogConfig) kingpin.Version(version.Print("smartctl_exporter")) kingpin.HelpFlag.Short('h') kingpin.Parse() - logger := promlog.New(promlogConfig) + logger := promslog.New(promslogConfig) - level.Info(logger).Log("msg", "Starting smartctl_exporter", "version", version.Info()) - level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext()) + logger.Info("Starting smartctl_exporter", "version", version.Info()) + logger.Info("Build context", "build_context", version.BuildContext()) var devices []Device devices = scanDevices(logger) - level.Info(logger).Log("msg", "Number of devices found", "count", len(devices)) + logger.Info("Number of devices found", "count", len(devices)) if len(*smartctlDevices) > 0 { - level.Info(logger).Log("msg", "Devices specified", "devices", strings.Join(*smartctlDevices, ", ")) + logger.Info("Devices specified", "devices", strings.Join(*smartctlDevices, ", ")) devices = filterDevices(logger, devices, *smartctlDevices) - level.Info(logger).Log("msg", "Devices filtered", "count", len(devices)) + logger.Info("Devices filtered", "count", len(devices)) } collector := SMARTctlManagerCollector{ @@ -182,8 +181,8 @@ func main() { } if *smartctlRescanInterval >= 1*time.Second { - level.Info(logger).Log("msg", "Start background scan process") - level.Info(logger).Log("msg", "Rescanning for devices every", "rescanInterval", *smartctlRescanInterval) + logger.Info("Start background scan process") + logger.Info("Rescanning for devices every", "rescanInterval", *smartctlRescanInterval) go collector.RescanForDevices() } @@ -211,7 +210,7 @@ func main() { } landingPage, err := web.NewLandingPage(landingConfig) if err != nil { - level.Error(logger).Log("err", err) + logger.Error("error creating landing page", "err", err) os.Exit(1) } http.Handle("/", landingPage) @@ -219,7 +218,7 @@ func main() { srv := &http.Server{} if err := web.ListenAndServe(srv, toolkitFlags, logger); err != nil { - level.Error(logger).Log("err", err) + logger.Error("error running HTTP server", "err", err) os.Exit(1) } } diff --git a/readjson.go b/readjson.go index 234bc85..079abab 100644 --- a/readjson.go +++ b/readjson.go @@ -15,14 +15,13 @@ package main import ( "fmt" + "log/slog" "os" "os/exec" "strings" "sync" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/tidwall/gjson" ) @@ -49,40 +48,40 @@ func parseJSON(data string) gjson.Result { } // Reading fake smartctl json -func readFakeSMARTctl(logger log.Logger, device Device) gjson.Result { +func readFakeSMARTctl(logger *slog.Logger, device Device) gjson.Result { s := strings.Split(device.Name, "/") filename := fmt.Sprintf("debug/%s.json", s[len(s)-1]) - level.Debug(logger).Log("msg", "Read fake S.M.A.R.T. data from json", "filename", filename) + logger.Debug("Read fake S.M.A.R.T. data from json", "filename", filename) jsonFile, err := os.ReadFile(filename) if err != nil { - level.Error(logger).Log("msg", "Fake S.M.A.R.T. data reading error", "err", err) + logger.Error("Fake S.M.A.R.T. data reading error", "err", err) return parseJSON("{}") } return parseJSON(string(jsonFile)) } // Get json from smartctl and parse it -func readSMARTctl(logger log.Logger, device Device) (gjson.Result, bool) { +func readSMARTctl(logger *slog.Logger, device Device) (gjson.Result, bool) { start := time.Now() out, err := exec.Command(*smartctlPath, "--json", "--info", "--health", "--attributes", "--tolerance=verypermissive", "--nocheck=standby", "--format=brief", "--log=error", "--device="+device.Type, device.Name).Output() if err != nil { - level.Warn(logger).Log("msg", "S.M.A.R.T. output reading", "err", err, "device", device.Info_Name) + logger.Warn("S.M.A.R.T. output reading", "err", err, "device", device.Info_Name) } json := parseJSON(string(out)) rcOk := resultCodeIsOk(logger, device, json.Get("smartctl.exit_status").Int()) jsonOk := jsonIsOk(logger, json) - level.Debug(logger).Log("msg", "Collected S.M.A.R.T. json data", "device", device.Info_Name, "duration", time.Since(start)) + logger.Debug("Collected S.M.A.R.T. json data", "device", device.Info_Name, "duration", time.Since(start)) return json, rcOk && jsonOk } -func readSMARTctlDevices(logger log.Logger) gjson.Result { - level.Debug(logger).Log("msg", "Scanning for devices") +func readSMARTctlDevices(logger *slog.Logger) gjson.Result { + logger.Debug("Scanning for devices") out, err := exec.Command(*smartctlPath, "--json", "--scan").Output() if exiterr, ok := err.(*exec.ExitError); ok { - level.Debug(logger).Log("msg", "Exit Status", "exit_code", exiterr.ExitCode()) + logger.Debug("Exit Status", "exit_code", exiterr.ExitCode()) // The smartctl command returns 2 if devices are sleeping, ignore this error. if exiterr.ExitCode() != 2 { - level.Warn(logger).Log("msg", "S.M.A.R.T. output reading error", "err", err) + logger.Warn("S.M.A.R.T. output reading error", "err", err) return gjson.Result{} } } @@ -90,7 +89,7 @@ func readSMARTctlDevices(logger log.Logger) gjson.Result { } // Select json source and parse -func readData(logger log.Logger, device Device) gjson.Result { +func readData(logger *slog.Logger, device Device) gjson.Result { if *smartctlFakeData { return readFakeSMARTctl(logger, device) } @@ -102,7 +101,7 @@ func readData(logger log.Logger, device Device) gjson.Result { jsonCache.Store(device, JSONCache{JSON: json, LastCollect: time.Now()}) j, found := jsonCache.Load(device) if !found { - level.Warn(logger).Log("msg", "device not found", "device", device.Info_Name) + logger.Warn("device not found", "device", device.Info_Name) } return j.(JSONCache).JSON } @@ -112,48 +111,48 @@ func readData(logger log.Logger, device Device) gjson.Result { } // Parse smartctl return code -func resultCodeIsOk(logger log.Logger, device Device, SMARTCtlResult int64) bool { +func resultCodeIsOk(logger *slog.Logger, device Device, SMARTCtlResult int64) bool { result := true if SMARTCtlResult > 0 { b := SMARTCtlResult if (b & 1) != 0 { - level.Error(logger).Log("msg", "Command line did not parse", "device", device.Info_Name) + logger.Error("Command line did not parse", "device", device.Info_Name) result = false } if (b & (1 << 1)) != 0 { - level.Error(logger).Log("msg", "Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode", "device", device.Info_Name) + logger.Error("Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode", "device", device.Info_Name) result = false } if (b & (1 << 2)) != 0 { - level.Warn(logger).Log("msg", "Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure", "device", device.Info_Name) + logger.Warn("Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure", "device", device.Info_Name) } if (b & (1 << 3)) != 0 { - level.Warn(logger).Log("msg", "SMART status check returned 'DISK FAILING'", "device", device.Info_Name) + logger.Warn("SMART status check returned 'DISK FAILING'", "device", device.Info_Name) } if (b & (1 << 4)) != 0 { - level.Warn(logger).Log("msg", "We found prefail Attributes <= threshold", "device", device.Info_Name) + logger.Warn("We found prefail Attributes <= threshold", "device", device.Info_Name) } if (b & (1 << 5)) != 0 { - level.Warn(logger).Log("msg", "SMART status check returned 'DISK OK' but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past", "device", device.Info_Name) + logger.Warn("SMART status check returned 'DISK OK' but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past", "device", device.Info_Name) } if (b & (1 << 6)) != 0 { - level.Warn(logger).Log("msg", "The device error log contains records of errors", "device", device.Info_Name) + logger.Warn("The device error log contains records of errors", "device", device.Info_Name) } if (b & (1 << 7)) != 0 { - level.Warn(logger).Log("msg", "The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored", "device", device.Info_Name) + logger.Warn("The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored", "device", device.Info_Name) } } return result } // Check json -func jsonIsOk(logger log.Logger, json gjson.Result) bool { +func jsonIsOk(logger *slog.Logger, json gjson.Result) bool { messages := json.Get("smartctl.messages") // logger.Debug(messages.String()) if messages.Exists() { for _, message := range messages.Array() { if message.Get("severity").String() == "error" { - level.Error(logger).Log("msg", message.Get("string").String()) + logger.Error(message.Get("string").String()) return false } } diff --git a/smartctl.go b/smartctl.go index 0fa96db..472cd01 100644 --- a/smartctl.go +++ b/smartctl.go @@ -15,11 +15,10 @@ package main import ( "fmt" + "log/slog" "regexp" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/tidwall/gjson" ) @@ -39,7 +38,7 @@ type SMARTDevice struct { type SMARTctl struct { ch chan<- prometheus.Metric json gjson.Result - logger log.Logger + logger *slog.Logger device SMARTDevice } @@ -68,7 +67,7 @@ func extractDiskName(input string) string { } // NewSMARTctl is smartctl constructor -func NewSMARTctl(logger log.Logger, json gjson.Result, ch chan<- prometheus.Metric) SMARTctl { +func NewSMARTctl(logger *slog.Logger, json gjson.Result, ch chan<- prometheus.Metric) SMARTctl { var model_name string if obj := json.Get("model_name"); obj.Exists() { model_name = obj.String() @@ -97,7 +96,7 @@ func NewSMARTctl(logger log.Logger, json gjson.Result, ch chan<- prometheus.Metr // Collect metrics func (smart *SMARTctl) Collect() { - level.Debug(smart.logger).Log("msg", "Collecting metrics from", "device", smart.device.device, "family", smart.device.family, "model", smart.device.model) + smart.logger.Debug("Collecting metrics from", "device", smart.device.device, "family", smart.device.family, "model", smart.device.model) smart.mineExitStatus() smart.mineDevice() smart.mineCapacity()