aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
2.96k stars 556 forks source link

@aws-sdk/client-marketplace-metering index.js Error message: Error reporting usage: TypeError: _.getTime is not a function #6151

Closed nyamurray closed 1 week ago

nyamurray commented 1 month ago

Checkboxes for prior research

Describe the bug

@aws-sdk/client-marketplace-metering/dist-cjs/index.js line 838 produces an error message: Error reporting usage: TypeError: _.getTime is not a function. The API reference indicates a UTC timestamp. This is producing the same error for a UTC timestamp in seconds, as for UTC timestamp in ISO-8601 format. The API reference indicates that this is the format required. Other usage fields did not produce an error.

SDK version number

@aws-sdk/client-marketplace-metering latest AWS Lambda version

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

Lambda nodejs 18x

Reproduction Steps

async function reportUsage(productCode, usageRecords) {
    const params = {
        ProductCode: productCode,
        UsageRecords: usageRecords
    };

   console.log(JSON.stringify(params)); 
// {"ProductCode":"xxxxxxxxxxxxxxxxxxxxxx","UsageRecords":[{"CustomerIdentifier":"xxxxxxxxxxx","Dimension":"API Gateway","Timestamp":1717122081,"Quantity":0},{"CustomerIdentifier":"xxxxxxxxxxx","Dimension":"API Gateway","Timestamp":1717122081,"Quantity":0}]}

    const command = new BatchMeterUsageCommand(params);

    try {
        const response = await meteringMarketplaceClient.send(command);
        console.log("Usage reported successfully:", response);
    } catch (error) {
        console.error("Error reporting usage:", error);
    }
}

Observed Behavior

ERROR Error reporting usage: TypeError: _.getTime is not a function at Timestamp (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:838:36) at applyInstruction (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1088:27) at take (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1056:5) at se_UsageRecord (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:834:40) at /var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:844:12 at Array.map () at se_UsageRecordList (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:843:41) at UsageRecords (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:820:26) at applyInstruction (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1088:27) at take (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1056:5)

Expected Behavior

The UsageRecordResult Status indicates the status of an individual UsageRecord processed by BatchMeterUsage. e.g. Success and an echo of the UsageRecord

Possible Solution

javascript sdk v3 returning inconsistent results for .getTime() function. Possibly the getTime() function is doing a comparison and perhaps converting the numeric value of the UTC date into a javscript date before comparison may be a possible solution. It is possible that the .getTime() function may require attention.

Additional Information/Context

I believe there are other implementations of jdk v3 return an error of .getTime() is not a function, though I do not have an example, anecdotal evidence only.

RanVaknin commented 3 weeks ago

Hi @nyamurray ,

There might be a problem with how the marketplace service team documented the Timestamp field.

From the docs:

Timestamp

Timestamp, in UTC, for which the usage is being reported.

Your application can meter usage for up to one hour in the past. Make sure the timestamp value is not before the start of the software usage.

Type: Timestamp

Required: Yes

However the actual API model that the Marketplace service team defines, uses Smithy's Timestmap type which mentiones RFC 3339 which is a more restrictive format of iso8601.

Can you try this:

{
  "ProductCode": "xxxxxxxxxxxxxxxxxxxxxx",
  "UsageRecords": [
    {
      "CustomerIdentifier": "xxxxxxxxxxx",
      "Dimension": "API Gateway",
-      "Timestamp": 1717122081,
+      "Timestamp": "2024-05-31T02:21:21+00:00",
      "Quantity": 0
    },
    {
      "CustomerIdentifier": "xxxxxxxxxxx",
      "Dimension": "API Gateway",
-      "Timestamp": 1717122081,
+      "Timestamp": "2024-05-31T02:21:21+00:00",
      "Quantity": 0
    }
  ]
}

Let me know if this helps.

Thanks, Ran~

charlydi commented 3 weeks ago

I got the same error but from client-quicksight module, details can be found here: #6176

nyamurray commented 3 weeks ago

Thanks for your input @RanVaknin - and yours @charlydi Ran I tried the following code with RFC 3339 a more restrictive format of iso8601:

function getCurrentRFC3339Timestamp() { const now = new Date(); const isoString = now.toISOString(); const dateTime = isoString.split('.')[0]; // Remove milliseconds const offset = now.getTimezoneOffset(); const absOffset = Math.abs(offset); const hours = String(Math.floor(absOffset / 60)).padStart(2, '0'); const minutes = String(absOffset % 60).padStart(2, '0'); const sign = offset > 0 ? '-' : '+';

return `${dateTime}${sign}${hours}:${minutes}`;

}

console.log(getCurrentRFC3339Timestamp());

So now completely aligned with both ISO8601 and RFC3339 as per Smithy's Timestmap https://smithy.io/2.0/spec/simple-types.html#timestamp

So "Timestamp":"2024-06-07T00:31:08+00:00" produces the same:- Error reporting usage: TypeError: _.getTime is not a function at Timestamp (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:838:36)

As I understand it the client-marketplace-metering client would be doing a time comparison to ensure that the metering only picks up on the past hour in my case. I get the feeling that it is the time comparison that is producing the error. Dates can be tricky in javascript. I have seen the .getTime() error from a data comparison in a different context. Since we are talking UTC, I cannot think what else could be producing a discrepancy.

best

Nya

nyamurray commented 3 weeks ago

PS: Here is the full message. Sadly I do not have time to investigate the depths of the Smithy error trail at the moment, it is quicker to rewrite in Python. If that still produces a timestamp error, I'll know there is something wrong with my AWS Account's parameters in the AWS Marketplace world view.

ERROR Error reporting usage: TypeError: _.getTime is not a function at Timestamp (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:838:36) at applyInstruction (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1088:27) at take (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1056:5) at se_UsageRecord (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:834:40) at /var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:844:12 at Array.map () at se_UsageRecordList (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:843:41) at UsageRecords (/var/runtime/node_modules/@aws-sdk/client-marketplace-metering/dist-cjs/index.js:820:26) at applyInstruction (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1088:27) at take (/var/runtime/node_modules/@aws-sdk/node_modules/@smithy/smithy-client/dist-cjs/index.js:1056:5)

nyamurray commented 3 weeks ago

I might add I had no problem with the same account, product customers etc with a nodejs14x implementation.

However I inadvertently overwrote this code in error, so I no longer have the original that worked, however from memory I was using a plain old timestamp in either seconds or milliseconds. And because it is just about the only code I run in US-East-1, and did not notice for six months that I'd overwritten the function, I no longer have a backup.

To my mind, this points to the difference being JDK v3 in Nodejs 18x deployed from an AWS Lambda service. I'll let you know if I get time to investigate the Smithy deployment of .getTime()

RanVaknin commented 1 week ago

Hi @nyamurray,

I ran that code with an epoch timestamp on a Node 14 environment and the issue remains the same. The issue is unlikely with the Node version.

Providing the timestamp as a Javascript Date object worked for me:

const testUsageRecords = [
  { CustomerIdentifier: "cust123", Dimension: "API Gateway", Timestamp: new Date("2024-06-17T00:00:00Z"), Quantity: 1 },
  { CustomerIdentifier: "cust124", Dimension: "API Gateway", Timestamp: new Date("2024-06-17T00:05:00Z"), Quantity: 2 }
];

Let me know if it solves your issue.

Thanks, Ran~

nyamurray commented 1 week ago

Thanks Ran.

I tried a number of ISO 8601 date formats. I finally tried that format again, and suddenly it was working. Don't know why. Nodejs 14x was pre modular, and there was a lot of non backward compatibility issues with jdk v3, which is why I suspected the jdk v3 codebase. Perhaps someone fixed the getTime() issue. I have not tried it again with the other ISO 8601 date formats, which is all that is in the documentation, just glad it works with one format. As I already tried that format and it failed, I think somebody must have taken a look at the codebase. best Nya