Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(logger): logger throws TypeError when log item has BigInt value #1201

Conversation

shdq
Copy link
Contributor

@shdq shdq commented Dec 28, 2022

Description of your changes

The replacer function used for JSON.stringify converts BigInt values to strings.

Added tests and removed external dependency for removeEmptyKeys() function.

How to verify this change

Related issues, RFCs

Issue number: #1117

PR status

Is this ready for review?: YES
Is it a breaking change?: NO

Checklist

  • My changes meet the tenets criteria
  • I have performed a self-review of my own code
  • I have commented my code where necessary, particularly in areas that should be flagged with a TODO, or hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have made corresponding changes to the examples
  • My changes generate no new warnings
  • The code coverage hasn't decreased
  • I have added tests that prove my change is effective and works
  • New and existing unit tests pass locally and in Github Actions
  • Any dependent changes have been merged and published
  • The PR title follows the conventional commit semantics

Breaking change checklist

  • I have documented the migration process
  • I have added, implemented necessary warnings (if it can live side by side)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@pull-request-size pull-request-size bot added the size/L PRs between 100-499 LOC label Dec 28, 2022
Comment on lines 32 to 41
public removeEmptyKeys(attributes: LogAttributes): LogAttributes {
return pickBy(attributes, (value) => value !== undefined && value !== '' && value !== null);
const newAttributes: LogAttributes = {};
for (const key in attributes) {
if (attributes[key] !== undefined && attributes[key] !== '' && attributes[key] !== null) {
newAttributes[key] = attributes[key];
}
}

return newAttributes;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firstly, I wrote a declarative one-liner:

public removeEmptyKeys(attributes: LogAttributes): LogAttributes {
    return Object.fromEntries(Object.entries(attributes).filter(([, value]) => value !== undefined && value !== '' && value !== null));
}

But for the sake of readability, I stick to the verbose version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if nested objects could be in the logItem, but it wasn't and isn't supported by this function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give an example of what do you mean by nested objects?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger.info("my message", { value: 42, nested: { value: "nested value", emptyValue: '', undefinedValue: undefined, nullValue: null } });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to support nested objects though.

Here's an example of logs emitted by Logger v1.5.0 (latest):
Screenshot 2022-12-28 at 14 40 48

from this code:

import { Logger, injectLambdaContext } from "@aws-lambda-powertools/logger";
import middy from "@middy/core";

const logger = new Logger({});

export const handler = middy(async () => {
  logger.info("my message", {
    value: 42,
    nested: {
      value: "nested value",
      emptyValue: "",
      undefinedValue: undefined,
      nullValue: null,
    },
  });
}).use(injectLambdaContext(logger, { logEvent: true }));

this was the event payload passed:

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "nested": {
      "some": "key",
      "other": 1
  }
}

We need to support nested objects both for the logEvent functionality (also present in the unit tests) and arbitrary objects

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh after re-reading I realize I might have misunderstood your comment.

Were you referring to supporting the removal of undefined, null, etc. from nested objects?

yes, it's just go through the first level

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, apologies for the misunderstanding!

I think that at the moment we should strive for maintaining the same exact functionality level as the current version without breaking changes. Which based on the test I did above, seems to at least remove undefined values.

Then later on, if there's demand we can explore extending the behavior to empty strings and/or null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined values are filtered somewhere else 🙃

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great then!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I definitely support/agree with the choice of using a more verbose version for the sake of readability.

@dreamorosi dreamorosi self-requested a review December 28, 2022 13:14
@github-actions github-actions bot added the bug Something isn't working label Dec 28, 2022
@dreamorosi dreamorosi linked an issue Dec 28, 2022 that may be closed by this pull request
@dreamorosi
Copy link
Contributor

I see that there's no package-lock.json in the file diff, if you have done it differently, could you please remove the dependency by running npm remove lodash.pickby -w packages/logger?

This should make the necessary updates to the lock file as well as removing it from the package.json of the package. Note that in order to successfully be able to run the command you might have to temporarily revert the change to package.json, otherwise npm will think the two files are out of sync.

Could you please also remove @types/lodash.pickby from devDependencies in the same package while at it?

@dreamorosi
Copy link
Contributor

Also, I see that the branch you're working on is behind main.

Normally this would be fine, but in this case I would strongly advise to rebase/bring it in line with main.

The reason why I say this is that as part of the migration to Node 18 we have updated all the dependencies and added the runtime to the unit & integration tests. For the integration tests to pass we need the CDK version that is currently present on main but not in your branch, which causes the integration tests to fail.

* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#exceptions
* @private
*/
private getReplacer(): (key: string, value: LogAttributes | Error | bigint) => void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new name, thanks for making the change

@dreamorosi
Copy link
Contributor

Thank you for syncing the branch & updating the dependencies & lock file.

I can confirm that the integration tests are passing: https://github.com/awslabs/aws-lambda-powertools-typescript/actions/runs/3794471678

@dreamorosi dreamorosi self-requested a review December 28, 2022 14:18
Copy link
Contributor

@dreamorosi dreamorosi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @shdq for picking this up and for the quick PR.

I appreciate the choices made throughout.

Comment on lines 32 to 41
public removeEmptyKeys(attributes: LogAttributes): LogAttributes {
return pickBy(attributes, (value) => value !== undefined && value !== '' && value !== null);
const newAttributes: LogAttributes = {};
for (const key in attributes) {
if (attributes[key] !== undefined && attributes[key] !== '' && attributes[key] !== null) {
newAttributes[key] = attributes[key];
}
}

return newAttributes;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I definitely support/agree with the choice of using a more verbose version for the sake of readability.

@shdq
Copy link
Contributor Author

shdq commented Dec 28, 2022

Thanks a lot @shdq for picking this up and for the quick PR.

I appreciate the choices made throughout.

I'm happy to help! Thanks for the fast feedback loop @dreamorosi!

@github-actions
Copy link
Contributor

📊 Package size report   0.2%↑

File Before After
aws-lambda-powertools-logger-1.5.0.tgz 24.9 kB 0.6%↑25.0 kB
logger-bundle.zip 25.4 kB 0.4%↑25.5 kB
Total (Includes all files) 152.8 kB 0.2%↑153.0 kB
Tarball size 151.8 kB 0.1%↑152.0 kB
Unchanged files
File Size
aws-lambda-powertools-commons-1.5.0.tgz 10.2 kB
aws-lambda-powertools-metrics-1.5.0.tgz 17.9 kB
aws-lambda-powertools-tracer-1.5.0.tgz 22.4 kB
commons-bundle.zip 10.8 kB
metrics-bundle.zip 18.4 kB
tracer-bundle.zip 22.9 kB

🤖 This report was automatically generated by pkg-size-action
(options hash: c101f9ed32c1999be6905b281c82051e)

@dreamorosi dreamorosi merged commit a09e4df into aws-powertools:main Dec 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working size/L PRs between 100-499 LOC
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: logging fails if input contains bigint values
2 participants