diff --git a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml index 2a648c673b40f..4d913690729c2 100644 --- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml @@ -437,7 +437,7 @@ - name: Facebook Marketing sourceDefinitionId: e7778cfc-e97c-4458-9ecb-b4f2bba8946c dockerRepository: airbyte/source-facebook-marketing - dockerImageTag: 0.2.73 + dockerImageTag: 0.2.74 documentationUrl: https://docs.airbyte.com/integrations/sources/facebook-marketing icon: facebook.svg sourceType: api diff --git a/airbyte-config/init/src/main/resources/seed/source_specs.yaml b/airbyte-config/init/src/main/resources/seed/source_specs.yaml index 5cb6f2b0186ff..d7582d939351a 100644 --- a/airbyte-config/init/src/main/resources/seed/source_specs.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_specs.yaml @@ -3396,7 +3396,7 @@ supportsNormalization: false supportsDBT: false supported_destination_sync_modes: [] -- dockerImage: "airbyte/source-facebook-marketing:0.2.73" +- dockerImage: "airbyte/source-facebook-marketing:0.2.74" spec: documentationUrl: "https://docs.airbyte.com/integrations/sources/facebook-marketing" changelogUrl: "https://docs.airbyte.com/integrations/sources/facebook-marketing" @@ -3651,7 +3651,10 @@ action_breakdowns: title: "Action Breakdowns" description: "A list of chosen action_breakdowns for action_breakdowns" - default: [] + default: + - "action_type" + - "action_target_id" + - "action_destination" type: "array" items: title: "ValidActionBreakdowns" diff --git a/airbyte-integrations/connectors/source-facebook-marketing/Dockerfile b/airbyte-integrations/connectors/source-facebook-marketing/Dockerfile index 9def614575ff0..7d6b21abe5a5e 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/Dockerfile +++ b/airbyte-integrations/connectors/source-facebook-marketing/Dockerfile @@ -13,5 +13,5 @@ ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] -LABEL io.airbyte.version=0.2.73 +LABEL io.airbyte.version=0.2.74 LABEL io.airbyte.name=airbyte/source-facebook-marketing diff --git a/airbyte-integrations/connectors/source-facebook-marketing/integration_tests/spec.json b/airbyte-integrations/connectors/source-facebook-marketing/integration_tests/spec.json index f27ad1bfc415d..a500163eb1880 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/integration_tests/spec.json +++ b/airbyte-integrations/connectors/source-facebook-marketing/integration_tests/spec.json @@ -250,7 +250,7 @@ "action_breakdowns": { "title": "Action Breakdowns", "description": "A list of chosen action_breakdowns for action_breakdowns", - "default": [], + "default": ["action_type", "action_target_id", "action_destination"], "type": "array", "items": { "title": "ValidActionBreakdowns", diff --git a/airbyte-integrations/connectors/source-facebook-marketing/setup.py b/airbyte-integrations/connectors/source-facebook-marketing/setup.py index ac757a2d80aea..c25b0c89972a8 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/setup.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages, setup MAIN_REQUIREMENTS = [ - "airbyte-cdk~=0.2", + "airbyte-cdk~=0.9", "cached_property==1.5.2", "facebook_business==15.0.0", "pendulum>=2,<3", diff --git a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/source.py b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/source.py index ce412bda58f5b..04b116a02a071 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/source.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/source.py @@ -32,7 +32,7 @@ Videos, ) -from .utils import read_full_refresh, validate_end_date, validate_start_date +from .utils import validate_end_date, validate_start_date logger = logging.getLogger("airbyte") @@ -63,11 +63,10 @@ def check_connection(self, logger: logging.Logger, config: Mapping[str, Any]) -> except requests.exceptions.RequestException as e: return False, e - # read one record from all custom insights streams - # to ensure that we have valid combination of "action_breakdowns" and "breakdowns" parameters + # make sure that we have valid combination of "action_breakdowns" and "breakdowns" parameters for stream in self.get_custom_insights_streams(api, config): try: - next(read_full_refresh(stream), None) + stream.check_breakdowns() except facebook_business.exceptions.FacebookRequestError as e: return False, e._api_error_message return True, None diff --git a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/spec.py b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/spec.py index 65497276005ba..fc08360a99a14 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/spec.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/spec.py @@ -47,7 +47,7 @@ class Config: action_breakdowns: Optional[List[ValidActionBreakdowns]] = Field( title="Action Breakdowns", description="A list of chosen action_breakdowns for action_breakdowns", - default=[], + default=["action_type", "action_target_id", "action_destination"], ) time_increment: Optional[PositiveInt] = Field( diff --git a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/streams/base_insight_streams.py b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/streams/base_insight_streams.py index 55d4898f2b0cf..bbb918d046b9b 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/streams/base_insight_streams.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/streams/base_insight_streams.py @@ -49,13 +49,10 @@ class AdsInsights(FBMarketingIncrementalStream): # https://developers.facebook.com/docs/marketing-api/reference/ad-account/insights/#overview INSIGHTS_RETENTION_PERIOD = pendulum.duration(months=37) - action_breakdowns = ALL_ACTION_BREAKDOWNS level = "ad" action_attribution_windows = ALL_ACTION_ATTRIBUTION_WINDOWS time_increment = 1 - breakdowns = [] - def __init__( self, name: str = None, @@ -70,8 +67,8 @@ def __init__( self._start_date = self._start_date.date() self._end_date = self._end_date.date() self._fields = fields - self.action_breakdowns = action_breakdowns or self.action_breakdowns - self.breakdowns = breakdowns or self.breakdowns + self.action_breakdowns = action_breakdowns or self.ALL_ACTION_BREAKDOWNS + self.breakdowns = breakdowns or [] self.time_increment = time_increment or self.time_increment self._new_class_name = name self._insights_lookback_window = insights_lookback_window @@ -198,6 +195,18 @@ def _generate_async_jobs(self, params: Mapping) -> Iterator[AsyncJob]: interval = pendulum.Period(ts_start, ts_end) yield InsightAsyncJob(api=self._api.api, edge_object=self._api.account, interval=interval, params=params) + def check_breakdowns(self): + """ + Making call to check "action_breakdowns" and "breakdowns" combinations + https://developers.facebook.com/docs/marketing-api/insights/breakdowns#combiningbreakdowns + """ + params = { + "action_breakdowns": self.action_breakdowns, + "breakdowns": self.breakdowns, + "fields": ["account_id"], + } + self._api.account.get_insights(params=params, is_async=False) + def stream_slices( self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None ) -> Iterable[Optional[Mapping[str, Any]]]: diff --git a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/utils.py b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/utils.py index c5e3e2a99f1f5..392658ef18259 100644 --- a/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/utils.py +++ b/airbyte-integrations/connectors/source-facebook-marketing/source_facebook_marketing/utils.py @@ -5,8 +5,6 @@ import logging import pendulum -from airbyte_cdk.models import SyncMode -from airbyte_cdk.sources.streams import Stream from pendulum import DateTime logger = logging.getLogger("airbyte") @@ -42,11 +40,3 @@ def validate_end_date(start_date: DateTime, end_date: DateTime) -> DateTime: logger.warning(message) return start_date return end_date - - -def read_full_refresh(stream_instance: Stream): - slices = stream_instance.stream_slices(sync_mode=SyncMode.full_refresh) - for _slice in slices: - records = stream_instance.read_records(stream_slice=_slice, sync_mode=SyncMode.full_refresh) - for record in records: - yield record diff --git a/docs/integrations/sources/facebook-marketing.md b/docs/integrations/sources/facebook-marketing.md index 0034f2edc62a7..5275f331084b8 100644 --- a/docs/integrations/sources/facebook-marketing.md +++ b/docs/integrations/sources/facebook-marketing.md @@ -127,6 +127,7 @@ Please be informed that the connector uses the `lookback_window` parameter to pe | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.2.74 | 2022-11-25 | [19803](https://github.com/airbytehq/airbyte/pull/19803) | New default for `action_breakdowns`, improve "check" command speed | | 0.2.73 | 2022-11-21 | [19645](https://github.com/airbytehq/airbyte/pull/19645) | Check "breakdowns" combinations | | 0.2.72 | 2022-11-04 | [18971](https://github.com/airbytehq/airbyte/pull/18971) | handle FacebookBadObjectError for empty results on async jobs | | 0.2.71 | 2022-10-31 | [18734](https://github.com/airbytehq/airbyte/pull/18734) | Reduce request record limit on retry |