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

feat: Record by default #176

Merged
merged 5 commits into from
Oct 12, 2022
Merged

feat: Record by default #176

merged 5 commits into from
Oct 12, 2022

Conversation

symwell
Copy link
Contributor

@symwell symwell commented Oct 4, 2022

Record appmaps by default.

Fixes #166

@symwell symwell force-pushed the sw/feat/record_by_default branch 25 times, most recently from fdaa71c to 7cfc095 Compare October 6, 2022 18:43
@symwell symwell force-pushed the sw/feat/record_by_default branch 2 times, most recently from c94d583 to 3168889 Compare October 7, 2022 13:48
@symwell symwell marked this pull request as ready for review October 7, 2022 13:57
@apotterri apotterri self-requested a review October 7, 2022 14:23
@symwell symwell force-pushed the sw/feat/record_by_default branch 4 times, most recently from 99b2d6c to f5f7b30 Compare October 7, 2022 17:42
Copy link
Collaborator

@apotterri apotterri left a comment

Choose a reason for hiding this comment

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

As I mentioned in one of my comments, please use one or more fixup commits when you make changes after a review. It'll make it much easier see the new code.

appmap/_implementation/detect_enabled.py Outdated Show resolved Hide resolved

@classmethod
def is_appmap_repo(cls):
return os.path.exists("appmap/_implementation/event.py") and os.path.exists(
Copy link
Collaborator

Choose a reason for hiding this comment

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

As I said in Slack, I think this would be better managed with an environment variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As a developer I would prefer to not have to define an environment variable, to not have to document a variable, to not have to read documentation to find if a variable should be defined, and to not have to think if I should comment-out any environment variable already defined depending on whether I'm developing for appmap-python or using it. I would prefer this decision to be derived automatically.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I still don't love this solution. But, if we have to go this way, let's at least test for a file that's less likely to move around if we refactor, e.g. appmap/__init__.py, or appmap/_implementation/__init__.py.

appmap/_implementation/detect_enabled.py Show resolved Hide resolved
appmap/test/test_detect_enabled.py Outdated Show resolved Hide resolved
@classmethod
def initialize(cls):
cls._instance = None
# because apparently __new__ and __init__ don't get called
Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, because you're not actually asking to create an instance, i.e. you don't say DetectEnabled() anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I try, whether I say DetectEnabled() or not, self._detected_for_method = {} from __init__ doesn't get set.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks to me like it gets set. Maybe I don't understand what you mean?

diff --git a/appmap/_implementation/detect_enabled.py b/appmap/_implementation/detect_enabled.py
index 6d03c7b..aeea80c 100644
--- a/appmap/_implementation/detect_enabled.py
+++ b/appmap/_implementation/detect_enabled.py
@@ -38,11 +38,12 @@ class DetectEnabled:
     def initialize(cls):
         cls._instance = None
         # because apparently __new__ and __init__ don't get called
-        cls._detected_for_method = {}
+        # cls._detected_for_method = {}

     @classmethod
     def clear_cache(cls):
-        cls._detected_for_method = {}
+        # cls._detected_for_method = {}
+        pass

     @classmethod
     def is_appmap_repo(cls):
sw/feat/record_by_default *$
ajp@Alans-MacBook-Pro appmap-python-2 % python
Python 3.10.7 (main, Sep 15 2022, 04:53:36) [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from appmap._implementation.detect_enabled import DetectEnabled
>>> de = DetectEnabled()
>>> print(de._detected_for_method)
{}
>>>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I apply the first diff -- if I comment out cls._detected_for_method = {} in initialize -- the Flask testcases don't pass

poetry run pytest appmap/test/test_flask.py

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, ok, but that's not (necessarily) the same thing as "init doesn't set a property of self", which is what it sounds like you meant.

appmap/_implementation/detect_enabled.py Outdated Show resolved Hide resolved
appmap/django.py Outdated Show resolved Hide resolved
appmap/test/test_detect_enabled.py Show resolved Hide resolved
Copy link
Collaborator

@apotterri apotterri left a comment

Choose a reason for hiding this comment

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

Somehow, GitHub decided that some of my comments should be one-offs, and others should be part of a review. So, I'm just submitting this as "general feedback"....


@classmethod
def is_appmap_repo(cls):
return os.path.exists("appmap/_implementation/event.py") and os.path.exists(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I still don't love this solution. But, if we have to go this way, let's at least test for a file that's less likely to move around if we refactor, e.g. appmap/__init__.py, or appmap/_implementation/__init__.py.

@classmethod
def initialize(cls):
cls._instance = None
# because apparently __new__ and __init__ don't get called
Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, ok, but that's not (necessarily) the same thing as "init doesn't set a property of self", which is what it sounds like you meant.

@apotterri apotterri force-pushed the sw/feat/record_by_default branch 2 times, most recently from 8d9993d to 4dd10e1 Compare October 11, 2022 09:20
@symwell symwell force-pushed the sw/feat/record_by_default branch 2 times, most recently from 838d741 to b53cc51 Compare October 11, 2022 18:58
@symwell
Copy link
Contributor Author

symwell commented Oct 11, 2022

This is ready to review. The build passes now.

Had to change a lot of testcases after the recent rebase.

Copy link
Collaborator

@apotterri apotterri left a comment

Choose a reason for hiding this comment

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

One more issue to resolve, then this should be ready for a final rebase.

self.app = app
if app is not None:
self.init_app(app)

def init_app(self, app):
if not Env.current.enabled:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Removing all these checks means that even if recording is disabled (e.g. with APPMAP=false), the remote-recording routes will still be added to the app, right? Is there some reason that's necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's right, the remote-recording routes will still be added.

Without removing this check some testcase wasn't working. I think it was test_starts_disabled

I wish my commit history wasn't squashed into a single commit so that I could find through the commit comments which testcase this was.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Making this change required adding an extra check in record_get, which is the corresponding check of if not Env.current.enabled.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we want the routes added if recording is disabled. To fix test_starts_disabled, couldn't you instead make sure that remote recording is enabled (e.g. with APPMAP=true?

Copy link
Contributor Author

@symwell symwell Oct 11, 2022

Choose a reason for hiding this comment

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

This was before the rebase of the events pr, so let me try to put it back and see what I get.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was failing two other testcases, not the one I said:

FAILED appmap/test/test_flask.py::TestRecordRequestsFlask::test_record_request_appmap_not_enabled_requests_enabled_and_remote - AssertionError
FAILED appmap/test/test_flask.py::TestRecordRequestsFlask::test_record_request_appmap_not_enabled_requests_enabled_no_remote - KeyError: 'appmap-file-name'

Also, it was failing this testcases only for Flask. Apparently there was no such check for the routes for Django.

I think it's because I was trying to test the case of APPMAP=false (appmap not enabled) but then enabling remote recording through the testcase issuing a POST.

My understanding is that remote recording and APPMAP=true are separate features. Is this true, or is remote recording possible only if APPMAP=true?

Copy link
Collaborator

@apotterri apotterri Oct 11, 2022

Choose a reason for hiding this comment

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

Is this true, or is remote recording possible only if APPMAP=true?

Remote recording is only possible if APPMAP=true.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Apparently there was no such check for the routes for Django.

This seems like a bug.

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 think something's wrong. In test_can_record I'm seeing remote requests enabled with a POST but then by the time the DELETE is issued to disable them recording is already off. As if some .stop_recording() call disabled recording.

@apotterri
Copy link
Collaborator

I wish my commit history wasn't squashed into a single commit so that I could find through the commit comments which testcase this was.

That seems reasonable. It's basically the workflow described here: https://git-scm.com/docs/git-rebase#_interactive_mode, amended for GitHub PRs:

  1. have a wonderful idea

  2. hack on the code

  3. prepare a series for submission, request a review

    a. apply fixup! commits to address review comments

    b. re-request review

    c. repeat a and b as necessary

  4. final history cleanup, squashing original commits into one or two final, orthogonal commits

My experience has been that step 4 can be somewhat challenging, if steps 1-3 have touched many files. Sometimes you can avoid this by making the initial task smaller, but not always.

@symwell symwell merged commit 717d39a into master Oct 12, 2022
@symwell symwell deleted the sw/feat/record_by_default branch October 12, 2022 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

get python agent to record by default
2 participants