From f2d4922a3ba6b1e8b13abe934d948482a0df9c30 Mon Sep 17 00:00:00 2001 From: ahz-r3v <2521920975@qq.com> Date: Sun, 4 May 2025 02:07:35 +0800 Subject: [PATCH 1/2] Fix(#636): resolve panic and add POST handler for aws client. --- pkg/driver/clients/aws_client.go | 55 +++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/pkg/driver/clients/aws_client.go b/pkg/driver/clients/aws_client.go index d347a1d25..110f0846b 100644 --- a/pkg/driver/clients/aws_client.go +++ b/pkg/driver/clients/aws_client.go @@ -8,6 +8,10 @@ import ( mc "github.com/vhive-serverless/loader/pkg/metric" "io" "sync" + "net/http" + "crypto/tls" + "bytes" + "time" ) type awsLambdaInvoker struct { @@ -24,7 +28,9 @@ func (i *awsLambdaInvoker) Invoke(function *common.Function, runtimeSpec *common log.Tracef("(Invoke)\t %s: %d[ms], %d[MiB]", function.Name, runtimeSpec.Runtime, runtimeSpec.Memory) dataString := fmt.Sprintf(`{"RuntimeInMilliSec": %d, "MemoryInMebiBytes": %d}`, runtimeSpec.Runtime, runtimeSpec.Memory) - success, executionRecordBase, res := httpInvocation(dataString, function, i.announceDoneExe, false) + + success, executionRecordBase, res := awsHttpInvocation(dataString, function, i.announceDoneExe, false) + defer res.Body.Close() executionRecordBase.RequestedDuration = uint32(runtimeSpec.Runtime * 1e3) record := &mc.ExecutionRecord{ExecutionRecordBase: *executionRecordBase} @@ -56,3 +62,50 @@ func (i *awsLambdaInvoker) Invoke(function *common.Function, runtimeSpec *common return true, record } + +func awsHttpInvocation(dataString string, function *common.Function, AnnounceDoneExe *sync.WaitGroup, tlsSkipVerify bool) (bool, *mc.ExecutionRecordBase, *http.Response) { + record := &mc.ExecutionRecordBase{} + start := time.Now() + record.StartTime = start.UnixMicro() + record.Instance = function.Name + requestURL := function.Endpoint + + if tlsSkipVerify { + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + } + + var bodyReader io.Reader + if dataString != "" { + bodyReader = bytes.NewBuffer([]byte(dataString)) + } else { + bodyReader = http.NoBody + } + + req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader) + if err != nil { + log.Warnf("http request creation failed for function %s - %s", function.Name, err) + record.ResponseTime = time.Since(start).Microseconds() + record.ConnectionTimeout = true + return false, record, nil + } + req.Header.Set("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Debugf("http request for function %s failed - %s", function.Name, err) + record.ResponseTime = time.Since(start).Microseconds() + record.ConnectionTimeout = true + return false, record, resp + } + // defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + log.Debugf("http request for function %s failed - error code: %s", function.Name, resp.Status) + record.ResponseTime = time.Since(start).Microseconds() + record.ConnectionTimeout = true + return false, record, resp + } + + return true, record, resp +} + From f29b6675dcbb0f3cd0fc24a30731fc3819f2d3d7 Mon Sep 17 00:00:00 2001 From: ahz-r3v <2521920975@qq.com> Date: Sun, 8 Jun 2025 00:15:21 +0800 Subject: [PATCH 2/2] bug fix: misses the measurements of response time in case of success --- pkg/driver/clients/aws_client.go | 38 +++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/pkg/driver/clients/aws_client.go b/pkg/driver/clients/aws_client.go index 110f0846b..dc998a2fd 100644 --- a/pkg/driver/clients/aws_client.go +++ b/pkg/driver/clients/aws_client.go @@ -12,6 +12,7 @@ import ( "crypto/tls" "bytes" "time" + "encoding/base64" ) type awsLambdaInvoker struct { @@ -97,7 +98,7 @@ func awsHttpInvocation(dataString string, function *common.Function, AnnounceDon record.ConnectionTimeout = true return false, record, resp } - // defer resp.Body.Close() + defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { log.Debugf("http request for function %s failed - error code: %s", function.Name, resp.Status) @@ -106,6 +107,41 @@ func awsHttpInvocation(dataString string, function *common.Function, AnnounceDon return false, record, resp } +bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + log.Warnf("Failed to read output %s - %v", function.Name, err) + + record.ResponseTime = time.Since(start).Microseconds() + record.FunctionTimeout = true + + return false, record, resp + } + + rawJson, err := base64.StdEncoding.DecodeString(string(bodyBytes)) + if err != nil { + log.Warnf("Failed to decode base64 output %s - %v", function.Name, err) + + record.ResponseTime = time.Since(start).Microseconds() + record.FunctionTimeout = true + + return false, record, resp + } + + var deserializedResponse FunctionResponse + err = json.Unmarshal(rawJson, &deserializedResponse) + if err != nil { + log.Warnf("Failed to deserialize response %s - %v", function.Name, err) + + record.ResponseTime = time.Since(start).Microseconds() + record.FunctionTimeout = true + + return false, record, resp + } + + record.Instance = deserializedResponse.Function + record.ResponseTime = time.Since(start).Microseconds() + record.ActualDuration = uint32(deserializedResponse.ExecutionTime) + return true, record, resp }