visit
import "net/http"
type Service struct {
httpClient *http.Client
}
func NewService() *Service {
httpClient := &http.Client{
Timeout: 5 * time.Second, // set up your own timeout
}
return &Service{
httpClient: httpClient,
}
}
func (s *Service) CallAPI(req *http.Request) error {
res, err := s.httpClient.Do(req)
if err != nil {
...
}
...
}
import (
"log"
"io/ioutil"
"net/http"
)
type Service struct {
httpClient *http.Client
}
type CallResponse struct {
Payload string
}
func NewService() *Service {
httpClient := &http.Client{
Timeout: 5 * time.Second,
}
return &Service{
httpClient: httpClient,
}
}
func (s *Service) CallAPI(req *http.Request) (CallResponse, error) {
res, err := s.httpClient.Do(req)
if err != nil {
return CallResponse{}, fmt.Errorf("do request: %w", err)
}
content, err := ioutil.ReadAll(res.Body)
if err != nil {
return CallResponse{}, fmt.Errorf("read response body: %w", err)
}
// gracefully handle the bad responses
if res.StatusCode >= 400 && res.StatusCode < 500 {
log.Printf("external service returned bad response. Code: %s. Content: %s\n", res.StatusCode, string(content))
return CallResponse{Payload: "default"}, nil
}
...
}
import (
"go.uber.org/ratelimit"
"net/http"
)
type Service struct {
limiter ratelimit.Limiter
httpClient *http.Client
}
func NewService() *Service {
httpClient := &http.Client{
Timeout: 5 * time.Second,
}
return &Service{
httpClient: httpClient,
limiter: ratelimit.New(10), // 10 is the max RPS that external API can handle
}
}
func (s *Service) CallAPI(req *http.Request) error {
s.limiter.Take() // hangs if the max RPS is reached
res, err := s.httpClient.Do(req)
if err != nil {
...
}
...
}
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
// ExternalServiceHTTPCallHistogram observes http call duration in seconds
ExternalServiceHTTPCallHistogram = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "namespace",
Subsystem: "subsystem",
Name: "external_service_call_duration_in_seconds",
Help: "http call duration in seconds to an external service",
}, []string{"path", "method"},
)
)
type Service struct {
httpClient *http.Client
}
func NewService() *Service {
httpClient := &http.Client{
Timeout: 5 * time.Second,
}
return &Service{
httpClient: httpClient,
}
}
func (s *Service) CallAPI(req *http.Request) error {
// save the request starting time point
start := time.Now()
// do the API call
res, err := s.httpClient.Do(req)
// calculate how much time the request takes
spentSeconds := time.Since(start).Seconds()
// send the measurement to Prometheus
metric.ExternalServiceHTTPCallHistogram.WithLabelValues(req.URL.Path, req.Method).Observe(spentSeconds)
...
}