singer-io / tap-typeform

Singer.io tap for extracting TypeForm data
GNU Affero General Public License v3.0
11 stars 20 forks source link

Log requests #41

Closed luandy64 closed 3 years ago

luandy64 commented 3 years ago

Description

This PR adds context in failure scenarios for certain requests.

Manual QA Steps

I generated 3 tokens with different sets of scopes

  1. Accounts:Read
  2. Forms:Read
  3. Forms:Read and Responses:Read

I ran the tap with each token in the order described above. Note that each time the tap made it father "into" the code

The logs to prove we need more scopes on the token

Accounts:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.3381948471069336, "tags": {"job_type": "form definition t6sbkCIz", "status": "failed"}}
CRITICAL HTTP-error-code: 403, Error: User doesn't have permission to access the resource.
Traceback (most recent call last):
  File "/usr/local/share/virtualenvs/tap-typeform/bin/tap-typeform", line 33, in <module>
    sys.exit(load_entry_point('tap-typeform', 'console_scripts', 'tap-typeform')())
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/singer/utils.py", line 229, in wrapped
    return fnc(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 128, in main
    sync(atx)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 81, in sync
    streams.sync_forms(atx)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 282, in sync_forms
    sync_form_definition(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 96, in sync_form_definition
    response = get_form_definition(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 68, in get_form_definition
    return atx.client.get_form_definition(form_id)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 131, in get_form_definition
    return self.request('get', url, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 99, in request
    raise_for_error(response)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 170, in raise_for_error
    raise exc(formatted_message, response) from None
tap_typeform.http.TypeformForbiddenError: HTTP-error-code: 403, Error: User doesn't have permission to access the resource.

Forms:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.32311463356018066, "tags": {"job_type": "form definition t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 2, "tags": {"endpoint": "questions"}}
INFO All landings query
CRITICAL HTTP-error-code: 403, Error: User doesn't have permission to access the resource.
Traceback (most recent call last):
  File "/usr/local/share/virtualenvs/tap-typeform/bin/tap-typeform", line 33, in <module>
    sys.exit(load_entry_point('tap-typeform', 'console_scripts', 'tap-typeform')())
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/singer/utils.py", line 229, in wrapped
    return fnc(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 128, in main
    sync(atx)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 81, in sync
    streams.sync_forms(atx)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 285, in sync_forms
    sync_landings(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 244, in sync_landings
    response = get_landings(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 87, in get_landings
    return atx.client.get_form_responses(form_id)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 136, in get_form_responses
    return self.request('get', url, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 99, in request
    raise_for_error(response)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 170, in raise_for_error
    raise exc(formatted_message, response) from None
tap_typeform.http.TypeformForbiddenError: HTTP-error-code: 403, Error: User doesn't have permission to access the resource.

Forms:Read and Responses:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.2069098949432373, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.20743322372436523, "tags": {"job_type": "form definition t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 2, "tags": {"endpoint": "questions"}}
INFO All landings query
INFO raw data items= 0
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.0352473258972168, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz/responses", "status": "succeeded"}}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 0, "tags": {"endpoint": "landings"}}
INFO Forms query - form: t6sbkCIz start_date: 2021-05-10 00:00 end_date: 2021-05-11 00:00
INFO raw data items= 0
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.030831575393676758, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz/responses", "status": "succeeded"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.031381845474243164, "tags": {"job_type": "form t6sbkCIz", "status": "succeeded"}}

The new and improved logs

Accounts:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 1.006927490234375, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz", "status": "failed"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 1.0073966979980469, "tags": {"job_type": "form definition t6sbkCIz", "status": "failed"}}
CRITICAL Maybe add the Forms:Read scope to your token
Traceback (most recent call last):
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 134, in get_form_definition
    return self.request('get', url, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 99, in request
    raise_for_error(response)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 179, in raise_for_error
    raise exc(formatted_message, response) from None
tap_typeform.http.TypeformForbiddenError: HTTP-error-code: 403, Error: User doesn't have permission to access the resource.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/share/virtualenvs/tap-typeform/bin/tap-typeform", line 33, in <module>
    sys.exit(load_entry_point('tap-typeform', 'console_scripts', 'tap-typeform')())
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/singer/utils.py", line 229, in wrapped
    return fnc(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 128, in main
    sync(atx)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 81, in sync
    streams.sync_forms(atx)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 282, in sync_forms
    sync_form_definition(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 96, in sync_form_definition
    response = get_form_definition(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 68, in get_form_definition
    return atx.client.get_form_definition(form_id)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 136, in get_form_definition
    raise RuntimeError("Maybe add the Forms:Read scope to your token") from err
RuntimeError: Maybe add the Forms:Read scope to your token     

Forms:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.1775655746459961, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.17805051803588867, "tags": {"job_type": "form definition t6sbkCIz", "status": "succeeded"}}
{"type": "RECORD", "stream": "questions", "record": {"form_id": "t6sbkCIz", "question_id": "e4hDM6IBIpyw"}, "time_extracted": "2021-07-27T03:32:02.618334Z"}
{"type": "RECORD", "stream": "questions", "record": {"form_id": "t6sbkCIz", "question_id": "IIYseA58pKxJ"}, "time_extracted": "2021-07-27T03:32:02.618334Z"}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 2, "tags": {"endpoint": "questions"}}
INFO All landings query
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.01852250099182129, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz/responses", "status": "failed"}}
CRITICAL Maybe add the Responses:Read scope to your token
Traceback (most recent call last):
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 143, in get_form_responses
    return self.request('get', url, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 99, in request
    raise_for_error(response)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 179, in raise_for_error
    raise exc(formatted_message, response) from None
tap_typeform.http.TypeformForbiddenError: HTTP-error-code: 403, Error: User doesn't have permission to access the resource.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/share/virtualenvs/tap-typeform/bin/tap-typeform", line 33, in <module>
    sys.exit(load_entry_point('tap-typeform', 'console_scripts', 'tap-typeform')())
  File "/usr/local/share/virtualenvs/tap-typeform/lib/python3.8/site-packages/singer/utils.py", line 229, in wrapped
    return fnc(*args, **kwargs)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 128, in main
    sync(atx)
  File "/opt/code/tap-typeform/tap_typeform/__init__.py", line 81, in sync
    streams.sync_forms(atx)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 285, in sync_forms
    sync_landings(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 244, in sync_landings
    response = get_landings(atx, form_id)
  File "/opt/code/tap-typeform/tap_typeform/streams.py", line 87, in get_landings
    return atx.client.get_form_responses(form_id)
  File "/opt/code/tap-typeform/tap_typeform/http.py", line 145, in get_form_responses
    raise RuntimeError("Maybe add the Responses:Read scope to your token") from err
RuntimeError: Maybe add the Responses:Read scope to your token     

Forms:Read and Responses:Read

INFO form: t6sbkCIz
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.3422980308532715, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.34274935722351074, "tags": {"job_type": "form definition t6sbkCIz", "status": "succeeded"}}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 2, "tags": {"endpoint": "questions"}}
INFO All landings query
INFO raw data items= 0
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.034545183181762695, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz/responses", "status": "succeeded"}}
INFO METRIC: {"type": "counter", "metric": "record_count", "value": 0, "tags": {"endpoint": "landings"}}
INFO Forms query - form: t6sbkCIz start_date: 2021-05-10 00:00 end_date: 2021-05-11 00:00
INFO raw data items= 0
INFO METRIC: {"type": "timer", "metric": "http_request_duration", "value": 0.03435397148132324, "tags": {"endpoint": "https://api.typeform.com/forms/t6sbkCIz/responses", "status": "succeeded"}}
INFO METRIC: {"type": "timer", "metric": "job_duration", "value": 0.034932851791381836, "tags": {"job_type": "form t6sbkCIz", "status": "succeeded"}}

Risks

It appeared that the release of v1.3.0 affected the scopes on the tokens somehow. Because tap runs that would previously succeed on v1.2.0 failed on v1.3.0 and v1.3.2.

Since things are broken, this PR should be very low risk because it only helps people help themselves

Rollback Steps

Revert the commit and bump the version

luandy64 commented 3 years ago

Closing this in favor of #42