From 6ba9390ce34fae34dc6c4736970007400b800f99 Mon Sep 17 00:00:00 2001 From: Excavator Bot <33266368+svc-excavator-bot@users.noreply.github.com> Date: Wed, 16 Jun 2021 23:30:36 +0100 Subject: [PATCH] Excavator: Manage go module dependencies (#33) --- go.mod | 2 +- go.sum | 18 +- .../v2/conjure-go-client/httpclient/client.go | 14 +- .../v2/conjure-go-client/httpclient/config.go | 10 +- .../httpclient/internal/request_retrier.go | 94 +++---- .../httpclient/internal/retry.go | 15 +- .../conjure-go-client/httpclient/metrics.go | 81 ++++-- .../palantir/witchcraft-go-logging/LICENSE | 201 +++++++++++++++ .../internal/gopath/gopath.go | 30 +++ .../wlog/common_fields.go | 25 ++ .../witchcraft-go-logging/wlog/context.go | 33 +++ .../wlog/internal/context.go | 38 +++ .../wlog/internal/default_logger.go | 33 +++ .../witchcraft-go-logging/wlog/levels.go | 52 ++++ .../witchcraft-go-logging/wlog/logentry.go | 101 ++++++++ .../wlog/logentry_map.go | 239 ++++++++++++++++++ .../wlog/logger_provider.go | 24 ++ .../wlog/logger_provider_default.go | 25 ++ .../wlog/logger_provider_jsonmarshal.go | 99 ++++++++ .../wlog/logger_provider_noop.go | 60 +++++ .../wlog/logger_provider_warnonce.go | 61 +++++ .../witchcraft-go-logging/wlog/params.go | 72 ++++++ .../wlog/svclog/svc1log/context.go | 93 +++++++ .../wlog/svclog/svc1log/default.go | 107 ++++++++ .../wlog/svclog/svc1log/logger.go | 60 +++++ .../wlog/svclog/svc1log/logger_default.go | 94 +++++++ .../wlog/svclog/svc1log/logger_wrapped.go | 44 ++++ .../wlog/svclog/svc1log/params.go | 224 ++++++++++++++++ vendor/modules.txt | 7 +- 29 files changed, 1852 insertions(+), 104 deletions(-) create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/LICENSE create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/internal/gopath/gopath.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/common_fields.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/context.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/context.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/default_logger.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/levels.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry_map.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_default.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_jsonmarshal.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_noop.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_warnonce.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/params.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/context.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/default.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_default.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_wrapped.go create mode 100644 vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/params.go diff --git a/go.mod b/go.mod index bca9f8c7..efb67e17 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fatih/color v1.10.0 // indirect github.com/mattn/go-runewidth v0.0.10 // indirect github.com/nmiyake/pkg/errorstringer v1.0.2 // indirect - github.com/palantir/conjure-go-runtime/v2 v2.13.1 + github.com/palantir/conjure-go-runtime/v2 v2.14.0 github.com/palantir/go-metrics v1.1.1 // indirect github.com/palantir/goastwriter v0.1.0 github.com/palantir/godel/v2 v2.39.0 diff --git a/go.sum b/go.sum index 4b14bbf3..8797aef2 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,7 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -197,8 +198,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/palantir/conjure-go-runtime/v2 v2.2.0/go.mod h1:k4+u7YJwBAO6Kk7SGvFCQR7vrkVW8vgQxO8rPZGuS5g= -github.com/palantir/conjure-go-runtime/v2 v2.13.1 h1:dr1yQMwq4LCj6GhpfPxwf4OVt8+FpK/+gsUpThsXe0Q= -github.com/palantir/conjure-go-runtime/v2 v2.13.1/go.mod h1:c36GPPKT6mk9ZpO54DtZJCqTWHBXLDsBWYmldTvd+i8= +github.com/palantir/conjure-go-runtime/v2 v2.14.0 h1:NL9fXq7tHhPR1nfqKFxTsJ10H1j786cLychfaAHVw7s= +github.com/palantir/conjure-go-runtime/v2 v2.14.0/go.mod h1:c36GPPKT6mk9ZpO54DtZJCqTWHBXLDsBWYmldTvd+i8= github.com/palantir/distgo/pkg/git v1.0.0/go.mod h1:eXrr3SOmf/sWTYmtiubYVxSaVegTlMGgRgBUFMFFedw= github.com/palantir/go-metrics v1.1.0/go.mod h1:fRkuipBnsI4nD8Vd9UNcrUJvD8Y0wOJMSbicygcBrGs= github.com/palantir/go-metrics v1.1.1 h1:YL/UmptBjrC6iSCTVr7vfuIcjL0M359Da3/gBGNny10= @@ -216,6 +217,7 @@ github.com/palantir/pkg/bytesbuffers v1.0.1/go.mod h1:tmmrI9egWT9g6oBhcO3bsd+R5H github.com/palantir/pkg/cobracli v1.0.1 h1:RLAL+bWRcFVqX1XHDQZp6V2vZYN483U0HE9dhp2W+WQ= github.com/palantir/pkg/cobracli v1.0.1/go.mod h1:UfYLriXzhyx7a3r+3UTD+kbX+xASjr9kSK05fC85NyI= github.com/palantir/pkg/datetime v1.0.0/go.mod h1:s01MDVkY8pZEP+sbAIbXxiAsS+mPLHla3cFnQ2pk//g= +github.com/palantir/pkg/datetime v1.0.1 h1:jxJmpTZYrb0mzD8vD0ct0ii7iClWvgzS8Wbct17IDso= github.com/palantir/pkg/datetime v1.0.1/go.mod h1:Xx0XxVNJKPZRPw4xkNJ2qLNTLqGFu5QW6rAWeuoATBs= github.com/palantir/pkg/gittest v1.0.0/go.mod h1:M49S4TsX5sh7lYJmOF+pFzcB4fJNOylzN8tOdpSq958= github.com/palantir/pkg/gittest v1.0.1 h1:SMGj38NLGzEpW1LFfGAitWprywHorJTmfOpJS/9kv/Y= @@ -243,8 +245,10 @@ github.com/palantir/pkg/safejson v1.0.0/go.mod h1:lrqgYn4dju1TbU+pf3gEQtzAbQtaGr github.com/palantir/pkg/safejson v1.0.1 h1:VfpUJrdOnRm2m2ZBHXuVkdGbZd+B0ZrH8FpPxrPtMcc= github.com/palantir/pkg/safejson v1.0.1/go.mod h1:jZEXk2DnsOJCv3zgXq+GvMZvZOW8sw5FP8NG4IfTxD8= github.com/palantir/pkg/safelong v1.0.0/go.mod h1:2Pabf6SbeE2kerW1RyPGREZroNIQ9HvXKxCux0N5C3k= +github.com/palantir/pkg/safelong v1.0.1 h1:l5IDwT1aAQ1FeyMG77kPnsEUb0z5bQXYYXVTTNJpP2E= github.com/palantir/pkg/safelong v1.0.1/go.mod h1:+uJuPdYul/jhsplszUwPu+jlc4E7Z4ZMNCuIXbMoyR8= github.com/palantir/pkg/safeyaml v1.0.0/go.mod h1:g0GfNcalrnCZbwyZbW0OBmtHdjLXK7dG1oEk/ew+cB8= +github.com/palantir/pkg/safeyaml v1.0.1 h1:4cSUj9Ttnwydq4vxB8NSxe+qhquBYYtMuJbw6EuSZpQ= github.com/palantir/pkg/safeyaml v1.0.1/go.mod h1:rwADKpvXsYupKvXJg4pOuPrwK8F4Ki95VIq6lHjUqyA= github.com/palantir/pkg/signals v1.0.1/go.mod h1:L5/ZeqXa2QjdxpjqcMQ4LtZL3xCp1FMEhGjMHyLDb2g= github.com/palantir/pkg/specdir v1.0.1 h1:h3FxhAYZHUAuvZXF5O40pyhjKjm4JlcHYRogIVNw3Ew= @@ -252,6 +256,7 @@ github.com/palantir/pkg/specdir v1.0.1/go.mod h1:RJN42E0F1s4wHrNuXoT0cG4erUigMs0 github.com/palantir/pkg/tlsconfig v1.0.0/go.mod h1:pyDZXpSYm5J6r/4Fm6mjDV25Oe1aMsrgTjkCccKt8MM= github.com/palantir/pkg/tlsconfig v1.1.0 h1:m4vn2v64qEjQ9clmEwa1lrZopR5F+gBbXjRA19JIqKo= github.com/palantir/pkg/tlsconfig v1.1.0/go.mod h1:296vFNnUdrZV3aFtufP9VFXMO4zVnjaMgnI3vt5l5ek= +github.com/palantir/pkg/transform v1.0.0 h1:21MzkUg9fQgIdadTYMM1Z1qrml2MVdpNY5ai27G15LM= github.com/palantir/pkg/transform v1.0.0/go.mod h1:YH2PQUzswoDayk4rTvKt6B+NcnUJgZRNr9MEqfAMCo0= github.com/palantir/pkg/uuid v1.0.0/go.mod h1:yCHOTYHJD/zKB1c8sJ2IhIGvPGnYYcp0FgGTnbr5jiM= github.com/palantir/pkg/uuid v1.0.1 h1:wcBLI2wA9IyCgE5o7z8jkfct74BHhC5iD8FNuqp8ZHc= @@ -264,6 +269,7 @@ github.com/palantir/witchcraft-go-error v1.5.0/go.mod h1:QMolXxoxfg2Pd8KWyYAPNJh github.com/palantir/witchcraft-go-health v1.6.0/go.mod h1:oOIMYzOgTJci1XwvmUTrxe4YAY1CmSprbeR6QdY+5w0= github.com/palantir/witchcraft-go-logging v1.5.2/go.mod h1:x2wqelmEPV2sqOgxnYpx7em44I2nzWuovl7d7cMv+pM= github.com/palantir/witchcraft-go-logging v1.9.0/go.mod h1:6hkyOVxxkoSOVSsL+ZoBVQiFzRSFthlnn47xFOnm6+w= +github.com/palantir/witchcraft-go-logging v1.14.0 h1:T5P1I3QZOygcwcHK09a1fNQ/sTmXJFnT0/yHkX2xWhw= github.com/palantir/witchcraft-go-logging v1.14.0/go.mod h1:ldlbj6ihGeZBgGFVLF2lCsg4Ka2pkLYt38UoUicXDZ0= github.com/palantir/witchcraft-go-params v1.1.0/go.mod h1:HH+l5b0binfqBJ21qVvQVOJp6s2/I6ld0NEWnaEgWvI= github.com/palantir/witchcraft-go-params v1.2.0 h1:hRaazk4T6ERR/58Ksn7V5/t9CDOhzUIUYaY8J6zgBxI= @@ -302,10 +308,12 @@ github.com/rogpeppe/go-internal v1.7.0 h1:3qqXGV8nn7GJT65debw77Dzrx9sfWYgP0DDo7x github.com/rogpeppe/go-internal v1.7.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.11.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs= github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -352,13 +360,17 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -381,6 +393,7 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -522,5 +535,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/client.go b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/client.go index 71d9782c..69e17482 100644 --- a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/client.go +++ b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/client.go @@ -24,6 +24,7 @@ import ( "github.com/palantir/pkg/bytesbuffers" "github.com/palantir/pkg/retry" werror "github.com/palantir/witchcraft-go-error" + "github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log" "github.com/palantir/witchcraft-go-tracing/wtracing" ) @@ -91,12 +92,15 @@ func (c *clientImpl) Do(ctx context.Context, params ...RequestParam) (*http.Resp var resp *http.Response retrier := internal.NewRequestRetrier(uris, retry.Start(ctx, c.backoffOptions...), c.maxAttempts) - for retrier.ShouldGetNextURI(resp, err) { - uri, retryErr := retrier.GetNextURI(ctx, resp, err) - if retryErr != nil { - return nil, retryErr + for { + uri, isRelocated := retrier.GetNextURI(resp, err) + if uri == "" { + break } - resp, err = c.doOnce(ctx, uri, retrier.IsRelocatedURI(uri), params...) + if err != nil { + svc1log.FromContext(ctx).Debug("Retrying request", svc1log.Stacktrace(err)) + } + resp, err = c.doOnce(ctx, uri, isRelocated, params...) } if err != nil { return nil, err diff --git a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/config.go b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/config.go index 10144d90..f11c1f3e 100644 --- a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/config.go +++ b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/config.go @@ -17,7 +17,6 @@ package httpclient import ( "bytes" "io/ioutil" - "net/http" "time" "github.com/palantir/pkg/metrics" @@ -249,10 +248,11 @@ func configToParams(c ClientConfig) ([]ClientParam, error) { // Metrics (default enabled) if c.Metrics.Enabled == nil || (c.Metrics.Enabled != nil && *c.Metrics.Enabled) { - configuredTags := TagsProviderFunc(func(*http.Request, *http.Response) metrics.Tags { - return metrics.MustNewTags(c.Metrics.Tags) - }) - params = append(params, WithMetrics(configuredTags)) + configuredTags, err := metrics.NewTags(c.Metrics.Tags) + if err != nil { + return nil, werror.Wrap(err, "invalid metrics configuration") + } + params = append(params, WithMetrics(StaticTagsProvider(configuredTags))) } // Proxy diff --git a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/request_retrier.go b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/request_retrier.go index 997d18b2..4c1053c4 100644 --- a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/request_retrier.go +++ b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/request_retrier.go @@ -15,14 +15,12 @@ package internal import ( - "context" "math/rand" "net/http" "net/url" "strings" "github.com/palantir/pkg/retry" - werror "github.com/palantir/witchcraft-go-error" ) const ( @@ -60,17 +58,6 @@ func NewRequestRetrier(uris []string, retrier retry.Retrier, maxAttempts int) *R } } -// ShouldGetNextURI returns true if GetNextURI has never been called or if the request and its corresponding error -// indicate the request should be retried. -func (r *RequestRetrier) ShouldGetNextURI(resp *http.Response, respErr error) bool { - if r.attemptCount == 0 { - return true - } - return r.attemptsRemaining() && - !r.isMeshURI(r.currentURI) && - r.responseAndErrRetriable(resp, respErr) -} - func (r *RequestRetrier) attemptsRemaining() bool { // maxAttempts of 0 indicates no limit if r.maxAttempts == 0 { @@ -79,48 +66,55 @@ func (r *RequestRetrier) attemptsRemaining() bool { return r.attemptCount < r.maxAttempts } -// GetNextURI returns the next URI a client should use, or an error if there's no suitable URI. -// This should only be called after validating that there's a suitable URI to use via ShouldGetNextURI, in which case -// an error will never be returned. -func (r *RequestRetrier) GetNextURI(ctx context.Context, resp *http.Response, respErr error) (string, error) { +// GetNextURI returns the next URI a client should use, or empty string if no suitable URI remaining to retry. +// isRelocated is true when the URI comes from a redirect's Location header. In this case, it already includes the request path. +func (r *RequestRetrier) GetNextURI(resp *http.Response, respErr error) (uri string, isRelocated bool) { defer func() { r.attemptCount++ }() if r.attemptCount == 0 { - return r.removeMeshSchemeIfPresent(r.currentURI), nil - } else if !r.ShouldGetNextURI(resp, respErr) { - return "", r.getErrorForUnretriableResponse(ctx, resp, respErr) + // First attempt is always successful. Trigger the first retry so later calls have backoff + // but ignore the returned value to ensure that the client can instrument the request even + // if the context is done. + r.retrier.Next() + return r.removeMeshSchemeIfPresent(r.currentURI), false + } + if !r.attemptsRemaining() { + // Retries exhausted + return "", false + } + if r.isMeshURI(r.currentURI) { + // Mesh uris don't get retried + return "", false } - return r.doRetrySelection(resp, respErr), nil -} - -func (r *RequestRetrier) doRetrySelection(resp *http.Response, respErr error) string { retryFn := r.getRetryFn(resp, respErr) - if retryFn != nil { - retryFn() - return r.currentURI + if retryFn == nil { + // The previous response was not retryable + return "", false } - return "" -} - -func (r *RequestRetrier) responseAndErrRetriable(resp *http.Response, respErr error) bool { - return r.getRetryFn(resp, respErr) != nil + // Updates currentURI + if !retryFn() { + return "", false + } + return r.currentURI, r.isRelocatedURI(r.currentURI) } -func (r *RequestRetrier) getRetryFn(resp *http.Response, respErr error) func() { - if retryOther, _ := isThrottleResponse(resp, respErr); retryOther { +func (r *RequestRetrier) getRetryFn(resp *http.Response, respErr error) func() bool { + errCode, _ := StatusCodeFromError(respErr) + if retryOther, _ := isThrottleResponse(resp, errCode); retryOther { // 429: throttle // Immediately backoff and select the next URI. // TODO(whickman): use the retry-after header once #81 is resolved return r.nextURIAndBackoff - } else if isUnavailableResponse(resp, respErr) { + } else if isUnavailableResponse(resp, errCode) { // 503: go to next node return r.nextURIOrBackoff - } else if shouldTryOther, otherURI := isRetryOtherResponse(resp, respErr); shouldTryOther { + } else if shouldTryOther, otherURI := isRetryOtherResponse(resp, respErr, errCode); shouldTryOther { // 307 or 308: go to next node, or particular node if provided. if otherURI != nil { - return func() { + return func() bool { r.setURIAndResetBackoff(otherURI) + return true } } return r.nextURIOrBackoff @@ -147,19 +141,20 @@ func (r *RequestRetrier) setURIAndResetBackoff(otherURI *url.URL) { // If lastURI was already marked failed, we perform a backoff as determined by the retrier before returning the next URI and its offset. // Otherwise, we add lastURI to failedURIs and return the next URI and its offset immediately. -func (r *RequestRetrier) nextURIOrBackoff() { +func (r *RequestRetrier) nextURIOrBackoff() bool { _, performBackoff := r.failedURIs[r.currentURI] r.markFailedAndMoveToNextURI() // If the URI has failed before, perform a backoff if performBackoff || len(r.uris) == 1 { - r.retrier.Next() + return r.retrier.Next() } + return true } // Marks the current URI as failed, gets the next URI, and performs a backoff as determined by the retrier. -func (r *RequestRetrier) nextURIAndBackoff() { +func (r *RequestRetrier) nextURIAndBackoff() bool { r.markFailedAndMoveToNextURI() - r.retrier.Next() + return r.retrier.Next() } func (r *RequestRetrier) markFailedAndMoveToNextURI() { @@ -181,22 +176,7 @@ func (r *RequestRetrier) isMeshURI(uri string) bool { return strings.HasPrefix(uri, meshSchemePrefix) } -// IsRelocatedURI is a helper function to identify if the provided URI is a relocated URI from response during retry -func (r *RequestRetrier) IsRelocatedURI(uri string) bool { +func (r *RequestRetrier) isRelocatedURI(uri string) bool { _, relocatedURI := r.relocatedURIs[uri] return relocatedURI } - -func (r *RequestRetrier) getErrorForUnretriableResponse(ctx context.Context, resp *http.Response, respErr error) error { - message := "GetNextURI called, but retry should not be attempted" - params := []werror.Param{ - werror.SafeParam("attemptCount", r.attemptCount), - werror.SafeParam("maxAttempts", r.maxAttempts), - werror.SafeParam("statusCodeRetriable", r.responseAndErrRetriable(resp, respErr)), - werror.SafeParam("uriInMesh", r.isMeshURI(r.currentURI)), - } - if respErr != nil { - return werror.WrapWithContextParams(ctx, respErr, message, params...) - } - return werror.ErrorWithContextParams(ctx, message, params...) -} diff --git a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/retry.go b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/retry.go index 6e77e0ad..f4c6b484 100644 --- a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/retry.go +++ b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal/retry.go @@ -59,9 +59,8 @@ const ( StatusCodeUnavailable = http.StatusServiceUnavailable ) -func isRetryOtherResponse(resp *http.Response, err error) (bool, *url.URL) { - errCode, ok := StatusCodeFromError(err) - if ok && (errCode == StatusCodeRetryOther || errCode == StatusCodeRetryTemporaryRedirect) { +func isRetryOtherResponse(resp *http.Response, err error, errCode int) (bool, *url.URL) { + if errCode == StatusCodeRetryOther || errCode == StatusCodeRetryTemporaryRedirect { locationStr, ok := LocationFromError(err) if ok { return true, parseLocationURL(locationStr) @@ -91,9 +90,8 @@ func parseLocationURL(locationStr string) *url.URL { return locationURL } -func isThrottleResponse(resp *http.Response, err error) (bool, time.Duration) { - errCode, ok := StatusCodeFromError(err) - if ok && errCode == StatusCodeThrottle { +func isThrottleResponse(resp *http.Response, errCode int) (bool, time.Duration) { + if errCode == StatusCodeThrottle { return true, 0 } if resp == nil || resp.StatusCode != StatusCodeThrottle { @@ -115,9 +113,8 @@ func isThrottleResponse(resp *http.Response, err error) (bool, time.Duration) { return true, time.Until(retryAfterDate) } -func isUnavailableResponse(resp *http.Response, err error) bool { - errCode, ok := StatusCodeFromError(err) - if ok && errCode == StatusCodeUnavailable { +func isUnavailableResponse(resp *http.Response, errCode int) bool { + if errCode == StatusCodeUnavailable { return true } if resp == nil || resp.StatusCode != StatusCodeUnavailable { diff --git a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/metrics.go b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/metrics.go index 7fd7bce2..a8b147f1 100644 --- a/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/metrics.go +++ b/vendor/github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/metrics.go @@ -17,6 +17,7 @@ package httpclient import ( "context" "crypto/tls" + "errors" "net" "net/http" "net/http/httptrace" @@ -34,13 +35,6 @@ const ( metricTagMethod = "method" metricRPCMethodName = "method-name" - metricTagFamilyOther = "other" - metricTagFamily1xx = "1xx" - metricTagFamily2xx = "2xx" - metricTagFamily3xx = "3xx" - metricTagFamily4xx = "4xx" - metricTagFamily5xx = "5xx" - MetricTLSHandshakeAttempt = "tls.handshake.attempt" MetricTLSHandshakeFailure = "tls.handshake.failure" MetricTLSHandshake = "tls.handshake" @@ -56,18 +50,33 @@ const ( var ( MetricTagConnectionNew = metrics.MustNewTag("reused", "false") MetricTagConnectionReused = metrics.MustNewTag("reused", "true") + + metricTagFamily1xx = metrics.MustNewTag(metricTagFamily, "1xx") + metricTagFamily2xx = metrics.MustNewTag(metricTagFamily, "2xx") + metricTagFamily3xx = metrics.MustNewTag(metricTagFamily, "3xx") + metricTagFamily4xx = metrics.MustNewTag(metricTagFamily, "4xx") + metricTagFamily5xx = metrics.MustNewTag(metricTagFamily, "5xx") + metricTagFamilyOther = metrics.MustNewTag(metricTagFamily, "other") + metricTagFamilyTimeout = metrics.MustNewTag(metricTagFamily, "timeout") ) // A TagsProvider returns metrics tags based on an http round trip. +// The 'error' argument is that returned from the request (if any). type TagsProvider interface { - Tags(*http.Request, *http.Response) metrics.Tags + Tags(*http.Request, *http.Response, error) metrics.Tags } // TagsProviderFunc is a convenience type that implements TagsProvider. -type TagsProviderFunc func(*http.Request, *http.Response) metrics.Tags +type TagsProviderFunc func(*http.Request, *http.Response, error) metrics.Tags -func (f TagsProviderFunc) Tags(req *http.Request, resp *http.Response) metrics.Tags { - return f(req, resp) +func (f TagsProviderFunc) Tags(req *http.Request, resp *http.Response, respErr error) metrics.Tags { + return f(req, resp, respErr) +} + +type StaticTagsProvider metrics.Tags + +func (s StaticTagsProvider) Tags(_ *http.Request, _ *http.Response, _ error) metrics.Tags { + return metrics.Tags(s) } // MetricsMiddleware updates the "client.response" timer metric on every request. @@ -86,7 +95,7 @@ func MetricsMiddleware(serviceName string, tagProviders ...TagsProvider) (Middle TagsProviderFunc(tagStatusFamily), TagsProviderFunc(tagRequestMethod), TagsProviderFunc(tagRequestMethodName), - TagsProviderFunc(func(*http.Request, *http.Response) metrics.Tags { return metrics.Tags{serviceNameTag} }), + StaticTagsProvider(metrics.Tags{serviceNameTag}), )}, nil } @@ -107,37 +116,39 @@ func (h *metricsMiddleware) RoundTrip(req *http.Request, next http.RoundTripper) var tags metrics.Tags for _, tagProvider := range h.Tags { - tags = append(tags, tagProvider.Tags(req, resp)...) + tags = append(tags, tagProvider.Tags(req, resp, err)...) } metrics.FromContext(req.Context()).Timer(metricClientResponse, tags...).Update(duration / time.Microsecond) return resp, err } -func tagStatusFamily(_ *http.Request, resp *http.Response) metrics.Tags { - var tag metrics.Tag +func tagStatusFamily(_ *http.Request, resp *http.Response, respErr error) metrics.Tags { switch { + case isTimeoutError(respErr): + return metrics.Tags{metricTagFamilyTimeout} case resp == nil, resp.StatusCode < 100, resp.StatusCode > 599: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamilyOther) + return metrics.Tags{metricTagFamilyOther} case resp.StatusCode < 200: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamily1xx) + return metrics.Tags{metricTagFamily1xx} case resp.StatusCode < 300: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamily2xx) + return metrics.Tags{metricTagFamily2xx} case resp.StatusCode < 400: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamily3xx) + return metrics.Tags{metricTagFamily3xx} case resp.StatusCode < 500: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamily4xx) + return metrics.Tags{metricTagFamily4xx} case resp.StatusCode < 600: - tag = metrics.MustNewTag(metricTagFamily, metricTagFamily5xx) + return metrics.Tags{metricTagFamily5xx} } - return metrics.Tags{tag} + // unreachable + return metrics.Tags{} } -func tagRequestMethod(req *http.Request, _ *http.Response) metrics.Tags { +func tagRequestMethod(req *http.Request, _ *http.Response, _ error) metrics.Tags { return metrics.Tags{metrics.MustNewTag(metricTagMethod, req.Method)} } -func tagRequestMethodName(req *http.Request, _ *http.Response) metrics.Tags { +func tagRequestMethodName(req *http.Request, _ *http.Response, _ error) metrics.Tags { rpcMethodName := getRPCMethodName(req.Context()) if rpcMethodName == "" { return metrics.Tags{metrics.MustNewTag(metricRPCMethodName, "RPCMethodNameMissing")} @@ -222,3 +233,25 @@ func (m *metricsWrappedConn) Close() error { m.counter.Dec(1) return m.Conn.Close() } + +func isTimeoutError(respErr error) bool { + if respErr == nil { + return false + } + rootErr := werror.RootCause(respErr) + if rootErr == nil { + return false + } + + if nerr, ok := rootErr.(net.Error); ok && nerr.Timeout() { + return true + } + if errors.Is(rootErr, context.Canceled) || errors.Is(rootErr, context.DeadlineExceeded) { + return true + } + // N.B. the http package does not expose these error types + if rootErr.Error() == "net/http: request canceled" || rootErr.Error() == "net/http: request canceled while waiting for connection" { + return true + } + return false +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/LICENSE b/vendor/github.com/palantir/witchcraft-go-logging/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/palantir/witchcraft-go-logging/internal/gopath/gopath.go b/vendor/github.com/palantir/witchcraft-go-logging/internal/gopath/gopath.go new file mode 100644 index 00000000..8c139d5f --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/internal/gopath/gopath.go @@ -0,0 +1,30 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gopath + +import ( + "strings" +) + +// TrimPrefix trims everything up to the first /src/ as a heuristic for limiting the file to the go import path. This is a +// very simple heuristic that will break if the GOPATH exists in a directory with /src/ in the path +// (e.g. ~/src/go/src/github...), but is considered best-effort. +func TrimPrefix(absolutePath string) string { + const srcDir = `/src/` + if idx := strings.Index(absolutePath, srcDir); idx >= 0 { + return absolutePath[idx+len(srcDir):] + } + return absolutePath +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/common_fields.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/common_fields.go new file mode 100644 index 00000000..79a42b8c --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/common_fields.go @@ -0,0 +1,25 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +const ( + TypeKey = "type" + TimeKey = "time" + UIDKey = "uid" + SIDKey = "sid" + TokenIDKey = "tokenId" + TraceIDKey = "traceId" + UnsafeParamsKey = "unsafeParams" +) diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/context.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/context.go new file mode 100644 index 00000000..b425943d --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/context.go @@ -0,0 +1,33 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "context" + + wloginternal "github.com/palantir/witchcraft-go-logging/wlog/internal" +) + +func ContextWithUID(ctx context.Context, uid string) context.Context { + return wloginternal.ContextWithID(ctx, wloginternal.UIDKey, uid) +} + +func ContextWithSID(ctx context.Context, sid string) context.Context { + return wloginternal.ContextWithID(ctx, wloginternal.SIDKey, sid) +} + +func ContextWithTokenID(ctx context.Context, tokenID string) context.Context { + return wloginternal.ContextWithID(ctx, wloginternal.TokenIDKey, tokenID) +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/context.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/context.go new file mode 100644 index 00000000..2595dcf1 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/context.go @@ -0,0 +1,38 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wloginternal + +import ( + "context" +) + +type wlogContextKeyType string + +const ( + UIDKey = wlogContextKeyType("wlog.uid") + SIDKey = wlogContextKeyType("wlog.sid") + TokenIDKey = wlogContextKeyType("wlog.tokenID") +) + +func ContextWithID(ctx context.Context, key wlogContextKeyType, id string) context.Context { + return context.WithValue(ctx, key, id) +} + +func IDFromContext(ctx context.Context, key wlogContextKeyType) *string { + if val, ok := ctx.Value(key).(string); ok { + return &val + } + return nil +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/default_logger.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/default_logger.go new file mode 100644 index 00000000..1362a2b9 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/internal/default_logger.go @@ -0,0 +1,33 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wloginternal + +import ( + "fmt" + "runtime" + "strings" +) + +// WarnLoggerOutput returns the logger output for a default warning logger for a given logger type. The output includes +// the location at which the call was made, with the "skip" parameter determining how far back in the call stack to go +// for the location (for example, skip=0 specifies the line in this function, skip=1 specifies the line that called this +// function, etc.). +// +// This function is defined in an internal package because each logger type needs to define its own warning logger type +// but the format/content of the output should be consistent across them. +func WarnLoggerOutput(loggerType, output string, skip int) string { + pc, fn, line, _ := runtime.Caller(skip) + return fmt.Sprintf("[WARNING] %s[%s:%d]: usage of %s.Logger from FromContext that did not have that logger set: %s", runtime.FuncForPC(pc).Name(), fn, line, loggerType, strings.TrimSuffix(output, "\n")) +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/levels.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/levels.go new file mode 100644 index 00000000..a30a8600 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/levels.go @@ -0,0 +1,52 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "fmt" + "strings" +) + +type LogLevel string + +const ( + DebugLevel LogLevel = "debug" + InfoLevel LogLevel = "info" + WarnLevel LogLevel = "warn" + ErrorLevel LogLevel = "error" + FatalLevel LogLevel = "fatal" +) + +func (l *LogLevel) UnmarshalText(b []byte) error { + switch strings.ToLower(string(b)) { + case string(DebugLevel): + *l = DebugLevel + return nil + case "", string(InfoLevel): + *l = InfoLevel + return nil + case string(WarnLevel): + *l = WarnLevel + return nil + case string(ErrorLevel): + *l = ErrorLevel + return nil + case string(FatalLevel): + *l = FatalLevel + return nil + default: + return fmt.Errorf("invalid log level: %q", string(b)) + } +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry.go new file mode 100644 index 00000000..c05acb12 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry.go @@ -0,0 +1,101 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "io" + "reflect" +) + +type LogEntry interface { + StringValue(k, v string) + OptionalStringValue(k, v string) + SafeLongValue(k string, v int64) + IntValue(k string, v int32) + StringListValue(k string, v []string) + StringMapValue(k string, v map[string]string) + AnyMapValue(k string, v map[string]interface{}) + + // ObjectValue logs the provided value associated with the specified key. If marshalerType is non-nil, then if a + // custom marshaler is registered for that type, it may be used to log the entry. If marshalerType is nil or no + // marshaler is registered for the provided type, the entry should be logged using reflection. + ObjectValue(k string, v interface{}, marshalerType reflect.Type) +} + +type Logger interface { + Log(params ...Param) +} + +type LoggerCreator func(w io.Writer) Logger + +type LeveledLoggerCreator func(w io.Writer, level LogLevel) LeveledLogger + +type LeveledLogger interface { + Debug(msg string, params ...Param) + Info(msg string, params ...Param) + Warn(msg string, params ...Param) + Error(msg string, params ...Param) + SetLevel(level LogLevel) +} + +type MapValueEntries struct { + stringMapValues map[string]map[string]string + anyMapValues map[string]map[string]interface{} +} + +func (m *MapValueEntries) StringMapValue(key string, values map[string]string) { + if len(values) == 0 { + return + } + if m.stringMapValues == nil { + m.stringMapValues = make(map[string]map[string]string) + } + entryMapVals, ok := m.stringMapValues[key] + if !ok { + entryMapVals = make(map[string]string) + m.stringMapValues[key] = entryMapVals + } + for k, v := range values { + entryMapVals[k] = v + } +} + +func (m *MapValueEntries) AnyMapValue(key string, values map[string]interface{}) { + if len(values) == 0 { + return + } + if len(values) == 0 { + return + } + if m.anyMapValues == nil { + m.anyMapValues = make(map[string]map[string]interface{}) + } + entryMapVals, ok := m.anyMapValues[key] + if !ok { + entryMapVals = make(map[string]interface{}) + m.anyMapValues[key] = entryMapVals + } + for k, v := range values { + entryMapVals[k] = v + } +} + +func (m *MapValueEntries) StringMapValues() map[string]map[string]string { + return m.stringMapValues +} + +func (m *MapValueEntries) AnyMapValues() map[string]map[string]interface{} { + return m.anyMapValues +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry_map.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry_map.go new file mode 100644 index 00000000..2340268c --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logentry_map.go @@ -0,0 +1,239 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "reflect" +) + +type MapLogEntry interface { + LogEntry + + StringValues() map[string]string + SafeLongValues() map[string]int64 + IntValues() map[string]int32 + StringListValues() map[string][]string + StringMapValues() map[string]map[string]string + AnyMapValues() map[string]map[string]interface{} + ObjectValues() map[string]ObjectValue + + // Apply applies the values of all of the stored entries of this MapLogEntry to the provided LogEntry. + Apply(logEntry LogEntry) + // AllValues returns a single map that contains all of the keys and values stored in this entry. + AllValues() map[string]interface{} +} + +type ObjectValue struct { + Value interface{} + MarshalerType reflect.Type +} + +func NewMapLogEntry() MapLogEntry { + return &mapLogEntry{ + allKeys: make(map[string]struct{}), + stringValues: make(map[string]string), + safeLongValues: make(map[string]int64), + intValues: make(map[string]int32), + stringListValues: make(map[string][]string), + stringMapValues: make(map[string]map[string]string), + anyMapValues: make(map[string]map[string]interface{}), + objectValues: make(map[string]ObjectValue), + } +} + +// mapLogEntry is an in-memory implementation of LogEntry that tracks all of the provided key/value pairs. It only +// stores a single value for a given key -- if multiple calls are made with the same key, only the last value is stored. +// If multiple map values are provided for the same key, the map values are merged. +type mapLogEntry struct { + allKeys map[string]struct{} + stringValues map[string]string + safeLongValues map[string]int64 + intValues map[string]int32 + stringListValues map[string][]string + stringMapValues map[string]map[string]string + anyMapValues map[string]map[string]interface{} + objectValues map[string]ObjectValue +} + +func (le *mapLogEntry) clearKey(key string) { + delete(le.allKeys, key) + delete(le.stringValues, key) + delete(le.safeLongValues, key) + delete(le.intValues, key) + delete(le.stringMapValues, key) + delete(le.anyMapValues, key) +} + +func (le *mapLogEntry) StringValues() map[string]string { + return le.stringValues +} + +func (le *mapLogEntry) SafeLongValues() map[string]int64 { + return le.safeLongValues +} + +func (le *mapLogEntry) IntValues() map[string]int32 { + return le.intValues +} + +func (le *mapLogEntry) StringListValues() map[string][]string { + return le.stringListValues +} + +func (le *mapLogEntry) StringMapValues() map[string]map[string]string { + return le.stringMapValues +} + +func (le *mapLogEntry) AnyMapValues() map[string]map[string]interface{} { + return le.anyMapValues +} + +func (le *mapLogEntry) ObjectValues() map[string]ObjectValue { + return le.objectValues +} + +func (le *mapLogEntry) StringValue(k, v string) { + le.clearKey(k) + + le.allKeys[k] = struct{}{} + le.stringValues[k] = v +} + +func (le *mapLogEntry) StringListValue(k string, v []string) { + le.clearKey(k) + + le.allKeys[k] = struct{}{} + le.stringListValues[k] = v +} + +func (le *mapLogEntry) OptionalStringValue(k, v string) { + if v != "" { + le.StringValue(k, v) + } +} + +func (le *mapLogEntry) SafeLongValue(k string, v int64) { + le.clearKey(k) + + le.allKeys[k] = struct{}{} + le.safeLongValues[k] = v +} + +func (le *mapLogEntry) IntValue(k string, v int32) { + le.clearKey(k) + + le.allKeys[k] = struct{}{} + le.intValues[k] = v +} + +func (le *mapLogEntry) StringMapValue(k string, v map[string]string) { + prevStringMapVal := le.stringMapValues[k] + le.clearKey(k) + le.allKeys[k] = struct{}{} + + var newMapVal map[string]string + if len(prevStringMapVal) == 0 { + newMapVal = v + } else { + newMapVal = make(map[string]string) + for prevK, prevV := range prevStringMapVal { + newMapVal[prevK] = prevV + } + for newK, newV := range v { + newMapVal[newK] = newV + } + } + le.stringMapValues[k] = newMapVal +} + +func (le *mapLogEntry) AnyMapValue(k string, v map[string]interface{}) { + prevAnyMapVal := le.anyMapValues[k] + le.clearKey(k) + le.allKeys[k] = struct{}{} + + var newMapVal map[string]interface{} + if len(prevAnyMapVal) == 0 { + newMapVal = v + } else { + newMapVal = make(map[string]interface{}) + for prevK, prevV := range prevAnyMapVal { + newMapVal[prevK] = prevV + } + for newK, newV := range v { + newMapVal[newK] = newV + } + } + le.anyMapValues[k] = newMapVal +} + +func (le *mapLogEntry) ObjectValue(k string, v interface{}, marshalerType reflect.Type) { + le.clearKey(k) + + le.allKeys[k] = struct{}{} + le.objectValues[k] = ObjectValue{ + Value: v, + MarshalerType: marshalerType, + } +} + +func (le *mapLogEntry) Apply(logEntry LogEntry) { + for k, v := range le.stringValues { + logEntry.StringValue(k, v) + } + for k, v := range le.safeLongValues { + logEntry.SafeLongValue(k, v) + } + for k, v := range le.intValues { + logEntry.IntValue(k, v) + } + for k, v := range le.stringListValues { + logEntry.StringListValue(k, v) + } + for k, v := range le.stringMapValues { + logEntry.StringMapValue(k, v) + } + for k, v := range le.anyMapValues { + logEntry.AnyMapValue(k, v) + } + for k, v := range le.objectValues { + logEntry.ObjectValue(k, v.Value, v.MarshalerType) + } +} + +func (le *mapLogEntry) AllValues() map[string]interface{} { + out := make(map[string]interface{}) + for k, v := range le.stringValues { + out[k] = v + } + for k, v := range le.safeLongValues { + out[k] = v + } + for k, v := range le.intValues { + out[k] = v + } + for k, v := range le.stringListValues { + out[k] = v + } + for k, v := range le.stringMapValues { + out[k] = v + } + for k, v := range le.anyMapValues { + out[k] = v + } + for k, v := range le.objectValues { + out[k] = v.Value + } + return out +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider.go new file mode 100644 index 00000000..f55674ee --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider.go @@ -0,0 +1,24 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "io" +) + +type LoggerProvider interface { + NewLogger(w io.Writer) Logger + NewLeveledLogger(w io.Writer, level LogLevel) LeveledLogger +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_default.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_default.go new file mode 100644 index 00000000..1249a15c --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_default.go @@ -0,0 +1,25 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +var defaultLoggerProvider = newWarnOnceLoggerProvider() + +func SetDefaultLoggerProvider(provider LoggerProvider) { + defaultLoggerProvider = provider +} + +func DefaultLoggerProvider() LoggerProvider { + return defaultLoggerProvider +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_jsonmarshal.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_jsonmarshal.go new file mode 100644 index 00000000..b7ecaef0 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_jsonmarshal.go @@ -0,0 +1,99 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "encoding/json" + "fmt" + "io" + "time" +) + +// NewJSONMarshalLoggerProvider returns a new logger provider that uses a MapLogEntry as its log entry and performs +// logging by performing a json.Marshal of the MapLogEntry. This is a naive implementation that is not very efficient: +// its primary purpose is for tests and in-memory usage in scenarios where one does not want to use a logger provider +// that uses an external library. +func NewJSONMarshalLoggerProvider() LoggerProvider { + return &jsonMarshalLoggerProvider{} +} + +type jsonMapLogger struct { + w io.Writer + level LogLevel +} + +func (l *jsonMapLogger) Log(params ...Param) { + l.logOutput(params) +} + +func (l *jsonMapLogger) Debug(msg string, params ...Param) { + switch l.level { + case DebugLevel: + l.logOutput(ParamsWithMessage(msg, params)) + } +} + +func (l *jsonMapLogger) Info(msg string, params ...Param) { + switch l.level { + case DebugLevel, InfoLevel: + l.logOutput(ParamsWithMessage(msg, params)) + } +} + +func (l *jsonMapLogger) Warn(msg string, params ...Param) { + switch l.level { + case DebugLevel, InfoLevel, WarnLevel: + l.logOutput(ParamsWithMessage(msg, params)) + } +} + +func (l *jsonMapLogger) Error(msg string, params ...Param) { + switch l.level { + case DebugLevel, InfoLevel, WarnLevel, ErrorLevel: + l.logOutput(ParamsWithMessage(msg, params)) + } +} + +func (l *jsonMapLogger) SetLevel(level LogLevel) { + l.level = level +} + +func (l *jsonMapLogger) logOutput(params []Param) { + params = append(params, StringParam(TimeKey, time.Now().Format(time.RFC3339Nano))) + + entry := NewMapLogEntry() + ApplyParams(entry, params) + bytes, _ := json.Marshal(entry.AllValues()) + _, _ = fmt.Fprintln(l.w, string(bytes)) +} + +type jsonMarshalLoggerProvider struct{} + +func (*jsonMarshalLoggerProvider) NewLogger(w io.Writer) Logger { + return &jsonMapLogger{ + w: w, + } +} + +func (*jsonMarshalLoggerProvider) NewLeveledLogger(w io.Writer, level LogLevel) LeveledLogger { + return &jsonMapLogger{ + w: w, + level: level, + } +} + +func (p *jsonMarshalLoggerProvider) NewLogEntry() LogEntry { + return NewMapLogEntry() +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_noop.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_noop.go new file mode 100644 index 00000000..8ab34de4 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_noop.go @@ -0,0 +1,60 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "io" + "reflect" +) + +// NewNoopLoggerProvider returns a LoggerProvider whose implementations +// are no-ops. That is, they return immediately after doing nothing. +func NewNoopLoggerProvider() LoggerProvider { + return &noopLoggerProvider{} +} + +type nooplogger struct{} + +func (*nooplogger) Log(params ...Param) {} +func (*nooplogger) Debug(msg string, params ...Param) {} +func (*nooplogger) Info(msg string, params ...Param) {} +func (*nooplogger) Warn(msg string, params ...Param) {} +func (*nooplogger) Error(msg string, params ...Param) {} +func (*nooplogger) SetLevel(level LogLevel) {} + +type noopLoggerProvider struct{} + +func (*noopLoggerProvider) NewLogger(w io.Writer) Logger { + return &nooplogger{} +} + +func (*noopLoggerProvider) NewLeveledLogger(w io.Writer, level LogLevel) LeveledLogger { + return &nooplogger{} +} + +func (p *noopLoggerProvider) NewLogEntry() LogEntry { + return &noopLogEntry{} +} + +type noopLogEntry struct{} + +func (*noopLogEntry) StringValue(k, v string) {} +func (*noopLogEntry) OptionalStringValue(k, v string) {} +func (*noopLogEntry) StringListValue(k string, v []string) {} +func (*noopLogEntry) SafeLongValue(k string, v int64) {} +func (*noopLogEntry) IntValue(k string, v int32) {} +func (*noopLogEntry) StringMapValue(k string, v map[string]string) {} +func (*noopLogEntry) AnyMapValue(k string, v map[string]interface{}) {} +func (*noopLogEntry) ObjectValue(k string, v interface{}, marshalerType reflect.Type) {} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_warnonce.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_warnonce.go new file mode 100644 index 00000000..2bb7951c --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/logger_provider_warnonce.go @@ -0,0 +1,61 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +import ( + "fmt" + "io" + "sync" +) + +func newWarnOnceLoggerProvider() LoggerProvider { + return &warnOnceLoggerProvider{} +} + +type warnOnceLogger struct { + w io.Writer + once sync.Once +} + +func (l *warnOnceLogger) Log(params ...Param) { l.once.Do(l.printWarning) } +func (l *warnOnceLogger) Debug(msg string, params ...Param) { l.once.Do(l.printWarning) } +func (l *warnOnceLogger) Info(msg string, params ...Param) { l.once.Do(l.printWarning) } +func (l *warnOnceLogger) Warn(msg string, params ...Param) { l.once.Do(l.printWarning) } +func (l *warnOnceLogger) Error(msg string, params ...Param) { l.once.Do(l.printWarning) } +func (l *warnOnceLogger) SetLevel(level LogLevel) { l.once.Do(l.printWarning) } + +func (l *warnOnceLogger) printWarning() { + _, _ = fmt.Fprintln(l.w, `[WARNING] Logging operation that uses the default logger provider was performed without specifying a logger provider implementation. `+ + `To see logger output, set the global logger provider implementation using wlog.SetDefaultLoggerProvider or by importing an implementation. `+ + `This warning can be disabled by setting the global logger provider to be the noop logger provider using wlog.SetDefaultLoggerProvider(wlog.NewNoopLoggerProvider()).`) +} + +type warnOnceLoggerProvider struct{} + +func (*warnOnceLoggerProvider) NewLogger(w io.Writer) Logger { + return &warnOnceLogger{ + w: w, + } +} + +func (*warnOnceLoggerProvider) NewLeveledLogger(w io.Writer, level LogLevel) LeveledLogger { + return &warnOnceLogger{ + w: w, + } +} + +func (*warnOnceLoggerProvider) NewLogEntry() LogEntry { + return &noopLogEntry{} +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/params.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/params.go new file mode 100644 index 00000000..f4ac95bb --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/params.go @@ -0,0 +1,72 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wlog + +type Param interface { + apply(logger LogEntry) +} + +func StringParam(key, value string) Param { + return NewParam(func(logger LogEntry) { + logger.StringValue(key, value) + }) +} + +func OptionalStringParam(key, value string) Param { + return NewParam(func(logger LogEntry) { + logger.OptionalStringValue(key, value) + }) +} + +func IntParam(key string, value int32) Param { + return NewParam(func(logger LogEntry) { + logger.IntValue(key, value) + }) +} + +func Int64Param(key string, value int64) Param { + return NewParam(func(logger LogEntry) { + logger.SafeLongValue(key, value) + }) +} + +func NewParam(fn func(entry LogEntry)) Param { + return paramFunc(fn) +} + +func ApplyParams(logger LogEntry, params []Param) { + for _, p := range params { + if p == nil { + continue + } + p.apply(logger) + } +} + +// ParamsWithMessage returns a new slice that appends a StringParam with the key "message" and +// value of the provided msg parameter if it is non-empty. If msg is empty, returns the provided slice +// without modification. +func ParamsWithMessage(msg string, params []Param) []Param { + if msg != "" { + return append(params, StringParam("message", msg)) + } + return params +} + +type paramFunc func(logger LogEntry) + +func (f paramFunc) apply(logger LogEntry) { + f(logger) +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/context.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/context.go new file mode 100644 index 00000000..d2924a84 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/context.go @@ -0,0 +1,93 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "context" + + "github.com/palantir/witchcraft-go-logging/wlog" + wloginternal "github.com/palantir/witchcraft-go-logging/wlog/internal" + wparams "github.com/palantir/witchcraft-go-params" + "github.com/palantir/witchcraft-go-tracing/wtracing" +) + +type svc1LogContextKeyType string + +const contextKey = svc1LogContextKeyType(TypeValue) + +// WithLogger returns a copy of the provided context with the provided Logger included as a value. This operation will +// replace any logger that was previously set on the context (along with all parameters that may have been set on the +// logger). +func WithLogger(ctx context.Context, logger Logger) context.Context { + return context.WithValue(ctx, contextKey, logger) +} + +// WithLoggerParams returns a copy of the provided context whose logger is configured with the provided parameters. If +// no parameters are provided, the original context is returned unmodified. If the provided context did not have a +// logger set on it, the returned context will contain the default logger configured with the provided parameters. If +// any of the provided parameters set safe or unsafe values, the returned context will also have those values set on it +// using the wparams.ContextWithSafeAndUnsafeParams function. +func WithLoggerParams(ctx context.Context, params ...Param) context.Context { + if len(params) == 0 { + return ctx + } + // if the provided params set any safe or unsafe values, set those as wparams on the context + if safeParams, unsafeParams := safeAndUnsafeParamsFromParams(params); len(safeParams) > 0 || len(unsafeParams) > 0 { + ctx = wparams.ContextWithSafeAndUnsafeParams(ctx, safeParams, unsafeParams) + } + return WithLogger(ctx, WithParams(loggerFromContext(ctx), params...)) +} + +// FromContext returns the Logger stored in the provided context. If no logger is set on the context, returns the logger +// created by calling DefaultLogger. If the context contains a TraceID set using wtracing, the returned logger has that +// TraceID set on it as a parameter. Any safe or unsafe parameters stored on the context using wparams are also set as +// parameters on the returned logger. +func FromContext(ctx context.Context) Logger { + logger := loggerFromContext(ctx) + var params []Param + if paramStorer := wparams.ParamStorerFromContext(ctx); paramStorer != nil && (len(paramStorer.SafeParams()) > 0 || len(paramStorer.UnsafeParams()) > 0) { + params = append(params, Params(paramStorer)) + } + if uid := wloginternal.IDFromContext(ctx, wloginternal.UIDKey); uid != nil { + params = append(params, UID(*uid)) + } + if sid := wloginternal.IDFromContext(ctx, wloginternal.SIDKey); sid != nil { + params = append(params, SID(*sid)) + } + if tokenID := wloginternal.IDFromContext(ctx, wloginternal.TokenIDKey); tokenID != nil { + params = append(params, TokenID(*tokenID)) + } + if traceID := wtracing.TraceIDFromContext(ctx); traceID != "" { + params = append(params, TraceID(string(traceID))) + } + return WithParams(logger, params...) +} + +func safeAndUnsafeParamsFromParams(params []Param) (safe map[string]interface{}, unsafe map[string]interface{}) { + logEntry := wlog.NewMapLogEntry() + for _, currParam := range params { + currParam.apply(logEntry) + } + return logEntry.AnyMapValues()[ParamsKey], logEntry.AnyMapValues()[wlog.UnsafeParamsKey] +} + +// loggerFromContext returns the logger stored in the provided context. If no logger is set on the context, returns the +// logger created by calling DefaultLogger. +func loggerFromContext(ctx context.Context) Logger { + if logger, ok := ctx.Value(contextKey).(Logger); ok { + return logger + } + return defaultLoggerCreator() +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/default.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/default.go new file mode 100644 index 00000000..2409fd7d --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/default.go @@ -0,0 +1,107 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "bytes" + "fmt" + "io" + "os" + + "github.com/palantir/witchcraft-go-logging/wlog" + wloginternal "github.com/palantir/witchcraft-go-logging/wlog/internal" +) + +func SetDefaultLoggerCreator(creator func() Logger) { + defaultLoggerCreator = creator +} + +var defaultLoggerCreator = func() Logger { + return &warnLogger{ + w: os.Stderr, + // store the DefaultLoggerProvider at creation-time so that the output of this logger will be consistent + // throughout its lifetime (if the default logger provider is changed after a specific warnLogger is created, + // that should not change the creator used for that warnLogger). + creator: wlog.DefaultLoggerProvider().NewLeveledLogger, + level: wlog.InfoLevel, + } +} + +// warnLogger is a logger that writes a warning to the provided io.Writer whenever its logging function is invoked. When +// the logging function is invoked, a new logger is created using the wlog.LoggerCreator and a warning and the output of +// the created logger are written to the io.Writer. +type warnLogger struct { + w io.Writer + creator wlog.LeveledLoggerCreator + level wlog.LogLevel +} + +func (l *warnLogger) Debug(msg string, params ...Param) { + switch l.level { + case wlog.DebugLevel: + default: + return + } + + l.log(func(logger Logger) { + logger.Debug(msg, params...) + }) +} + +func (l *warnLogger) Info(msg string, params ...Param) { + switch l.level { + case wlog.DebugLevel, wlog.InfoLevel: + default: + return + } + + l.log(func(logger Logger) { + logger.Info(msg, params...) + }) +} + +func (l *warnLogger) Warn(msg string, params ...Param) { + switch l.level { + case wlog.DebugLevel, wlog.InfoLevel, wlog.WarnLevel: + default: + return + } + + l.log(func(logger Logger) { + logger.Warn(msg, params...) + }) +} + +func (l *warnLogger) Error(msg string, params ...Param) { + switch l.level { + case wlog.DebugLevel, wlog.InfoLevel, wlog.WarnLevel, wlog.ErrorLevel: + default: + return + } + + l.log(func(logger Logger) { + logger.Error(msg, params...) + }) +} + +func (l *warnLogger) SetLevel(level wlog.LogLevel) { + l.level = level +} + +func (l *warnLogger) log(logFn func(logger Logger)) { + buf := &bytes.Buffer{} + logFn(NewFromCreator(buf, l.level, l.creator)) + _, _ = fmt.Fprintln(l.w, wloginternal.WarnLoggerOutput("svc1log", buf.String(), 4)) +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger.go new file mode 100644 index 00000000..197474df --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger.go @@ -0,0 +1,60 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "io" + + "github.com/palantir/witchcraft-go-logging/wlog" +) + +type Logger interface { + Debug(msg string, params ...Param) + Info(msg string, params ...Param) + Warn(msg string, params ...Param) + Error(msg string, params ...Param) + SetLevel(level wlog.LogLevel) +} + +func New(w io.Writer, level wlog.LogLevel, params ...Param) Logger { + return NewFromCreator(w, level, wlog.DefaultLoggerProvider().NewLeveledLogger, params...) +} + +func NewFromCreator(w io.Writer, level wlog.LogLevel, creator wlog.LeveledLoggerCreator, params ...Param) Logger { + return WithParams(&defaultLogger{ + loggerCreator: func(level wlog.LogLevel) wlog.LeveledLogger { + return creator(w, level) + }, + logger: creator(w, level), + }, params...) +} + +func WithParams(logger Logger, params ...Param) Logger { + // Note that wrapping is performed even if len(params) == 0. This is done intentionally to ensure that every default + // logger evaluates its parameters at the same level in the stack, which is required to ensure that the + // OriginFromCallLine parameter works generically. + + if innerWrapped, ok := logger.(*wrappedLogger); ok { + return &wrappedLogger{ + logger: innerWrapped.logger, + params: append(innerWrapped.params, params...), + } + } + + return &wrappedLogger{ + logger: logger, + params: params, + } +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_default.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_default.go new file mode 100644 index 00000000..436439fa --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_default.go @@ -0,0 +1,94 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "time" + + "github.com/palantir/witchcraft-go-logging/wlog" +) + +var ( + // Level params declared as variables so that they are only allocated once + debugLevelParam = wlog.NewParam(func(entry wlog.LogEntry) { + entry.StringValue(LevelKey, LevelDebugValue) + }) + infoLevelParam = wlog.NewParam(func(entry wlog.LogEntry) { + entry.StringValue(LevelKey, LevelInfoValue) + }) + warnLevelParam = wlog.NewParam(func(entry wlog.LogEntry) { + entry.StringValue(LevelKey, LevelWarnValue) + }) + errorLevelParam = wlog.NewParam(func(entry wlog.LogEntry) { + entry.StringValue(LevelKey, LevelErrorValue) + }) +) + +func DebugLevelParam() wlog.Param { + return debugLevelParam +} +func InfoLevelParam() wlog.Param { + return infoLevelParam +} +func WarnLevelParam() wlog.Param { + return warnLevelParam +} +func ErrorLevelParam() wlog.Param { + return errorLevelParam +} + +type defaultLogger struct { + loggerCreator func(level wlog.LogLevel) wlog.LeveledLogger + + logger wlog.LeveledLogger + params []Param +} + +func (l *defaultLogger) Debug(msg string, params ...Param) { + l.logger.Debug(msg, ToParams(DebugLevelParam(), params)...) +} + +func (l *defaultLogger) Info(msg string, params ...Param) { + l.logger.Info(msg, ToParams(InfoLevelParam(), params)...) +} + +func (l *defaultLogger) Warn(msg string, params ...Param) { + l.logger.Warn(msg, ToParams(WarnLevelParam(), params)...) +} + +func (l *defaultLogger) Error(msg string, params ...Param) { + l.logger.Error(msg, ToParams(ErrorLevelParam(), params)...) +} + +func (l *defaultLogger) SetLevel(level wlog.LogLevel) { + l.logger.SetLevel(level) +} + +func ToParams(level wlog.Param, inParams []Param) []wlog.Param { + outParams := make([]wlog.Param, len(defaultTypeParam)+1+len(inParams)) + copy(outParams, defaultTypeParam) + outParams[len(defaultTypeParam)] = level + for idx := range inParams { + outParams[len(defaultTypeParam)+1+idx] = wlog.NewParam(inParams[idx].apply) + } + return outParams +} + +var defaultTypeParam = []wlog.Param{ + wlog.NewParam(func(entry wlog.LogEntry) { + entry.StringValue(wlog.TypeKey, TypeValue) + entry.StringValue(wlog.TimeKey, time.Now().Format(time.RFC3339Nano)) + }), +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_wrapped.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_wrapped.go new file mode 100644 index 00000000..219857ec --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/logger_wrapped.go @@ -0,0 +1,44 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "github.com/palantir/witchcraft-go-logging/wlog" +) + +type wrappedLogger struct { + logger Logger + params []Param +} + +func (w *wrappedLogger) Debug(msg string, params ...Param) { + w.logger.Debug(msg, append(w.params, params...)...) +} + +func (w *wrappedLogger) Info(msg string, params ...Param) { + w.logger.Info(msg, append(w.params, params...)...) +} + +func (w *wrappedLogger) Warn(msg string, params ...Param) { + w.logger.Warn(msg, append(w.params, params...)...) +} + +func (w *wrappedLogger) Error(msg string, params ...Param) { + w.logger.Error(msg, append(w.params, params...)...) +} + +func (w *wrappedLogger) SetLevel(level wlog.LogLevel) { + w.logger.SetLevel(level) +} diff --git a/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/params.go b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/params.go new file mode 100644 index 00000000..2397e669 --- /dev/null +++ b/vendor/github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log/params.go @@ -0,0 +1,224 @@ +// Copyright (c) 2018 Palantir Technologies. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package svc1log + +import ( + "path" + "runtime" + "strconv" + + werror "github.com/palantir/witchcraft-go-error" + "github.com/palantir/witchcraft-go-logging/internal/gopath" + "github.com/palantir/witchcraft-go-logging/wlog" + wparams "github.com/palantir/witchcraft-go-params" +) + +const ( + TypeValue = "service.1" + + LevelKey = "level" + LevelDebugValue = "DEBUG" + LevelInfoValue = "INFO" + LevelWarnValue = "WARN" + LevelErrorValue = "ERROR" + + OriginKey = "origin" + ThreadKey = "thread" + MessageKey = "message" + ParamsKey = "params" + StacktraceKey = "stacktrace" + TagsKey = "tags" +) + +type Param interface { + apply(entry wlog.LogEntry) +} + +func ApplyParam(p Param, entry wlog.LogEntry) { + if p == nil { + return + } + p.apply(entry) +} + +type paramFunc func(entry wlog.LogEntry) + +func (f paramFunc) apply(entry wlog.LogEntry) { + f(entry) +} + +// Origin sets the "origin" field to be the provided value if it is non-empty. +func Origin(origin string) Param { + return paramFunc(func(logger wlog.LogEntry) { + logger.OptionalStringValue(OriginKey, origin) + }) +} + +// CallerPkg returns a package path based on the location at which this function is called and the parameters given to +// the function. This can be used in conjunction with the "Origin" param to set the origin field programmatically. +// +// The parentCaller parameter specifies the number of "parents" to go back in the call stack, while the parentPkg +// parameter determines the level of the parent package that should be used. For example, if this function is called in +// a file with the package path "github.com/palantir/witchcraft-go-logging/wlog" and that function is called from a file +// with the package path "github.com/palantir/project/helper", then with parentCaller=0 and parentPkg=0 the returned +// value would be "github.com/palantir/witchcraft-go-logging/wlog", while with parentCaller=1 and parentPkg=1 the value +// would be "github.com/palantir/project" (parentCaller=1 sets the package to "github.com/palantir/project/helper" and +// parentPkg=1 causes the package to become "github.com/palantir/project"). +func CallerPkg(parentCaller, parentPkg int) string { + origin := "" + if file, _, ok := initLineCaller(1 + parentCaller); ok { + origin = path.Dir(file) + for i := 0; i < parentPkg; i++ { + origin = path.Dir(origin) + } + } + return origin +} + +// OriginFromInitLine sets the "origin" field to be the filename and line of the location at which this function is +// called. +func OriginFromInitLine() Param { + origin := "" + if file, line, ok := initLineCaller(1); ok { + origin = file + ":" + strconv.Itoa(line) + } + return Origin(origin) +} + +// OriginFromInitPkg sets the "origin" field to be the package path of the location at which this function is called. +// The skipPkg parameter determines the level of the parent package that should be used. For example, if this function +// is called in a file with the package path "github.com/palantir/witchcraft-go-logging/wlog", then with skipPkg=0 the +// origin would be "github.com/palantir/witchcraft-go-logging/wlog", while with skipPkg=1 the origin would be +// "github.com/palantir/witchcraft-go-logging". +func OriginFromInitPkg(skipPkg int) Param { + return Origin(CallerPkg(1, 0)) +} + +// OriginFromCallLine sets the "origin" field to be the filename and line of the location at which the logger invocation +// is performed. +// +// Note that, when this parameter is used, every log invocation will perform a "runtime.Caller" call, which may not be +// suitable for performance-critical scenarios. +// +// Note that this parameter is tied to the implementation details of the logger implementations defined in the svc1log +// package (it hard-codes assumptions relating to the number of call stacks that must be skipped to reach the log site). +// Using this parameter with an svc1log.Logger implementation not defined in the svc1log package may result in incorrect +// output. If wrapping the default implementation of svc1log.Logger, OriginFromCallLineWithSkip allows for trimming +// additional stack frames. +func OriginFromCallLine() Param { + return OriginFromCallLineWithSkip(0) +} + +const defaultOriginFromCallLineStackSkip = 8 + +// OriginFromCallLineWithSkip is like OriginFromCallLine but allows for configuring additional skipped stack frames. +// This allows for libraries wrapping loggers to hide their implementation frames from the caller. +func OriginFromCallLineWithSkip(skipFrames int) Param { + return paramFunc(func(entry wlog.LogEntry) { + origin := "" + if file, line, ok := initLineCaller(defaultOriginFromCallLineStackSkip + skipFrames); ok { + origin = file + ":" + strconv.Itoa(line) + } + entry.OptionalStringValue(OriginKey, origin) + }) +} + +func initLineCaller(skip int) (string, int, bool) { + // the 1 skips the current "initLineCaller" function + _, file, line, ok := runtime.Caller(1 + skip) + if ok { + file = gopath.TrimPrefix(file) + } + return file, line, ok +} + +func SafeParam(key string, value interface{}) Param { + return SafeParams(map[string]interface{}{ + key: value, + }) +} + +func SafeParams(safe map[string]interface{}) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.AnyMapValue(ParamsKey, safe) + }) +} + +func UID(uid string) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.OptionalStringValue(wlog.UIDKey, uid) + }) +} + +func SID(sid string) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.OptionalStringValue(wlog.SIDKey, sid) + }) +} + +func TokenID(tokenID string) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.OptionalStringValue(wlog.TokenIDKey, tokenID) + }) +} + +func TraceID(traceID string) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.OptionalStringValue(wlog.TraceIDKey, traceID) + }) +} + +func Stacktrace(err error) Param { + return paramFunc(func(entry wlog.LogEntry) { + if err == nil { + return + } + entry.StringValue(StacktraceKey, werror.GenerateErrorString(err, false)) + + // add all safe and unsafe parameters stored in error + safeParams, unsafeParams := werror.ParamsFromError(err) + SafeParams(safeParams).apply(entry) + UnsafeParams(unsafeParams).apply(entry) + }) +} + +func UnsafeParam(key string, value interface{}) Param { + return UnsafeParams(map[string]interface{}{ + key: value, + }) +} + +func UnsafeParams(unsafe map[string]interface{}) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.AnyMapValue(wlog.UnsafeParamsKey, unsafe) + }) +} + +func Params(object wparams.ParamStorer) Param { + return paramFunc(func(entry wlog.LogEntry) { + SafeParams(object.SafeParams()).apply(entry) + UnsafeParams(object.UnsafeParams()).apply(entry) + }) +} + +func Tag(key, value string) Param { + return Tags(map[string]string{key: value}) +} + +func Tags(tags map[string]string) Param { + return paramFunc(func(entry wlog.LogEntry) { + entry.StringMapValue(TagsKey, tags) + }) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 287694af..9cc1cd0f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -21,7 +21,7 @@ github.com/mattn/go-runewidth github.com/nmiyake/pkg # github.com/nmiyake/pkg/errorstringer v1.0.2 github.com/nmiyake/pkg/errorstringer -# github.com/palantir/conjure-go-runtime/v2 v2.13.1 +# github.com/palantir/conjure-go-runtime/v2 v2.14.0 github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient/internal github.com/palantir/conjure-go-runtime/v2/conjure-go-contract/codecs @@ -71,6 +71,11 @@ github.com/palantir/pkg/uuid/internal/uuid # github.com/palantir/witchcraft-go-error v1.5.0 github.com/palantir/witchcraft-go-error github.com/palantir/witchcraft-go-error/internal/errors +# github.com/palantir/witchcraft-go-logging v1.14.0 +github.com/palantir/witchcraft-go-logging/internal/gopath +github.com/palantir/witchcraft-go-logging/wlog +github.com/palantir/witchcraft-go-logging/wlog/internal +github.com/palantir/witchcraft-go-logging/wlog/svclog/svc1log # github.com/palantir/witchcraft-go-params v1.2.0 github.com/palantir/witchcraft-go-params # github.com/palantir/witchcraft-go-tracing v1.4.0