Skip to content

Commit

Permalink
implement grpc client
Browse files Browse the repository at this point in the history
  • Loading branch information
The-Gleb committed Mar 31, 2024
1 parent 07f8fb4 commit cf3c375
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 139 deletions.
108 changes: 108 additions & 0 deletions cmd/agent/grpc_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package main

import (
"context"
"log"

"github.com/The-Gleb/go_metrics_and_alerting/internal/domain/entity"
"github.com/The-Gleb/go_metrics_and_alerting/internal/logger"
metrics "github.com/The-Gleb/go_metrics_and_alerting/internal/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

type grpcClient struct {
client metrics.MetricServiceClient
signKey []byte
publicKeyPath string
}

func NewGRPCClient(
address string, signKey []byte, publicKeyPath string,
) (*grpcClient, error) {
conn, err := grpc.Dial(
address,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithChainUnaryInterceptor(),
)
if err != nil {
return nil, err
}

c := metrics.NewMetricServiceClient(conn)

// TODO: interceptors

return &grpcClient{
client: c,
signKey: signKey,
publicKeyPath: publicKeyPath,
}, nil

}

// func (c *grpcClient) SomeInterceptor(
// ctx context.Context, method string, req any, reply any, cc *grpc.ClientConn,
// invoker grpc.UnaryInvoker, opts ...grpc.CallOption,
// ) error {

// }

func (c *grpcClient) SendMetricSet(metricsMap *metricsMap) {
metricStructs := make([]*metrics.UpdateMetricRequest, 0)

for name, value := range metricsMap.Gauge {

m := metrics.UpdateMetricRequest{
Type: metrics.MetricType_GAUGE,
Name: name,
Value: value,
}

metricStructs = append(metricStructs, &m)

}

metricStructs = append(metricStructs, &metrics.UpdateMetricRequest{
Type: metrics.MetricType_COUNTER,
Name: "PollCount",
Delta: metricsMap.PollCount.Load(),
})

in := &metrics.UpdateMetricSetRequest{
Metrics: metricStructs,
}

logger.Log.Debug("METRICS TO SEND")
logger.Log.Debug(metricStructs)

resp, err := c.client.UpdateMetricSet(context.Background(), in)
if err != nil {
log.Fatal(err)
}

logger.Log.Debugf("%d metrics updated", resp.GetUpdatedNum())

}

func (c *grpcClient) GetAllMetrics() ([]entity.Metric, error) {
resp, err := c.client.GetAllMetrics(context.Background(), &metrics.GetAllMetricsRequest{})
if err != nil {
return nil, err
}

metricStructs := make([]entity.Metric, len(resp.Metrics))

for _, m := range resp.Metrics {
counter := m.GetCounterValue()

metricStructs = append(metricStructs, entity.Metric{
MType: metrics.MetricType_name[int32(m.Type)],
ID: m.GetName(),
Value: &m.GaugeValue,
Delta: &counter,
})
}

return metricStructs, nil
}
189 changes: 189 additions & 0 deletions cmd/agent/http_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package main

import (
"bytes"
"compress/gzip"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"time"

"github.com/The-Gleb/go_metrics_and_alerting/internal/domain/entity"
"github.com/The-Gleb/go_metrics_and_alerting/internal/logger"
"github.com/go-resty/resty/v2"
)

type httpClient struct {
c *resty.Client
publicKeyPath string
signKey []byte
}

func NewHTTPClient(
address string,
signKey []byte,
publicKeyPath string,
) (*httpClient, error) {
baseURL := fmt.Sprintf("http://%s", address)
client := resty.New()
client.
SetRetryCount(3).
SetRetryMaxWaitTime(5 * time.Second).
SetRetryAfter(func(c *resty.Client, r *resty.Response) (time.Duration, error) {
logger.Log.Debug("attempt: %d", r.Request.Attempt)
dur := time.Duration(r.Request.Attempt*2-1) * time.Second
return dur, nil
}).
SetBaseURL(baseURL)

return &httpClient{
c: client,
publicKeyPath: publicKeyPath,
signKey: signKey,
}, nil
}

func (c *httpClient) SendMetricSet(metrics *metricsMap) {
metricStructs := make([]entity.Metric, 0)

metrics.mu.RLock()
for name, value := range metrics.Gauge {
metricStructs = append(metricStructs, entity.Metric{
MType: "gauge",
ID: name,
Value: &value,
})
}
metrics.mu.RUnlock()

counter := metrics.PollCount.Load()
metricStructs = append(metricStructs, entity.Metric{
MType: "counter",
ID: "PollCount",
Delta: &counter,
})

data, err := json.Marshal(metricStructs)
if err != nil {
log.Fatal(err)
}

logger.Log.Debug("sent body is", string(data))

var sign []byte
if len(c.signKey) > 0 {
sign, err = hash(data, c.signKey)
if err != nil {
log.Fatal(err)
}

logger.Log.Debug("signKey is ", string(c.signKey))
logger.Log.Debug("hex encoded signature is ", hex.EncodeToString(sign))
}

buf := bytes.Buffer{}
gw := gzip.NewWriter(&buf)
gw.Write(data)
err = gw.Close()
if err != nil {
log.Fatal(err)
}

body := buf.Bytes()

if c.publicKeyPath != "" {
var err error
body, err = encrypt(body, c.publicKeyPath)
if err != nil {
log.Fatal(err)
}
}

resp, err := c.c.R().
SetHeader("Content-Type", "application/json").
SetHeader("Content-Encoding", "gzip").
SetHeader("Accept-Encoding", "gzip").
SetHeader("HashSHA256", hex.EncodeToString(sign)).
SetHeader("X-Real-IP", "127.0.0.1").
SetBody(body).
Post("/updates/")
if err != nil {
log.Fatal(err)
return
}

// logger.Log.Debug(resp.Header().Get("Content-Encoding"))
logger.Log.Debugf("response code %d", resp.StatusCode())
logger.Log.Debugf("response body %d", string(resp.Body()))

}

func (c *httpClient) SendMetricsJSON(metrics *metricsMap) {
pollCount := metrics.PollCount.Load()

for name, val := range metrics.Gauge {
var result entity.Metric
_, err := c.c.R().
SetBody(&entity.Metric{
ID: name,
MType: "gauge",
Value: &val,
}).
SetResult(&result).
Post("/update/")

if err != nil {
return
}
}
var result entity.Metric
_, err := c.c.R().
SetBody(&entity.Metric{
ID: "PollCount",
MType: "counter",
Delta: &pollCount,
}).
SetResult(&result).
Post("/update/")

if err != nil {
return
}
log.Printf("\nUpdated to %v\n", result)
}

func (c *httpClient) SendMetrics(metrics *metricsMap) {
pollCount := metrics.PollCount.Load()

for name, val := range metrics.Gauge {
requestURL := fmt.Sprintf("%s/update/gauge/%s/%f", c.c.BaseURL, name, val)

resp, err := c.c.R().
SetHeader("Content-Type", "application/json").
SetHeader("Content-Encoding", "gzip").
SetHeader("Accept-Encoding", "gzip").
Post(requestURL)
if err != nil {
log.Printf("client: error making http request: %s\n", err)
return
}
log.Println(string(resp.Body()))
}

requestURL := fmt.Sprintf("%s/update/counter/PollCount/%d", c.c.BaseURL, pollCount)
resp, err := c.c.R().
SetHeader("Content-Type", "application/json").
Post(requestURL)
if err != nil {
log.Printf("client: error making http request: %s\n", err)
return
}

logger.Log.Infow("METRICS SENT - : %s\nStatus: %d\n",
"ADDRES", c.c.BaseURL,
"Status", resp.StatusCode(),
)
log.Printf("client: status code: %d\n", resp.StatusCode())
log.Println(string(resp.Body()))
}
Loading

0 comments on commit cf3c375

Please sign in to comment.