diff --git a/go.mod b/go.mod index 91ab0c05559..a097aa67719 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/feast-dev/feast -go 1.23 +go 1.24.0 -toolchain go1.23.12 +toolchain go1.24.4 require ( github.com/apache/arrow/go/v17 v17.0.0 @@ -19,10 +19,16 @@ require ( github.com/roberson-io/mmh3 v0.0.0-20190729202758-fdfce3ba6225 github.com/rs/zerolog v1.33.0 github.com/spaolacci/murmur3 v1.1.0 - github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 - google.golang.org/grpc v1.67.0 - google.golang.org/protobuf v1.34.2 + github.com/stretchr/testify v1.11.1 + go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 + go.opentelemetry.io/otel/sdk v1.38.0 + go.opentelemetry.io/otel/trace v1.38.0 + golang.org/x/sync v0.17.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 + google.golang.org/grpc v1.75.0 + google.golang.org/protobuf v1.36.8 ) require ( @@ -45,12 +51,16 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect github.com/aws/smithy-go v1.22.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect @@ -62,14 +72,17 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.1 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.35.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7778a906ecd..f2530758915 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,6 @@ github.com/apache/arrow/go/v17 v17.0.0 h1:RRR2bdqKcdbss9Gxy2NS/hK8i4LDMh23L6BbkN github.com/apache/arrow/go/v17 v17.0.0/go.mod h1:jR7QHkODl15PfYyjM2nU+yTLScZ/qfj7OSUZmJ8putc= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= -github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E= github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= @@ -18,12 +16,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9 github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= @@ -56,6 +50,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -65,6 +61,11 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -74,16 +75,22 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -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/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 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.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -106,6 +113,8 @@ github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0 github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/roberson-io/mmh3 v0.0.0-20190729202758-fdfce3ba6225 h1:ZMsPCp7oYgjoIFt1c+sM2qojxZXotSYcMF8Ur9/LJlM= github.com/roberson-io/mmh3 v0.0.0-20190729202758-fdfce3ba6225/go.mod h1:XEESr+X1SY8ZSuc3jqsTlb3clCkqQJ4DcF3Qxv1N3PM= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 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= @@ -113,42 +122,65 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -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/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +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/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= -gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= -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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/go/README.md b/go/README.md index eebbfb7d62d..9108216e19d 100644 --- a/go/README.md +++ b/go/README.md @@ -1,12 +1,110 @@ -[Update 10/31/2024] This Go feature server code is updated from the Expedia Group's forked Feast branch (https://github.com/ExpediaGroup/feast.git) on 10/22/2024. Thanks the engineers of the Expedia Groups who contributed and improved the Go feature server. +[Update 10/31/2024] This Go feature server code is updated from the Expedia Group's forked Feast branch (https://github.com/ExpediaGroup/feast.git) on 10/22/2024. Thanks the engineers of the Expedia Groups who contributed and improved the Go Feature Server. -This directory contains the Go logic that's executed by the `EmbeddedOnlineFeatureServer` from Python. - ## Build and Run To build and run the Go Feature Server locally, create a feature_store.yaml file with necessary configurations and run below commands: ```bash - go build -o feast ./go/main.go - ./feast --type=http --port=8080 -``` \ No newline at end of file + go build -o feast-go ./go/main.go + # start the http server + ./feast-go --type=http --port=8080 + # or start the gRPC server + #./feast-go --type=grpc --port=[your-choice] +``` + +## OTEL based observability +The OS level env variable `ENABLE_OTEL_TRACING=="true"/"false"` (string type) is used to enable/disable this service (with Tracing only). + +## List of files have OTEL observability code +1. internal/feast/transformation/transformation.go + +3. internal/feast/onlinestore/redisonlinestore.go +4. internal/feast/server/grpc_server.go +5. internal/feast/server/http_server.go +6. internal/feast/server/server_commons.go +7. internal/feast/featurestore.go + +## Example monitoring infra setup +1. docker compose file to setup Prometheus, Jaeger, and OTEL-collector. +```yaml +services: + prometheus: + image: prom/prometheus + volumes: + - ./prometheus.yaml:/etc/prometheus/prometheus.yaml + ports: + - 9090:9090 # web UI http://localhost:9090 + jaeger: + image: jaegertracing/all-in-one:latest + ports: + - 16686:16686 # Web UI: http://localhost:16686 + - 14268:14268 # http based receiver + - 14250:14250 # gRPC based receiver + otel-collector: + image: otel/opentelemetry-collector-contrib + volumes: + - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml + ports: + #- 1888:1888 # pprof extension + - 8888:8888 # Prometheus metrics exposed by the Collector + - 8889:8889 # Prometheus exporter metrics + #- 13133:13133 # health_check extension + #- 4317:4317 # OTLP gRPC receiver + - 4318:4318 # OTLP http receiver + - 55679:55679 # zpages extension. check http://localhost:55679/debug/tracez + depends_on: + - jaeger + - prometheus +``` +2. OTEL collector configure file. +```yaml +receivers: + otlp: + protocols: + http: + endpoint: 0.0.0.0:4318 + +exporters: + prometheus: + endpoint: 0.0.0.0:8889 + namespace: feast-go + otlp/jarger: # this is a gRPC based exporter. use "otelhttp" for http based exporter. + endpoint: jaeger:4317 + tls: + insecure: true + +extensions: + zpages: + endpoint: 0.0.0.0:55679 + +processors: + batch: + +service: + extensions: [zpages] + pipelines: + metrics: + receivers: [otlp] + exporters: [prometheus] + traces: + receivers: [otlp] + exporters: [otlp/jarger] +``` +3. Prometheus config. +```yaml + #https://github.com/prometheus/prometheus/blob/release-3.6/config/testdata/conf.good.yml + scrape_configs: + - job_name: 'otel-collector' + scrape_interval: 1m + scrape_timeout: 30s # Increase this if needed + static_configs: + # Check the IP address of or Docker host network. + # Refer: https://stackoverflow.com/questions/48546124/what-is-the-linux-equivalent-of-host-docker-internal + - targets: ['172.17.0.1:8888'] # Replace with the Collector's IP and port + - job_name: 'otel-collected' + scrape_interval: 1m + scrape_timeout: 30s # Increase this if needed + static_configs: + - targets: ['172.17.0.1:8889'] # Replace with the Collector's IP and port +``` +4. Jaeger config file is not used in this setup. \ No newline at end of file diff --git a/go/infra/docker/otel/compose.yaml b/go/infra/docker/otel/compose.yaml new file mode 100644 index 00000000000..7872797d205 --- /dev/null +++ b/go/infra/docker/otel/compose.yaml @@ -0,0 +1,29 @@ +services: + prometheus: + image: prom/prometheus + volumes: + - ./prometheus.yaml:/etc/prometheus/prometheus.yaml + ports: + - 9090:9090 + jaeger: + image: jaegertracing/all-in-one:latest + #volumes: + # - ./jaeger.yaml:/jaeger/config.yaml + ports: + - 16686:16686 # Web UI: http://localhost:16686 + - 14268:14268 # http based receiver + - 14250:14250 # gRPC based receiver + otel-collector: + image: otel/opentelemetry-collector-contrib + volumes: + - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml + ports: + #- 1888:1888 # pprof extension + - 8888:8888 # Prometheus metrics exposed by the Collector + - 8889:8889 # Prometheus exporter metrics + #- 13133:13133 # health_check extension + #- 4317:4317 # OTLP gRPC receiver + - 4318:4318 # OTLP http receiver + - 55679:55679 # zpages extension + depends_on: + - jaeger \ No newline at end of file diff --git a/go/infra/docker/otel/otel-collector-config.yaml b/go/infra/docker/otel/otel-collector-config.yaml new file mode 100644 index 00000000000..475812f2eda --- /dev/null +++ b/go/infra/docker/otel/otel-collector-config.yaml @@ -0,0 +1,31 @@ +receivers: + otlp: + protocols: + http: + endpoint: 0.0.0.0:4318 + +exporters: + prometheus: + endpoint: 0.0.0.0:8889 + namespace: feast-go + otlp/jarger: + endpoint: jaeger:4317 + tls: + insecure: true + +extensions: + zpages: + endpoint: 0.0.0.0:55679 + +processors: + batch: + +service: + extensions: [zpages] + pipelines: + metrics: + receivers: [otlp] + exporters: [prometheus] + traces: + receivers: [otlp] + exporters: [otlp/jarger] \ No newline at end of file diff --git a/go/infra/docker/otel/prometheus.yaml b/go/infra/docker/otel/prometheus.yaml new file mode 100644 index 00000000000..8ab32f38870 --- /dev/null +++ b/go/infra/docker/otel/prometheus.yaml @@ -0,0 +1,14 @@ + #https://github.com/prometheus/prometheus/blob/release-3.6/config/testdata/conf.good.yml + scrape_configs: + - job_name: 'otel-collector' + scrape_interval: 1m + scrape_timeout: 30s # Increase this if needed + static_configs: + # Check the IP address of or Docker host network. + # Refer: https://stackoverflow.com/questions/48546124/what-is-the-linux-equivalent-of-host-docker-internal + - targets: ['172.17.0.1:8888'] # Replace with the Collector's IP and port + - job_name: 'otel-collected' + scrape_interval: 1m + scrape_timeout: 30s # Increase this if needed + static_configs: + - targets: ['172.17.0.1:8889'] # Replace with the Collector's IP and port \ No newline at end of file diff --git a/go/internal/feast/featurestore.go b/go/internal/feast/featurestore.go index abe1d195def..f6abd50e3d1 100644 --- a/go/internal/feast/featurestore.go +++ b/go/internal/feast/featurestore.go @@ -7,6 +7,7 @@ import ( "github.com/apache/arrow/go/v17/arrow/memory" //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "go.opentelemetry.io/otel" "github.com/feast-dev/feast/go/internal/feast/model" "github.com/feast-dev/feast/go/internal/feast/onlineserving" @@ -17,6 +18,8 @@ import ( prototypes "github.com/feast-dev/feast/go/protos/feast/types" ) +var tracer = otel.Tracer("github.com/feast-dev/feast/go/feast") + type FeatureStore struct { config *registry.RepoConfig registry *registry.Registry @@ -322,8 +325,8 @@ func (fs *FeatureStore) readFromOnlineStore(ctx context.Context, entityRows []*p requestedFeatureNames []string, ) ([][]onlinestore.FeatureData, error) { // Create a Datadog span from context - //span, _ := tracer.StartSpanFromContext(ctx, "fs.readFromOnlineStore") - //defer span.Finish() + ctx, span := tracer.Start(ctx, "fs.readFromOnlineStore") + defer span.End() numRows := len(entityRows) entityRowsValue := make([]*prototypes.EntityKey, numRows) diff --git a/go/internal/feast/onlinestore/redisonlinestore.go b/go/internal/feast/onlinestore/redisonlinestore.go index 3fa6cf580c7..222fcdc4ec5 100644 --- a/go/internal/feast/onlinestore/redisonlinestore.go +++ b/go/internal/feast/onlinestore/redisonlinestore.go @@ -11,7 +11,7 @@ import ( "strings" "github.com/feast-dev/feast/go/internal/feast/registry" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "go.opentelemetry.io/otel" "github.com/redis/go-redis/v9" "github.com/spaolacci/murmur3" @@ -24,6 +24,7 @@ import ( //redistrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/redis/go-redis.v9" ) +var tracer = otel.Tracer("github.com/feast-dev/feast/go/onlinestore") type redisType int const ( @@ -211,8 +212,8 @@ func (r *RedisOnlineStore) buildRedisKeys(entityKeys []*types.EntityKey) ([]*[]b } func (r *RedisOnlineStore) OnlineRead(ctx context.Context, entityKeys []*types.EntityKey, featureViewNames []string, featureNames []string) ([][]FeatureData, error) { - //span, _ := tracer.StartSpanFromContext(ctx, "redis.OnlineRead") - //defer span.Finish() + ctx, span := tracer.Start(ctx, "redis.OnlineRead") + defer span.End() featureCount := len(featureNames) featureViewIndices, indicesFeatureView, index := r.buildFeatureViewIndices(featureViewNames, featureNames) diff --git a/go/internal/feast/server/grpc_server.go b/go/internal/feast/server/grpc_server.go index d5e18b1c9ef..490afa3d63a 100644 --- a/go/internal/feast/server/grpc_server.go +++ b/go/internal/feast/server/grpc_server.go @@ -9,11 +9,12 @@ import ( prototypes "github.com/feast-dev/feast/go/protos/feast/types" "github.com/feast-dev/feast/go/types" "github.com/google/uuid" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + ) const feastServerVersion = "0.0.1" + type grpcServingServiceServer struct { fs *feast.FeatureStore loggingService *logging.LoggingService @@ -34,16 +35,16 @@ func (s *grpcServingServiceServer) GetFeastServingInfo(ctx context.Context, requ // Metadata contains feature names that corresponds to the number of rows in response.Results. // Results contains values including the value of the feature, the event timestamp, and feature status in a columnar format. func (s *grpcServingServiceServer) GetOnlineFeatures(ctx context.Context, request *serving.GetOnlineFeaturesRequest) (*serving.GetOnlineFeaturesResponse, error) { - //span, ctx := tracer.StartSpanFromContext(ctx, "getOnlineFeatures", tracer.ResourceName("ServingService/GetOnlineFeatures")) - //defer span.Finish() + ctx, span := tracer.Start(ctx, "server.getOnlineFeatures") + defer span.End() - //logSpanContext := LogWithSpanContext(span) + logSpanContext := LogWithSpanContext(span) requestId := GenerateRequestId() featuresOrService, err := s.fs.ParseFeatures(request.GetKind()) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error parsing feature service or feature list from request") + logSpanContext.Error().Err(err).Msg("Error parsing feature service or feature list from request") return nil, err } @@ -56,7 +57,7 @@ func (s *grpcServingServiceServer) GetOnlineFeatures(ctx context.Context, reques request.GetFullFeatureNames()) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error getting online features") + logSpanContext.Error().Err(err).Msg("Error getting online features") return nil, err } @@ -75,7 +76,7 @@ func (s *grpcServingServiceServer) GetOnlineFeatures(ctx context.Context, reques featureNames[idx] = vector.Name values, err := types.ArrowValuesToProtoValues(vector.Values) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error converting Arrow values to proto values") + logSpanContext.Error().Err(err).Msg("Error converting Arrow values to proto values") return nil, err } if _, ok := request.Entities[vector.Name]; ok { @@ -93,13 +94,13 @@ func (s *grpcServingServiceServer) GetOnlineFeatures(ctx context.Context, reques if featureService != nil && featureService.LoggingConfig != nil && s.loggingService != nil { logger, err := s.loggingService.GetOrCreateLogger(featureService) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error to instantiating logger for feature service: " + featuresOrService.FeatureService.Name) + logSpanContext.Error().Err(err).Msg("Error to instantiating logger for feature service: " + featuresOrService.FeatureService.Name) fmt.Printf("Couldn't instantiate logger for feature service %s: %+v", featuresOrService.FeatureService.Name, err) } err = logger.Log(request.Entities, resp.Results[len(request.Entities):], resp.Metadata.FeatureNames.Val[len(request.Entities):], request.RequestContext, requestId) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error to logging to feature service: " + featuresOrService.FeatureService.Name) + logSpanContext.Error().Err(err).Msg("Error to logging to feature service: " + featuresOrService.FeatureService.Name) fmt.Printf("LoggerImpl error[%s]: %+v", featuresOrService.FeatureService.Name, err) } } diff --git a/go/internal/feast/server/http_server.go b/go/internal/feast/server/http_server.go index def58aedb88..312a0a6352e 100644 --- a/go/internal/feast/server/http_server.go +++ b/go/internal/feast/server/http_server.go @@ -5,10 +5,8 @@ import ( "encoding/json" "fmt" "net/http" - //"os" "runtime" "strconv" - //"strings" "time" "github.com/feast-dev/feast/go/internal/feast" @@ -19,8 +17,6 @@ import ( prototypes "github.com/feast-dev/feast/go/protos/feast/types" "github.com/feast-dev/feast/go/types" "github.com/rs/zerolog/log" - //httptrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) type httpServer struct { @@ -150,10 +146,10 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { var err error ctx := r.Context() - //span, ctx := tracer.StartSpanFromContext(r.Context(), "getOnlineFeatures", tracer.ResourceName("/get-online-features")) - //defer span.Finish(tracer.WithError(err)) + ctx, span := tracer.Start(r.Context(), "server.getOnlineFeatures") + defer span.End() - //logSpanContext := LogWithSpanContext(span) + logSpanContext := LogWithSpanContext(span) if r.Method != "POST" { http.NotFound(w, r) @@ -166,7 +162,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { if statusQuery != "" { status, err = strconv.ParseBool(statusQuery) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error parsing status query parameter") + logSpanContext.Error().Err(err).Msg("Error parsing status query parameter") writeJSONError(w, fmt.Errorf("Error parsing status query parameter: %+v", err), http.StatusBadRequest) return } @@ -176,7 +172,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { var request getOnlineFeaturesRequest err = decoder.Decode(&request) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error decoding JSON request data") + logSpanContext.Error().Err(err).Msg("Error decoding JSON request data") writeJSONError(w, fmt.Errorf("Error decoding JSON request data: %+v", err), http.StatusInternalServerError) return } @@ -184,7 +180,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { if request.FeatureService != nil { featureService, err = s.fs.GetFeatureService(*request.FeatureService) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error getting feature service from registry") + logSpanContext.Error().Err(err).Msg("Error getting feature service from registry") writeJSONError(w, fmt.Errorf("Error getting feature service from registry: %+v", err), http.StatusInternalServerError) return } @@ -207,7 +203,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { request.FullFeatureNames) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error getting feature vector") + logSpanContext.Error().Err(err).Msg("Error getting feature vector") writeJSONError(w, fmt.Errorf("Error getting feature vector: %+v", err), http.StatusInternalServerError) return } @@ -249,7 +245,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(response) if err != nil { - //logSpanContext.Error().Err(err).Msg("Error encoding response") + logSpanContext.Error().Err(err).Msg("Error encoding response") writeJSONError(w, fmt.Errorf("Error encoding response: %+v", err), http.StatusInternalServerError) return } @@ -257,7 +253,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { if featureService != nil && featureService.LoggingConfig != nil && s.loggingService != nil { logger, err := s.loggingService.GetOrCreateLogger(featureService) if err != nil { - //logSpanContext.Error().Err(err).Msgf("Couldn't instantiate logger for feature service %s", featureService.Name) + logSpanContext.Error().Err(err).Msgf("Couldn't instantiate logger for feature service %s", featureService.Name) writeJSONError(w, fmt.Errorf("Couldn't instantiate logger for feature service %s: %+v", featureService.Name, err), http.StatusInternalServerError) return } @@ -270,7 +266,7 @@ func (s *httpServer) getOnlineFeatures(w http.ResponseWriter, r *http.Request) { for _, vector := range featureVectors[len(request.Entities):] { values, err := types.ArrowValuesToProtoValues(vector.Values) if err != nil { - //logSpanContext.Error().Err(err).Msg("Couldn't convert arrow values into protobuf") + logSpanContext.Error().Err(err).Msg("Couldn't convert arrow values into protobuf") writeJSONError(w, fmt.Errorf("Couldn't convert arrow values into protobuf: %+v", err), http.StatusInternalServerError) return } @@ -340,11 +336,6 @@ func recoverMiddleware(next http.Handler) http.Handler { } func (s *httpServer) Serve(host string, port int) error { - // DD - //if strings.ToLower(os.Getenv("ENABLE_DATADOG_TRACING")) == "true" { - // tracer.Start(tracer.WithRuntimeMetrics()) - // defer tracer.Stop() - //} mux := http.NewServeMux() mux.Handle("/get-online-features", recoverMiddleware(http.HandlerFunc(s.getOnlineFeatures))) mux.HandleFunc("/health", healthCheckHandler) diff --git a/go/internal/feast/server/server_commons.go b/go/internal/feast/server/server_commons.go index 140269d5c1c..7a78c622f02 100644 --- a/go/internal/feast/server/server_commons.go +++ b/go/internal/feast/server/server_commons.go @@ -1,31 +1,25 @@ package server import ( - "github.com/rs/zerolog" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "os" -) -func LogWiwithSpanContext() zerolog.Logger { - var logger = zerolog.New(os.Stderr).With(). - Timestamp(). - Logger() + "github.com/rs/zerolog" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel" +) - return logger -} +var tracer = otel.Tracer("github.com/feast-dev/feast/go/server") -/* -func LogWithSpanContext(span tracer.Span) zerolog.Logger { - spanContext := span.Context() +func LogWithSpanContext(span trace.Span) zerolog.Logger { + spanContext := span.SpanContext() var logger = zerolog.New(os.Stderr).With(). + Timestamp(). + Logger(). + Hex("trace_id", spanContext.TraceID()). + Hex("span_id", spanContext.SpanID()). Timestamp(). Logger() - //Int64("trace_id", int64(spanContext.TraceID())). - //Int64("span_id", int64(spanContext.SpanID())). - //Timestamp(). - //Logger() return logger } -*/ diff --git a/go/internal/feast/transformation/transformation.go b/go/internal/feast/transformation/transformation.go index d6df03039d7..1080967b664 100644 --- a/go/internal/feast/transformation/transformation.go +++ b/go/internal/feast/transformation/transformation.go @@ -9,7 +9,7 @@ import ( "github.com/apache/arrow/go/v17/arrow" "github.com/apache/arrow/go/v17/arrow/memory" "github.com/rs/zerolog/log" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "go.opentelemetry.io/otel" "github.com/feast-dev/feast/go/internal/feast/model" "github.com/feast-dev/feast/go/internal/feast/onlineserving" @@ -17,6 +17,8 @@ import ( "github.com/feast-dev/feast/go/types" ) +var tracer = otel.Tracer("github.com/feast-dev/feast/go/transformation") + /* TransformationCallback is a Python callback function's expected signature. The function should accept name of the on demand feature view and pointers to input & output record batches. @@ -40,8 +42,8 @@ func AugmentResponseWithOnDemandTransforms( fullFeatureNames bool, ) ([]*onlineserving.FeatureVector, error) { - //span, _ := tracer.StartSpanFromContext(ctx, "transformation.AugmentResponseWithOnDemandTransforms") - //defer span.Finish() + ctx, span := tracer.Start(ctx, "transformation.AugmentResponseWithOnDemandTransforms") + defer span.End() result := make([]*onlineserving.FeatureVector, 0) var err error diff --git a/go/main.go b/go/main.go index feb54faa2e0..e23ac0b727e 100644 --- a/go/main.go +++ b/go/main.go @@ -1,12 +1,13 @@ package main import ( + "context" "flag" "fmt" "net" "os" "os/signal" - //"strings" + "strings" "syscall" "github.com/feast-dev/feast/go/internal/feast" @@ -18,10 +19,18 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" - //grpctrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/google.golang.org/grpc" - //"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.37.0" + "go.opentelemetry.io/otel/trace" ) +var tracer trace.Tracer + type ServerStarter interface { StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error @@ -56,6 +65,30 @@ func main() { flag.IntVar(&port, "port", port, "Specify a port for the server") flag.Parse() + // Initial tracer + if OTELTracingEnabled() { + ctx := context.Background() + + exp, err := newExporter(ctx) + if err != nil { + log.Fatal().Stack().Err(err).Msg("Failed to initialize exporter.") + } + + // Create a new tracer provider with a batch span processor and the given exporter. + tp, err := newTracerProvider(exp) + if err != nil { + log.Fatal().Stack().Err(err).Msg("Failed to initialize tracer provider.") + } + + // Handle shutdown properly so nothing leaks. + defer func() { _ = tp.Shutdown(ctx) }() + + otel.SetTracerProvider(tp) + + // Finally, set the tracer that can be used for this package. + tracer = tp.Tracer("github.com/feast-dev/feast/go") + } + repoConfig, err := registry.NewRepoConfigFromFile(repoPath) if err != nil { log.Fatal().Stack().Err(err).Msg("Failed to convert to RepoConfig") @@ -110,11 +143,6 @@ func constructLoggingService(fs *feast.FeatureStore, writeLoggedFeaturesCallback // StartGprcServerWithLogging starts gRPC server with enabled feature logging func StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { - // #DD - //if strings.ToLower(os.Getenv("ENABLE_DATADOG_TRACING")) == "true" { - // tracer.Start(tracer.WithRuntimeMetrics()) - // defer tracer.Stop() - //} loggingService, err := constructLoggingService(fs, writeLoggedFeaturesCallback, loggingOpts) if err != nil { return err @@ -178,3 +206,35 @@ func StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedF return ser.Serve(host, port) } + +func OTELTracingEnabled() bool { + return strings.ToLower(os.Getenv("ENABLE_OTEL_TRACING")) == "true" +} + +func newExporter(ctx context.Context) (*otlptrace.Exporter, error) { + exp, err := otlptracehttp.New(ctx) + if err != nil { + return nil, err + } + return exp, nil +} + +func newTracerProvider(exp sdktrace.SpanExporter) (*sdktrace.TracerProvider, error) { + r, err := resource.Merge( + resource.Default(), + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceName("FeastGoFeatureServer"), + ), + ) + + if err != nil { + return nil, err + } + + return sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exp), + sdktrace.WithResource(r), + ), nil +} +