Skip to content

Commit

Permalink
Merge pull request #9 from ex0rcist/iter9
Browse files Browse the repository at this point in the history
Инкремент №9
  • Loading branch information
ex0rcist authored Jul 29, 2024
2 parents 8a78ecc + 09ac024 commit 431312f
Show file tree
Hide file tree
Showing 50 changed files with 2,941 additions and 450 deletions.
Binary file modified .DS_Store
Binary file not shown.
4 changes: 0 additions & 4 deletions cmd/agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,5 @@ func main() {
logging.LogFatal(err)
}

logging.LogInfo(agnt.Config.String())

agnt.Run()

logging.LogInfo("agent ready")
}
8 changes: 0 additions & 8 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ func main() {
logging.LogFatal(err)
}

err = srv.ParseFlags()
if err != nil {
logging.LogFatal(err)
}

logging.LogInfo(srv.Config.String())
logging.LogInfo("server ready") // TODO: must be after run?

err = srv.Run()
if err != nil {
logging.LogFatal(err)
Expand Down
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ go 1.22.4

require (
github.com/caarlos0/env/v11 v11.1.0
github.com/go-chi/chi v1.5.5
github.com/go-chi/chi/v5 v5.1.0
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0
github.com/satori/go.uuid v1.2.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
)
Expand All @@ -15,7 +16,9 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.21.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/sys v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ github.com/caarlos0/env/v11 v11.1.0/go.mod h1:LwgkYk1kDvfGpHthrWWLof3Ny7PezzFwS4
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
Expand All @@ -18,15 +20,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
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/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
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=
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/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
24 changes: 11 additions & 13 deletions internal/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/caarlos0/env/v11"
"github.com/ex0rcist/metflix/internal/entities"
"github.com/ex0rcist/metflix/internal/logging"
"github.com/ex0rcist/metflix/internal/utils"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -45,7 +46,7 @@ func New() (*Agent, error) {
func (a *Agent) ParseFlags() error {
address := a.Config.Address

pflag.VarP(&address, "address", "a", "address:port for HTTP API requests") // HELP: "&"" because Set() has pointer receiver?
pflag.VarP(&address, "address", "a", "address:port for HTTP API requests")

pflag.IntVarP(&a.Config.PollInterval, "poll-interval", "p", a.Config.PollInterval, "interval (s) for polling stats")
pflag.IntVarP(&a.Config.ReportInterval, "report-interval", "r", a.Config.ReportInterval, "interval (s) for polling stats")
Expand All @@ -68,6 +69,9 @@ func (a *Agent) ParseFlags() error {
}

func (a *Agent) Run() {
logging.LogInfo(a.Config.String())
logging.LogInfo("agent ready")

a.wg.Add(2)

go a.startPolling()
Expand All @@ -85,15 +89,15 @@ func (a *Agent) startPolling() {
logging.LogError(err)
}

time.Sleep(intToDuration(a.Config.PollInterval))
time.Sleep(utils.IntToDuration(a.Config.PollInterval))
}
}

func (a *Agent) startReporting() {
defer a.wg.Done()

for {
time.Sleep(intToDuration(a.Config.ReportInterval))
time.Sleep(utils.IntToDuration(a.Config.ReportInterval))

a.reportStats()
}
Expand Down Expand Up @@ -144,15 +148,9 @@ func (a *Agent) reportStats() {
a.Stats.PollCount -= snapshot.PollCount
}

func intToDuration(s int) time.Duration {
return time.Duration(s) * time.Second
}

func (c Config) String() string {
out := "agent config: "

out += fmt.Sprintf("address=%v \t", c.Address)
out += fmt.Sprintf("poll-interval=%v \t", c.PollInterval)
out += fmt.Sprintf("report-interval=%v \t", c.ReportInterval)
return out
return fmt.Sprintf(
"agent config: address=%v; poll-interval=%v; report-interval=%v",
c.Address, c.PollInterval, c.ReportInterval,
)
}
77 changes: 66 additions & 11 deletions internal/agent/api.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package agent

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"

"github.com/ex0rcist/metflix/internal/compression"
"github.com/ex0rcist/metflix/internal/entities"
"github.com/ex0rcist/metflix/internal/logging"
"github.com/ex0rcist/metflix/internal/metrics"
"github.com/ex0rcist/metflix/internal/utils"
"github.com/rs/zerolog/log"
)

type API struct {
Expand All @@ -33,34 +38,84 @@ func NewAPI(address *entities.Address, httpTransport http.RoundTripper) *API {
}

func (c *API) Report(name string, metric metrics.Metric) *API {
// todo: another transport?
url := "http://" + c.address.String() + fmt.Sprintf("/update/%s/%s/%s", metric.Kind(), name, metric)
url := "http://" + c.address.String() + "/update"

req, err := http.NewRequest(http.MethodPost, url, http.NoBody)
requestID := utils.GenerateRequestID()
ctx := setupLoggerCtx(requestID)
var mex metrics.MetricExchange

switch metric.Kind() {
case metrics.KindCounter:
mex = metrics.NewUpdateCounterMex(name, metric.(metrics.Counter))
case metrics.KindGauge:
mex = metrics.NewUpdateGaugeMex(name, metric.(metrics.Gauge))
default:
logging.LogError(entities.ErrMetricReport, "unknown metric")
return c
}

body, err := json.Marshal(mex)
if err != nil {
logging.LogError(err, "httpRequest error")
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "error during marshaling", err.Error())
return c
}

req.Header.Set("Content-Type", "text/plain")
payload, err := compression.Pack(body)
if err != nil {
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "error during compression", err.Error())
return c
}

logging.LogInfo(fmt.Sprintf("sending POST to %v", url))
req, err := http.NewRequest(http.MethodPost, url, payload)
if err != nil {
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "httpRequest error", err.Error())
return c
}

resp, err := c.httpClient.Do(req)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("X-Request-Id", requestID)

logRequest(ctx, url, req.Header, body)

resp, err := c.httpClient.Do(req)
if err != nil {
logging.LogError(err, "httpClient error")
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "error making http request", err.Error())
return c
}

defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body) // нужно прочитать ответ для keepalive?
respBody, err := io.ReadAll(resp.Body)
if err != nil {
logging.LogError(entities.ErrMetricReport, "error reading response body")
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "error reading response body", err.Error())
return c
}

logResponse(ctx, resp, respBody)

if resp.StatusCode != http.StatusOK {
logging.LogError(entities.ErrMetricReport, string(respBody))
logging.LogErrorCtx(ctx, entities.ErrMetricReport, "error reporting stat", resp.Status, string(respBody))
}

return c
}

func setupLoggerCtx(requestID string) context.Context {
// empty context for now
ctx := context.Background()

// setup logger with rid attached
logger := log.Logger.With().Ctx(ctx).Str("rid", requestID).Logger()

// return context for logging
return logger.WithContext(ctx)
}

func logRequest(ctx context.Context, url string, headers http.Header, body []byte) {
logging.LogInfoCtx(ctx, "sending request to: "+url)
logging.LogDebugCtx(ctx, fmt.Sprintf("request: headers=%s; body=%s", utils.HeadersToStr(headers), string(body)))
}

func logResponse(ctx context.Context, resp *http.Response, respBody []byte) {
logging.LogDebugCtx(ctx, fmt.Sprintf("response: %v; headers=%s; body=%s", resp.Status, utils.HeadersToStr(resp.Header), respBody))
}
18 changes: 16 additions & 2 deletions internal/agent/api_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package agent

import (
"encoding/json"
"io"
"net/http"
"testing"

"github.com/ex0rcist/metflix/internal/compression"
"github.com/ex0rcist/metflix/internal/entities"
"github.com/ex0rcist/metflix/internal/metrics"
"github.com/stretchr/testify/assert"
Expand All @@ -29,9 +32,20 @@ func TestNewApi(t *testing.T) {

func TestApiClientReport(t *testing.T) {
rtf := func(req *http.Request) *http.Response {
assert.Equal(t, "http://localhost:8080/update/counter/Test/0", req.URL.String())
assert.Equal(t, "http://localhost:8080/update", req.URL.String())
assert.Equal(t, http.MethodPost, req.Method)

payload, err := json.Marshal(metrics.NewUpdateCounterMex("test", 42))
require.NoError(t, err)

expectedPayload, err := compression.Pack(payload)
require.NoError(t, err)

actualPayload, err := io.ReadAll(req.Body)
require.NoError(t, err)

assert.Equal(t, expectedPayload.Bytes(), actualPayload)

return &http.Response{
StatusCode: 200,
Body: http.NoBody,
Expand All @@ -42,5 +56,5 @@ func TestApiClientReport(t *testing.T) {
address := entities.Address("localhost:8080")

api := NewAPI(&address, RoundTripFunc(rtf))
api.Report("Test", metrics.Counter(0))
api.Report("test", metrics.Counter(42))
}
2 changes: 1 addition & 1 deletion internal/agent/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func NewStats() *Stats {
}

func (m *Stats) Poll() error {
logging.LogInfo("polling stats ... ")
logging.LogDebug("polling stats ... ")

m.PollCount++
m.RandomValue = metrics.Gauge(m.generator.Float64())
Expand Down
26 changes: 26 additions & 0 deletions internal/compression/compression.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package compression

import (
"bytes"
"compress/gzip"
"fmt"
)

func Pack(data []byte) (*bytes.Buffer, error) {
bb := new(bytes.Buffer)

encoder, err := gzip.NewWriterLevel(bb, gzip.BestSpeed)
if err != nil {
return nil, fmt.Errorf("failed init compress writer: %v", err)
}

if _, err = encoder.Write(data); err != nil {
return nil, fmt.Errorf("failed write data to compress temporary buffer: %v", err)
}

if err = encoder.Close(); err != nil {
return nil, fmt.Errorf("failed compress data: %v", err)
}

return bb, nil
}
31 changes: 31 additions & 0 deletions internal/compression/compression_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package compression

import (
"bytes"
"compress/gzip"
"io"
"testing"
)

func TestPack_Success(t *testing.T) {
data := []byte("test data")
buffer, err := Pack(data)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}

reader, err := gzip.NewReader(buffer)
if err != nil {
t.Fatalf("expected no error creating gzip reader, got %v", err)
}
defer reader.Close()

unpackedData, err := io.ReadAll(reader)
if err != nil {
t.Fatalf("expected no error reading from gzip reader, got %v", err)
}

if !bytes.Equal(data, unpackedData) {
t.Fatalf("expected %s, got %s", data, unpackedData)
}
}
Loading

0 comments on commit 431312f

Please sign in to comment.