-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
🎉 New Source: Sentry #6975
🎉 New Source: Sentry #6975
Conversation
@koji-m I will take a look at it tomorrow. |
"organization": config["organization"], | ||
"project": config["project"], | ||
} | ||
return [Events(**stream_args), Issues(**stream_args)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProjectDetail is not added here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added ProjectDetail
and Projects
.
project_detail_stream = ProjectDetail( | ||
authenticator=TokenAuthenticator(token=config["auth_token"]), | ||
hostname=config.get("hostname", self.DEFAULT_HOST), | ||
organization=config["organization"], | ||
project=config["project"], | ||
) | ||
next(project_detail_stream.read_records(sync_mode=SyncMode.full_refresh)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any simple way to test if the token is valid ? Which is more generic ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I added Projects
stream for endpoint /api/0/projects/ and changed to use Projects
stream to test if the token is valid.
if "next" in response.links and "results" in response.links["next"] and "cursor" in response.links["next"]: | ||
if response.links["next"]["results"] == "true": | ||
return {"cursor": response.links["next"]["cursor"]} | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use try catch here and comment here on what can go wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed to handle errors with try-catch, and also added comment.
|
||
|
||
class Events(SentryStream): | ||
primary_key = "id" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can keep this for SentryStream
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved primary_key
variable to SentryStream
class.
Also can you run |
"required": [ | ||
"avatar", | ||
"dateCreated", | ||
"id", | ||
"isEarlyAdopter", | ||
"name", | ||
"require2FA", | ||
"slug", | ||
"status" | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove these required keys
"required": [ | ||
"authors", | ||
"commitCount", | ||
"data", | ||
"dateCreated", | ||
"dateReleased", | ||
"deployCount", | ||
"firstEvent", | ||
"lastCommit", | ||
"lastDeploy", | ||
"lastEvent", | ||
"newGroups", | ||
"owner", | ||
"projects", | ||
"ref", | ||
"shortVersion", | ||
"url", | ||
"version" | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove these required keys
"required": [ | ||
"allowedDomains", | ||
"avatar", | ||
"color", | ||
"dataScrubber", | ||
"dataScrubberDefaults", | ||
"dateCreated", | ||
"defaultEnvironment", | ||
"digestsMaxDelay", | ||
"digestsMinDelay", | ||
"features", | ||
"firstEvent", | ||
"hasAccess", | ||
"id", | ||
"isBookmarked", | ||
"isInternal", | ||
"isMember", | ||
"isPublic", | ||
"latestRelease", | ||
"name", | ||
"options", | ||
"organization", | ||
"platform", | ||
"platforms", | ||
"processingIssues", | ||
"relayPiiConfig", | ||
"resolveAge", | ||
"safeFields", | ||
"scrapeJavaScript", | ||
"scrubIPAddresses", | ||
"securityToken", | ||
"securityTokenHeader", | ||
"sensitiveFields", | ||
"slug", | ||
"status", | ||
"storeCrashReports", | ||
"subjectPrefix", | ||
"subjectTemplate", | ||
"team", | ||
"teams", | ||
"verifySSL" | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove these required keys. Same across the schemas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed required-key fields from all of the schemas.
|
||
# Source | ||
class SourceSentry(AbstractSource): | ||
DEFAULT_HOST = "sentry.io" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed here since we have already used default in the config? can't we directly get this from config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to set default value in code. I've fixed.
except KeyError: | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any change with this we enter a loop because is not possible to update the cursor? If it's expected to always have the values raise an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't update the cursor parameter in the request_params
method, so I fixed it to do so.
And as it's expected to always have the results
and cursor
values in link header, I fixed to raise error if there is no values for that.
class Events(SentryStream): | ||
def __init__(self, organization: str, project: str, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add docs to each endpoint, see example:
airbyte/airbyte-integrations/connectors/source-cart/source_cart/streams.py
Lines 104 to 108 in 1fcd6c4
class CustomersCart(IncrementalCartStream): | |
""" | |
Docs: https://developers.cart.com/docs/rest-api/restapi.json/paths/~1customers/get | |
""" | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added docs to each endpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small comments, but overall great work! @harshithmullapudi execute tests and makes sure it's passing CI (format and tests)
That's how it was before Ive replaced it with those xWithHash classes to correctly log records with detailed_logger fixture. Changing it back would break
No, different order records should not fail test. We had such defect in SAT #5735 but it was fixed .
No, it should work with any items order. @koji-m you can find Dont forget to rebuild SAT image or just run SAT with command line: Could you try it out and share detailed logs with failed case? |
@avida why would this break logging records? I must be missing some understanding there (pointing me at relevant PR/code might be easiest answer 😄) |
@Phlair there is function in detailed_logger that dumps well formatted json into log:
serialized raw string would be a pain to read or parse with diff tools. Btw Ive created PR #7491 where I replaced serialize function (cause we actually dont need to serialize objects, just to compare) . Please check it out. |
@avida Thank you for your advice and how to isolate the problem. I tried to confirm difference between first and second read. But response data is so large to compare, so before that I tried small test as follow: import json
import functools
from typing import List, Mapping
@functools.total_ordering
class DictWithHash(dict):
_hash: str = None
def __hash__(self):
if not self._hash:
self._hash = hash(json.dumps({k: serialize(v) for k, v in self.items()}, sort_keys=True))
return self._hash
def __lt__(self, other):
return hash(self) < hash(other)
def __eq__(self, other):
return hash(self) == hash(other)
def serialize(value) -> str:
"""Simplify comparison of nested dicts/lists"""
if isinstance(value, Mapping):
return DictWithHash(value)
if isinstance(value, List):
return sorted([serialize(v) for v in value])
return str(value)
first = {
"organization": {
"features": [
"performance-tag-page",
"issue-percent-filters",
]
}
}
second = {
"organization": {
"features": [
"issue-percent-filters",
"performance-tag-page",
]
}
}
print(f'first {hash(serialize(first))}')
print(f'second {hash(serialize(second))}') This show different hash value as follow: first 2562171057633847383
second 4625636057198759702 I think the two values must be the same. There may be some mistakes in the content being verified, but I would be grateful if you could confirm it. |
I checked the test case, it looks good to me. |
ok, to add to everything above, the original serialize didn't have this issue and was using simple technic that most of pytest plugin use to compare, serialize and pprint will show much better diff than raw dicts. @avida added file logger that supposed to be used manually for detailed investigation, that is why objects there is not serialized. |
@koji-m is this resolved and are test cases passing in local ? |
Not yet resolved, but if #7491 is merged, I would assume the test case will pass. I'll let you know when the test is complete. |
Thank you @avida . |
Examples of issue and event are added, tested APIs for: |
OneSignal is now a duplicate source, prevents usage.
|
Sorry for the omission in the confirmation when merging master into this PR. I'll thoroughly check for conflicts. |
* add Events, Issues, ProjectDetail stream * add P/R number * add SUMMARY entry * add docs/integrations/README.md entry * add source_definitions.yaml entry * add connector JSON definition * add builds.md entry * SentryStream keeps primary_key * add Projects stream * change stream for connection checking * handling errors with try-catch in next_page_token function * remove required key field from schemas * remove DEFAULT_HOST * raise error if link header don't have mandatory field * fix unit test for streams * update cursor for pagination * add docs to each endpoint * add hostname property to invalid_config * fix schema * add hostname to sample_config
* add Events, Issues, ProjectDetail stream * add P/R number * add SUMMARY entry * add docs/integrations/README.md entry * add source_definitions.yaml entry * add connector JSON definition * add builds.md entry * SentryStream keeps primary_key * add Projects stream * change stream for connection checking * handling errors with try-catch in next_page_token function * remove required key field from schemas * remove DEFAULT_HOST * raise error if link header don't have mandatory field * fix unit test for streams * update cursor for pagination * add docs to each endpoint * add hostname property to invalid_config * fix schema * add hostname to sample_config
What
How
Added support for the following streams:
Recommended reading order
Test Runs
Integration Test
Unit Test
Pre-merge Checklist
Community member or Airbyter
airbyte_secret
./gradlew :airbyte-integrations:connectors:<name>:integrationTest
.README.md
bootstrap.md
. See description and examplesdocs/SUMMARY.md
docs/integrations/<source or destination>/<name>.md
including changelog. See changelog exampledocs/integrations/README.md
airbyte-integrations/builds.md
Airbyter
If this is a community PR, the Airbyte engineer reviewing this PR is responsible for the below items.
/test connector=connectors/<name>
command is passing./publish
command described here