From f560b15a573cb14715657b42a5b1ed0aa13eed8c Mon Sep 17 00:00:00 2001 From: DevMiner Date: Fri, 23 Aug 2024 00:34:37 +0200 Subject: [PATCH] refactor: move integrations into separate packages --- go.mod | 27 ++-- go.sum | 80 ++++++---- span.go | 3 +- telemetry.go | 27 ++-- traced_transport.go | 101 ------------- tracing.go | 8 +- .../fiber_middleware.go | 63 ++++---- .../request_logger.go | 44 +++--- unitelhttp/transport.go | 142 ++++++++++++++++++ sql_tracing.go => unitelsql/hooks.go | 101 +++++++------ unitelutils/constants.go | 6 + version.go | 6 - 12 files changed, 339 insertions(+), 269 deletions(-) delete mode 100644 traced_transport.go rename fiber_middleware.go => unitelhttp/fiber_middleware.go (79%) rename request_logger.go => unitelhttp/request_logger.go (78%) create mode 100644 unitelhttp/transport.go rename sql_tracing.go => unitelsql/hooks.go (65%) create mode 100644 unitelutils/constants.go delete mode 100644 version.go diff --git a/go.mod b/go.mod index 0744c15..4ceb801 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.22.5 require ( github.com/getsentry/sentry-go v0.28.1 + github.com/go-logr/logr v1.4.2 github.com/gofiber/fiber/v2 v2.52.5 - github.com/jackc/pgx/v5 v5.6.0 github.com/qustavo/sqlhooks/v2 v2.1.0 github.com/rs/zerolog v1.33.0 github.com/valyala/fasthttp v1.55.0 @@ -23,29 +23,24 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.64.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect ) diff --git a/go.sum b/go.sum index 3fd06ef..e60b565 100644 --- a/go.sum +++ b/go.sum @@ -20,20 +20,15 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= -github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= @@ -44,8 +39,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -57,15 +52,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/qustavo/sqlhooks/v2 v2.1.0 h1:54yBemHnGHp/7xgT+pxwmIlMSDNYKx5JW5dfRAiCZi0= github.com/qustavo/sqlhooks/v2 v2.1.0/go.mod h1:aMREyKo7fOKTwiLuWPsaHRXEmtqG4yREztO0idF83AU= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -74,6 +68,7 @@ github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8 github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= @@ -98,31 +93,52 @@ go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeX go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/span.go b/span.go index 44853bc..dae91a2 100644 --- a/span.go +++ b/span.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "git.devminer.xyz/devminer/unitel/unitelutils" "github.com/getsentry/sentry-go" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -208,7 +209,7 @@ func (s *Span) SetUser(id uint64, username, ip, permissions string) *Span { s.otel.SetAttributes( semconv.EnduserID(uid), semconv.EnduserScope(permissions), - attribute.String(libBase+"/username", username), + attribute.String(unitelutils.Base+"/username", username), semconv.ClientAddress(ip), ) diff --git a/telemetry.go b/telemetry.go index 8f4aaad..f2c3d23 100644 --- a/telemetry.go +++ b/telemetry.go @@ -25,8 +25,11 @@ import ( type telemetryContextKey struct{} type Opts struct { - Environment string - ServiceName string + Environment string + + ServiceName string + ServiceVersion string + OTLPEndpoint string SentryDSN string } @@ -42,21 +45,21 @@ func ParseOpts(serviceName string) Opts { type Telemetry struct { Opts Opts - propagator propagation.TextMapPropagator - tracerProvider trace.TracerProvider - meterProvider metric.MeterProvider + Propagator propagation.TextMapPropagator + TracerProvider trace.TracerProvider + MeterProvider metric.MeterProvider Tracer trace.Tracer Meter metric.Meter } func (o *Telemetry) Shutdown(ctx context.Context) { - if tp, ok := o.tracerProvider.(*sdktrace.TracerProvider); ok { + if tp, ok := o.TracerProvider.(*sdktrace.TracerProvider); ok { if err := tp.Shutdown(ctx); err != nil { log.Error().Err(err).Msg("failed to shutdown TracerProvider") } } - if mp, ok := o.meterProvider.(*sdkmetric.MeterProvider); ok { + if mp, ok := o.MeterProvider.(*sdkmetric.MeterProvider); ok { if err := mp.Shutdown(ctx); err != nil { log.Error().Err(err).Msg("failed to stop MeterProvider") } @@ -121,7 +124,7 @@ func initializeSentry(opts Opts) error { return sentry.Init(sentry.ClientOptions{ Dsn: opts.SentryDSN, - Release: libVersion, + Release: opts.ServiceVersion, AttachStacktrace: true, SampleRate: getSampleRate(opts), EnableTracing: true, @@ -157,7 +160,7 @@ func Initialize(opts Opts) (*Telemetry, error) { resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName(opts.ServiceName), - semconv.ServiceVersion(libVersion), + semconv.ServiceVersion(opts.ServiceVersion), semconv.DeploymentEnvironment(opts.Environment), ), ) @@ -219,9 +222,9 @@ func Initialize(opts Opts) (*Telemetry, error) { return &Telemetry{ Opts: opts, - propagator: propagator, - tracerProvider: tracerProvider, - meterProvider: metricProvider, + Propagator: propagator, + TracerProvider: tracerProvider, + MeterProvider: metricProvider, Tracer: tracerProvider.Tracer(opts.ServiceName), Meter: metricProvider.Meter(opts.ServiceName), }, nil diff --git a/traced_transport.go b/traced_transport.go deleted file mode 100644 index 4c4ab4c..0000000 --- a/traced_transport.go +++ /dev/null @@ -1,101 +0,0 @@ -package unitel - -import ( - "fmt" - "net/http" - - "github.com/getsentry/sentry-go" - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.26.0" - "go.opentelemetry.io/otel/trace" -) - -const httpClientTransportClientID = libBase + "#HTTPTansport" - -type HTTPTransport struct { - telemetry *Telemetry - forwardTrace bool - tracedRequestHeaders []string - tracedResponseHeaders []string - Transport http.RoundTripper - - tracer trace.Tracer -} - -func (t *Telemetry) NewTracedTransport(transport http.RoundTripper, forwardTrace bool, tracedRequestHeaders []string, tracedResponseHeaders []string) *HTTPTransport { - return &HTTPTransport{ - telemetry: t, - forwardTrace: forwardTrace, - tracedRequestHeaders: tracedRequestHeaders, - tracedResponseHeaders: tracedResponseHeaders, - Transport: transport, - - tracer: t.tracerProvider.Tracer(httpClientTransportClientID, trace.WithInstrumentationVersion(libVersion)), - } -} - -func (t *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) { - s := t.telemetry. - StartSpan(req.Context(), "http.client", fmt.Sprintf("%s %s", req.Method, req.URL), WithOtelOptions(trace.WithSpanKind(trace.SpanKindClient))). - AddAttributes( - semconv.HTTPRequestMethodKey.String(req.Method), - semconv.URLFull(req.URL.String()), - ) - defer s.End() - ctx := s.Context() - req = req.WithContext(ctx) - - if t.forwardTrace { - t.telemetry.InjectIntoHeaders(ctx, req.Header) - } - - for _, header := range t.tracedRequestHeaders { - vv := req.Header.Values(header) - for i, v := range vv { - s.AddAttributes(attribute.String(formatHeaderAttribute("http.request", header, vv, i), v)) - } - } - - resp, err := t.Transport.RoundTrip(req) - if err != nil { - s.CaptureBreadcrumb(SeverityError, BreadcrumbTypeHTTP, BreadcrumbCatagoryHTTP, fmt.Sprintf("Failed to send request to %s: %v", req.URL.String(), err), map[string]any{ - "url": req.URL.String(), - "method": req.Method, - }) - - if hub := sentry.GetHubFromContext(ctx); hub != nil { - hub.CaptureException(err) - } - - return resp, err - } - - { - severity := SeverityDebug - if resp.StatusCode < http.StatusBadRequest { - severity = SeverityInfo - } else if resp.StatusCode < http.StatusInternalServerError { - severity = SeverityError - } else { - severity = SeverityError - } - s.CaptureBreadcrumb(severity, BreadcrumbTypeHTTP, BreadcrumbCatagoryHTTP, req.URL.String(), map[string]any{ - "url": req.URL.String(), - "method": req.Method, - "status": resp.StatusCode, - }) - } - - s. - AddAttributes(semconv.HTTPResponseStatusCode(resp.StatusCode)). - SetStatus(httpStatusToSpanStatus(resp.StatusCode, false), "") - - for _, header := range t.tracedResponseHeaders { - vv := resp.Header.Values(header) - for i, v := range vv { - s.AddAttributes(attribute.String(formatHeaderAttribute("http.response", header, vv, i), v)) - } - } - - return resp, err -} diff --git a/tracing.go b/tracing.go index 5a3f129..27b533f 100644 --- a/tracing.go +++ b/tracing.go @@ -62,7 +62,7 @@ func WithOtelOptions(opts ...trace.SpanStartOption) ConfigureSpanStartFunc { } func (t *Telemetry) InjectIntoHeaders(ctx context.Context, headers http.Header) { - t.propagator.Inject(ctx, propagation.HeaderCarrier(headers)) + t.Propagator.Inject(ctx, propagation.HeaderCarrier(headers)) if sentrySpan := sentry.SpanFromContext(ctx); sentrySpan == nil { // this should never happen... @@ -74,7 +74,7 @@ func (t *Telemetry) InjectIntoHeaders(ctx context.Context, headers http.Header) } func (t *Telemetry) InjectIntoMap(ctx context.Context, m map[string]string) { - t.propagator.Inject(ctx, propagation.MapCarrier(m)) + t.Propagator.Inject(ctx, propagation.MapCarrier(m)) if sentrySpan := sentry.SpanFromContext(ctx); sentrySpan == nil { // this should never happen... @@ -87,7 +87,7 @@ func (t *Telemetry) InjectIntoMap(ctx context.Context, m map[string]string) { func (t *Telemetry) ContinueFromHeaders(h http.Header) ConfigureSpanStartFunc { return func(ctx context.Context) (context.Context, []trace.SpanStartOption, []sentry.SpanOption) { - ctx = t.propagator.Extract(ctx, propagation.HeaderCarrier(h)) + ctx = t.Propagator.Extract(ctx, propagation.HeaderCarrier(h)) return ctx, []trace.SpanStartOption{}, @@ -100,7 +100,7 @@ func (t *Telemetry) ContinueFromHeaders(h http.Header) ConfigureSpanStartFunc { func (t *Telemetry) ContinueFromMap(m map[string]string) ConfigureSpanStartFunc { return func(ctx context.Context) (context.Context, []trace.SpanStartOption, []sentry.SpanOption) { - ctx = t.propagator.Extract(ctx, propagation.MapCarrier(m)) + ctx = t.Propagator.Extract(ctx, propagation.MapCarrier(m)) sentryTrace := m[sentry.SentryTraceHeader] sentryBaggage := m[sentry.SentryBaggageHeader] diff --git a/fiber_middleware.go b/unitelhttp/fiber_middleware.go similarity index 79% rename from fiber_middleware.go rename to unitelhttp/fiber_middleware.go index b5ec754..bbc7031 100644 --- a/fiber_middleware.go +++ b/unitelhttp/fiber_middleware.go @@ -1,4 +1,4 @@ -package unitel +package unitelhttp import ( "fmt" @@ -6,10 +6,12 @@ import ( "slices" "time" + "git.devminer.xyz/devminer/unitel" + "git.devminer.xyz/devminer/unitel/unitelutils" "github.com/getsentry/sentry-go" + "github.com/go-logr/logr" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/rs/zerolog/log" "github.com/valyala/fasthttp/fasthttpadaptor" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -19,7 +21,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -const fiberMwClientID = libBase + "#FiberMiddleware" +const fiberMwClientID = unitelutils.Base + "#FiberMiddleware@" + unitelutils.Version type FiberMiddlewareConfig struct { Repanic bool @@ -28,6 +30,7 @@ type FiberMiddlewareConfig struct { TraceRequestHeaders []string TraceResponseHeaders []string IgnoredRoutes []string + Logger logr.Logger } var fiberMiddlewareConfigDefault = FiberMiddlewareConfig{ @@ -37,17 +40,10 @@ var fiberMiddlewareConfigDefault = FiberMiddlewareConfig{ TraceRequestHeaders: []string{}, TraceResponseHeaders: []string{}, IgnoredRoutes: []string{}, + Logger: logr.Discard(), } -func newFiberMiddlewareTracer(tp trace.TracerProvider) trace.Tracer { - return tp.Tracer(fiberMwClientID, trace.WithInstrumentationVersion(libVersion)) -} - -func newFiberMiddlewareMeter(mp metric.MeterProvider) metric.Meter { - return mp.Meter(fiberMwClientID, metric.WithInstrumentationVersion(libVersion)) -} - -func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handler { +func FiberMiddleware(t *unitel.Telemetry, config ...FiberMiddlewareConfig) fiber.Handler { cfg := fiberMiddlewareConfigDefault if len(config) > 0 { cfg = config[0] @@ -65,8 +61,8 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl cfg.IgnoredRoutes = []string{} } - meter := newFiberMiddlewareMeter(t.meterProvider) - tracer := newFiberMiddlewareTracer(t.tracerProvider) + meter := t.MeterProvider.Meter(fiberMwClientID, metric.WithInstrumentationVersion(unitelutils.Version)) + tracer := t.TracerProvider.Tracer(fiberMwClientID, trace.WithInstrumentationVersion(unitelutils.Version)) mDuration, err := meter.Float64Histogram( "http.server.duration", @@ -74,7 +70,8 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl metric.WithUnit("ms"), ) if err != nil { - log.Fatal().Err(err).Msg("failed to create request duration histogram") + cfg.Logger.Error(err, "Failed to create request duration histogram") + panic(err) } mActiveRequests, err := meter.Int64UpDownCounter( @@ -83,30 +80,33 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl metric.WithUnit("1"), ) if err != nil { - log.Fatal().Err(err).Msg("failed to create active requests counter") + cfg.Logger.Error(err, "Failed to create active requests counter") + panic(err) } mRequestSize, err := meter.Int64Histogram( "http.server.request.size", metric.WithUnit("By"), - metric.WithDescription("HTTP request sizes"), + metric.WithDescription("HTTP request body sizes"), ) if err != nil { - log.Fatal().Err(err).Msg("failed to create request size histogram") + cfg.Logger.Error(err, "Failed to create request body size counter") + panic(err) } mResponseSize, err := meter.Int64Histogram( "http.server.response.size", metric.WithUnit("By"), - metric.WithDescription("HTTP response sizes"), + metric.WithDescription("HTTP response body sizes"), ) if err != nil { - log.Fatal().Err(err).Msg("failed to create response size histogram") + cfg.Logger.Error(err, "Failed to create response body size counter") + panic(err) } return func(c *fiber.Ctx) error { ctx := c.UserContext() - ctx = SetOnContext(t, ctx) + ctx = unitel.SetOnContext(t, ctx) c.SetUserContext(ctx) // Skip ignored routes (/ping for example) @@ -127,7 +127,8 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl return err } - ctx = t.propagator.Extract(ctx, propagation.HeaderCarrier(stdRequest.Header)) + // FIXME: Only extract the headers from trusted servers + ctx = t.Propagator.Extract(ctx, propagation.HeaderCarrier(stdRequest.Header)) hub := sentry.CurrentHub().Clone() if client := hub.Client(); client != nil { @@ -144,13 +145,13 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl ctx, "http.server", description, - WithOtelOptions(trace.WithSpanKind(trace.SpanKindServer)), - WithOtelTracer(tracer), + unitel.WithOtelOptions(trace.WithSpanKind(trace.SpanKindServer)), + unitel.WithOtelTracer(tracer), t.ContinueFromHeaders(stdRequest.Header), ) defer func() { if err := recover(); err != nil { - log.Error().Stack().Msgf("panic()'ed: %v", err) + cfg.Logger.WithCallDepth(0).V(-2).Info("panic()ed: ", "err", err) timeout := (*time.Duration)(nil) if cfg.WaitForDelivery { @@ -168,7 +169,7 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl defer func() { h := propagation.HeaderCarrier{} - t.propagator.Inject(ctx, h) + t.Propagator.Inject(ctx, h) for _, k := range h.Keys() { c.Set(k, h.Get(k)) @@ -235,24 +236,24 @@ func (t *Telemetry) FiberMiddleware(config ...FiberMiddlewareConfig) fiber.Handl } } -func httpStatusToSpanStatus(code int, isServer bool) SpanStatus { +func httpStatusToSpanStatus(code int, isServer bool) unitel.SpanStatus { sentryStatus := sentry.HTTPtoSpanStatus(code) if code < http.StatusBadRequest { - return SpanStatus{codes.Ok, sentryStatus} + return unitel.SpanStatus{codes.Ok, sentryStatus} } if code < http.StatusInternalServerError { // For HTTP status codes in the 4xx range span status MUST be left unset // in case of SpanKind.SERVER and MUST be set to Error in case of SpanKind.CLIENT. if isServer { - return SpanStatus{codes.Unset, sentryStatus} + return unitel.SpanStatus{codes.Unset, sentryStatus} } - return SpanStatus{codes.Error, sentryStatus} + return unitel.SpanStatus{codes.Error, sentryStatus} } - return SpanStatus{codes.Error, sentryStatus} + return unitel.SpanStatus{codes.Error, sentryStatus} } func httpFlavorAttribute(c *fiber.Ctx) attribute.KeyValue { diff --git a/request_logger.go b/unitelhttp/request_logger.go similarity index 78% rename from request_logger.go rename to unitelhttp/request_logger.go index cbcf050..49a3087 100644 --- a/request_logger.go +++ b/unitelhttp/request_logger.go @@ -1,19 +1,19 @@ -package unitel +package unitelhttp import ( "fmt" "time" "github.com/getsentry/sentry-go" + "github.com/go-logr/logr" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/rs/zerolog" "go.opentelemetry.io/otel/trace" ) const reqLoggerBufSize = 1000 -func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber.Handler { +func RequestLogger(l logr.Logger, requestHeaders, responseHeaders bool) fiber.Handler { type request struct { Method string Path string @@ -39,56 +39,54 @@ func RequestLogger(l zerolog.Logger, requestHeaders, responseHeaders bool) fiber for { select { case r := <-reqCh: - l2 := l.Trace(). - Str("method", r.Method). - Str("path", r.Path). - Time("start", r.Start) + attrs := []any{ + "method", r.Method, + "path", r.Path, + "start", r.Start, + } if r.OtelSpanID != nil { - l2 = l2.Str("otel_span_id", r.OtelSpanID.String()) + attrs = append(attrs, "otel_span_id", r.OtelSpanID.String()) } if r.SentrySpanID != nil { - l2 = l2.Str("sentry_span_id", r.SentrySpanID.String()) + attrs = append(attrs, "sentry_span_id", r.SentrySpanID.String()) } if requestHeaders { for k, v := range r.RequestHeaders { for i, vv := range v { - attr := formatHeaderAttribute("request", k, v, i) - - l2 = l2.Str(attr, vv) + attrs = append(attrs, formatHeaderAttribute("request", k, v, i), vv) } } } - l2.Msg("request") + l.V(1).Info("request", attrs...) case r := <-resCh: - l2 := l.Trace(). - Int("status", r.Status). - Time("end", r.End). - Dur("duration", r.Duration) + attrs := []any{ + "status", r.Status, + "end", r.End, + "duration", r.Duration, + } if r.OtelSpanID != nil { - l2 = l2.Str("otel_span_id", r.OtelSpanID.String()) + attrs = append(attrs, "otel_span_id", r.OtelSpanID.String()) } if r.SentrySpanID != nil { - l2 = l2.Str("sentry_span_id", r.SentrySpanID.String()) + attrs = append(attrs, "sentry_span_id", r.SentrySpanID.String()) } if responseHeaders { for k, v := range r.ResponseHeaders { for i, vv := range v { - attr := formatHeaderAttribute("response", k, v, i) - - l2 = l2.Str(attr, vv) + attrs = append(attrs, formatHeaderAttribute("response", k, v, i), vv) } } } - l2.Msg("response") + l.V(1).Info("response", attrs...) } } }() diff --git a/unitelhttp/transport.go b/unitelhttp/transport.go new file mode 100644 index 0000000..4a6c291 --- /dev/null +++ b/unitelhttp/transport.go @@ -0,0 +1,142 @@ +package unitelhttp + +import ( + "fmt" + "net/http" + "time" + + "git.devminer.xyz/devminer/unitel" + "git.devminer.xyz/devminer/unitel/unitelutils" + "github.com/getsentry/sentry-go" + "github.com/go-logr/logr" + "go.opentelemetry.io/otel/attribute" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "go.opentelemetry.io/otel/trace" +) + +const transportClientID = unitelutils.Base + "#HTTPTansport@" + unitelutils.Version + +type HTTPTransportOpt func(t *HTTPTransport) + +func WithLogger(l logr.Logger) HTTPTransportOpt { + return func(t *HTTPTransport) { + t.logger = l + } +} + +type HTTPTransport struct { + logger logr.Logger + telemetry *unitel.Telemetry + transport http.RoundTripper + + forwardTrace bool + + tracedRequestHeaders []string + tracedResponseHeaders []string + + tracer trace.Tracer +} + +func NewTracedTransport(t *unitel.Telemetry, inner http.RoundTripper, forwardTrace bool, tracedRequestHeaders []string, tracedResponseHeaders []string, opts ...HTTPTransportOpt) *HTTPTransport { + transport := &HTTPTransport{ + logger: logr.Discard(), + telemetry: t, + transport: inner, + + forwardTrace: forwardTrace, + + tracedRequestHeaders: tracedRequestHeaders, + tracedResponseHeaders: tracedResponseHeaders, + + tracer: t.TracerProvider.Tracer(transportClientID, trace.WithInstrumentationVersion(unitelutils.Version)), + } + + for _, opt := range opts { + opt(transport) + } + + return transport +} + +func (t *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) { + s := t.telemetry. + StartSpan(req.Context(), "http.client", fmt.Sprintf("%s %s", req.Method, req.URL), unitel.WithOtelOptions(trace.WithSpanKind(trace.SpanKindClient))). + AddAttributes( + semconv.HTTPRequestMethodKey.String(req.Method), + semconv.URLFull(req.URL.String()), + ) + defer s.End() + ctx := s.Context() + req = req.WithContext(ctx) + + if t.forwardTrace { + t.telemetry.InjectIntoHeaders(ctx, req.Header) + } + + for _, header := range t.tracedRequestHeaders { + vv := req.Header.Values(header) + for i, v := range vv { + s.AddAttributes(attribute.String(formatHeaderAttribute("http.request", header, vv, i), v)) + } + } + + start := time.Now() + resp, err := t.transport.RoundTrip(req) + elapsed := time.Since(start) + if err == nil { + t.logger.V(1).Info("fetch succeeded", "url", req.URL.String(), "status", resp.StatusCode, "duration", elapsed) + } else { + t.logger.V(1).Error(err, "fetch failed", "url", req.URL.String(), "duration", elapsed) + + s.CaptureBreadcrumb( + unitel.SeverityError, + unitel.BreadcrumbTypeHTTP, + unitel.BreadcrumbCatagoryHTTP, + fmt.Sprintf("Failed to send request to %s: %v", req.URL.String(), err), + map[string]any{ + "url": req.URL.String(), + "method": req.Method, + "duration": elapsed, + }, + ) + + if hub := sentry.GetHubFromContext(ctx); hub != nil { + hub.CaptureException(err) + } + + return resp, err + } + + { + severity := unitel.SeverityDebug + if resp.StatusCode < http.StatusBadRequest { + severity = unitel.SeverityInfo + } else if resp.StatusCode < http.StatusInternalServerError { + severity = unitel.SeverityError + } + + s.CaptureBreadcrumb( + severity, + unitel.BreadcrumbTypeHTTP, + unitel.BreadcrumbCatagoryHTTP, + req.URL.String(), + map[string]any{ + "url": req.URL.String(), + "method": req.Method, + "status": resp.StatusCode, + }, + ) + } + + s.AddAttributes(semconv.HTTPResponseStatusCode(resp.StatusCode)). + SetStatus(httpStatusToSpanStatus(resp.StatusCode, false), "") + + for _, header := range t.tracedResponseHeaders { + vv := resp.Header.Values(header) + for i, v := range vv { + s.AddAttributes(attribute.String(formatHeaderAttribute("http.response", header, vv, i), v)) + } + } + + return resp, err +} diff --git a/sql_tracing.go b/unitelsql/hooks.go similarity index 65% rename from sql_tracing.go rename to unitelsql/hooks.go index 3dbdd02..5ce6a14 100644 --- a/sql_tracing.go +++ b/unitelsql/hooks.go @@ -1,4 +1,4 @@ -package unitel +package unitelsql import ( "context" @@ -7,6 +7,9 @@ import ( "strings" "time" + "git.devminer.xyz/devminer/unitel" + "git.devminer.xyz/devminer/unitel/unitelutils" + "github.com/go-logr/logr" "github.com/qustavo/sqlhooks/v2" "github.com/rs/zerolog/log" "go.opentelemetry.io/otel/attribute" @@ -18,10 +21,12 @@ import ( // TODO: Port to github.com/loghole/dbhook for proper error handling const ( - sqlClientID = libBase + "#TracedSQL" + sqlClientID = unitelutils.Base + "#TracedSQL@" + unitelutils.Version ) -var dbCtxKey = struct{}{} +type dbCtxKeyT struct{} + +var dbCtxKey = dbCtxKeyT{} type dbCtxVal struct { start time.Time @@ -29,13 +34,49 @@ type dbCtxVal struct { } type tracedSQLHooks struct { + telemetry *unitel.Telemetry + logger logr.Logger + dbType string - t *Telemetry - printQueries bool - tracer trace.Tracer - mDuration metric.Float64Histogram + tracer trace.Tracer +} + +type TracedSQLOpt func(t *tracedSQLHooks) + +func WithLogger(l logr.Logger) TracedSQLOpt { + return func(t *tracedSQLHooks) { + t.logger = l + } +} + +func NewTracedSQL(t *unitel.Telemetry, driver driver.Driver, dbType string, opts ...TracedSQLOpt) driver.Driver { + meter := t.MeterProvider.Meter(sqlClientID, metric.WithInstrumentationVersion(unitelutils.Version)) + mDuration, err := meter.Float64Histogram( + "db.client.operation.duration", + metric.WithDescription("Database query response times"), + metric.WithUnit("ms"), + metric.WithExplicitBucketBoundaries(0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10), + ) + if err != nil { + log.Fatal().Err(err).Msg("failed to create request duration histogram") + } + + traced := &tracedSQLHooks{ + dbType: dbType, + + telemetry: t, + + mDuration: mDuration, + tracer: t.TracerProvider.Tracer(sqlClientID, trace.WithInstrumentationVersion(unitelutils.Version)), + } + + for _, o := range opts { + o(traced) + } + + return sqlhooks.Wrap(driver, traced) } func (h *tracedSQLHooks) Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) { @@ -61,18 +102,17 @@ func (h *tracedSQLHooks) Before(ctx context.Context, query string, args ...inter attrs = append(attrs, attribute.String(fmt.Sprintf("db.query.parameter.%d", i), formatArg(arg))) } - s := h.t.StartSpan(ctx, "db.sql.query", cleanedQuery, WithOtelTracer(h.tracer)) + s := h.telemetry.StartSpan(ctx, "db.sql.query", cleanedQuery, unitel.WithOtelTracer(h.tracer)) s.AddAttributes(attrs...) - if h.printQueries { - l := log.Trace() - - for i, arg := range args { - l = l.Interface(fmt.Sprintf("arg%d", i), arg) - } - - l.Msg(cleanedQuery) + opts := make([]any, 2*len(args)) + for i, arg := range args { + opts = append(opts, fmt.Sprintf("arg%d", i), arg) } + h.logger.Info(cleanedQuery, opts...) + + s.CaptureBreadcrumb(unitel.SeverityDebug, unitel.BreadcrumbTypeQuery, "started", query, map[string]any{"args": args}). + End() return context.WithValue(s.Context(), dbCtxKey, dbCtxVal{ start: time.Now(), @@ -87,39 +127,14 @@ func (h *tracedSQLHooks) After(ctx context.Context, query string, args ...interf h.mDuration.Record(ctx, float64(time.Since(val.start).Milliseconds()), metric.WithAttributes(attrs...)) } - if s := SpanFromContext(ctx); s != nil { - s.CaptureBreadcrumb(SeverityDebug, BreadcrumbTypeQuery, "started", query, map[string]any{"args": args}). + if s := unitel.SpanFromContext(ctx); s != nil { + s.CaptureBreadcrumb(unitel.SeverityDebug, unitel.BreadcrumbTypeQuery, "finished", query, map[string]any{"args": args}). End() } return ctx, nil } -func (t *Telemetry) TraceSQL(driver driver.Driver, dbType string, printQueries bool) driver.Driver { - tracer := t.tracerProvider.Tracer(sqlClientID, trace.WithInstrumentationVersion(libVersion)) - meter := t.meterProvider.Meter(sqlClientID, metric.WithInstrumentationVersion(libVersion)) - - mDuration, err := meter.Float64Histogram( - "db.client.operation.duration", - metric.WithDescription("Database query response times"), - metric.WithUnit("ms"), - metric.WithExplicitBucketBoundaries(0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10), - ) - if err != nil { - log.Fatal().Err(err).Msg("failed to create request duration histogram") - } - - return sqlhooks.Wrap(driver, &tracedSQLHooks{ - dbType: dbType, - - printQueries: printQueries, - t: t, - tracer: tracer, - - mDuration: mDuration, - }) -} - func formatArgs(args []interface{}) []string { formattedArgs := make([]string, len(args)) diff --git a/unitelutils/constants.go b/unitelutils/constants.go new file mode 100644 index 0000000..fc7dcca --- /dev/null +++ b/unitelutils/constants.go @@ -0,0 +1,6 @@ +package unitelutils + +const ( + Base = "git.devminer.xyz/devminer/unitel" + Version = "0.0.1" +) diff --git a/version.go b/version.go deleted file mode 100644 index 95af79c..0000000 --- a/version.go +++ /dev/null @@ -1,6 +0,0 @@ -package unitel - -const ( - libBase = "git.devminer.xyz/devminer/unitel" - libVersion = "0.0.1" -)