func (s *stats) runtime() *pstats.RuntimeStats { return &pstats.RuntimeStats{ HeapInUse: proto.Uint64(uint64(getGaugeVal(s.registry, "runtime.MemStats.HeapInuse"))), HeapTotal: proto.Uint64(uint64(getGaugeVal(s.registry, "runtime.MemStats.TotalAlloc"))), HeapReleased: proto.Uint64(uint64(getGaugeVal(s.registry, "runtime.MemStats.HeapReleased"))), LastGCDuration: proto.Uint64(uint64(getGaugeVal(s.registry, "local.GCStats.LastGCDuration"))), NumGC: proto.Uint32(uint32(getGaugeVal(s.registry, "debug.GCStats.NumGC"))), NumGoRoutines: proto.Uint32(uint32(getGaugeVal(s.registry, "runtime.NumGoroutine"))), } }
// ToProtobuf takes a Error and returns a protobuf error func ToProtobuf(err Error) *pe.PlatformError { return &pe.PlatformError{ Type: pe.PlatformError_ErrorType(pe.PlatformError_ErrorType_value[err.Type()]).Enum(), Code: proto.String(err.Code()), Description: proto.String(err.Description()), Context: err.Context(), HttpCode: proto.Uint32(err.HttpCode()), } }
// ConfiguredHttpCaller with more explicit configuration options than simple HttpCaller func ConfiguredHttpCaller(opts Options) Caller { tp := &httpclient.Transport{ ConnectTimeout: durationOrDefault(opts.ConnectTimeout, 5*time.Second), RequestTimeout: durationOrDefault(opts.RequestTimeout, 5*time.Second), ResponseHeaderTimeout: durationOrDefault(opts.ResponseHeaderTimeout, 5*time.Second), } if opts.TlsSkipVerify { tp.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} } httpClient := &http.Client{Transport: tp} return func(req *client.Request, rsp proto.Message) errors.Error { u, err := url.Parse(opts.BaseUrl) q := u.Query() q.Set("session_id", req.SessionID()) q.Set("service", req.Service()) q.Set("endpoint", req.Endpoint()) u.Path = "/rpc" u.RawQuery = q.Encode() var httpReq *http.Request // send JSON req content-type to thin API as form-encoded data // send proto req content-type directly as bytes, with proto content type if req.ContentType() == jsonContentType { values := make(url.Values) values.Set("service", req.Service()) values.Set("endpoint", req.Endpoint()) values.Set("request", string(req.Payload())) httpReq, _ = http.NewRequest("POST", u.String(), bytes.NewReader([]byte(values.Encode()))) httpReq.Header.Set("Content-Type", formEncodedContentType) } else { httpReq, _ = http.NewRequest("POST", u.String(), bytes.NewReader(req.Payload())) httpReq.Header.Set("Content-Type", protoContentType) } log.Tracef("[Multiclient] HTTP caller - calling '%s' : content-type '%s'", u.String(), req.ContentType()) httpRsp, err := httpClient.Do(httpReq) if err != nil { log.Warnf("[Multiclient] HTTP caller error calling %s.%s via %s : %s", req.Service(), req.Endpoint(), u.String(), err) return errors.InternalServerError("multiclienthttp.postform", fmt.Sprintf("Error calling %s.%s via %s : %s", req.Service(), req.Endpoint(), u.String(), err)) } defer httpRsp.Body.Close() rspBody, err := ioutil.ReadAll(httpRsp.Body) if err != nil { return errors.BadResponse("multiclienthttp.readresponse", fmt.Sprintf("Error reading response bytes: %v", err)) } // what status code? if httpRsp.StatusCode != 200 { // deal with error e := &protoerror.PlatformError{} var err error if req.ContentType() == jsonContentType { jsonErr := &errorBody{} err = json.Unmarshal(rspBody, jsonErr) e.Code = proto.String(jsonErr.DottedCode) e.Context = jsonErr.Context e.Description = proto.String(jsonErr.Payload) e.HttpCode = proto.Uint32(uint32(httpRsp.StatusCode)) // this conversion is lossy, since the JSON response for errors, as crafted // by the "thin API", does not currently include the error type, so we have // to guess from HTTP status code, but there is no distinct code for "BAD_RESPONSE" switch httpRsp.StatusCode { case 400: e.Type = protoerror.PlatformError_BAD_REQUEST.Enum() case 403: e.Type = protoerror.PlatformError_FORBIDDEN.Enum() case 404: e.Type = protoerror.PlatformError_NOT_FOUND.Enum() case 500: e.Type = protoerror.PlatformError_INTERNAL_SERVER_ERROR.Enum() case 504: e.Type = protoerror.PlatformError_TIMEOUT.Enum() } } else { err = proto.Unmarshal(rspBody, e) } // some issue understanding error rsp if err != nil { return errors.BadResponse("multiclienthttp.unmarshalerr", fmt.Sprintf("Error unmarshaling error response '%s': %v", string(rspBody), err)) } return errors.FromProtobuf(e) } // unmarshal response if req.ContentType() == jsonContentType { err = json.Unmarshal(rspBody, rsp) } else { err = proto.Unmarshal(rspBody, rsp) } if err != nil { return errors.BadResponse("multiclienthttp.unmarshal", fmt.Sprintf("Error unmarshaling response: %v", err)) } return nil } }