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 40e46cdecc042..1fcb3c8fbe7b2 100644 --- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml @@ -1554,7 +1554,7 @@ - name: Postgres sourceDefinitionId: decd338e-5647-4c0b-adf4-da0e75f5a750 dockerRepository: airbyte/source-postgres - dockerImageTag: 2.0.4 + dockerImageTag: 2.0.5 documentationUrl: https://docs.airbyte.com/integrations/sources/postgres icon: postgresql.svg sourceType: database 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 2c95ac03124ad..d5c92bb971593 100644 --- a/airbyte-config/init/src/main/resources/seed/source_specs.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_specs.yaml @@ -11882,7 +11882,7 @@ supportsNormalization: false supportsDBT: false supported_destination_sync_modes: [] -- dockerImage: "airbyte/source-postgres:2.0.4" +- dockerImage: "airbyte/source-postgres:2.0.5" spec: documentationUrl: "https://docs.airbyte.com/integrations/sources/postgres" connectionSpecification: diff --git a/airbyte-integrations/bases/base-java/Dockerfile b/airbyte-integrations/bases/base-java/Dockerfile index e6da294f31f08..bdca035e4c2b1 100644 --- a/airbyte-integrations/bases/base-java/Dockerfile +++ b/airbyte-integrations/bases/base-java/Dockerfile @@ -6,6 +6,9 @@ RUN yum install -y tar openssl && yum clean all WORKDIR /airbyte +# Add the Datadog Java APM agent +ADD https://dtdg.co/latest-java-tracer dd-java-agent.jar + COPY javabase.sh . # airbyte base commands @@ -18,5 +21,5 @@ ENV AIRBYTE_WRITE_CMD "/airbyte/javabase.sh --write" ENV AIRBYTE_ENTRYPOINT "/airbyte/base.sh" ENTRYPOINT ["/airbyte/base.sh"] -LABEL io.airbyte.version=0.1.1 +LABEL io.airbyte.version=0.1.2 LABEL io.airbyte.name=airbyte/integration-base-java diff --git a/airbyte-integrations/bases/base-java/build.gradle b/airbyte-integrations/bases/base-java/build.gradle index 45d66f5e2adbe..8b9483dd5ec28 100644 --- a/airbyte-integrations/bases/base-java/build.gradle +++ b/airbyte-integrations/bases/base-java/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation libs.jackson.annotations implementation libs.connectors.testcontainers implementation libs.connectors.testcontainers.jdbc + implementation libs.bundles.datadog implementation files(project(':airbyte-integrations:bases:base').airbyteDocker.outputs) diff --git a/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/base/IntegrationRunner.java b/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/base/IntegrationRunner.java index 0d1757e4e64a8..3f58d694a0fcb 100644 --- a/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/base/IntegrationRunner.java +++ b/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/base/IntegrationRunner.java @@ -9,11 +9,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import datadog.trace.api.Trace; import io.airbyte.commons.io.IOs; import io.airbyte.commons.json.Jsons; import io.airbyte.commons.lang.Exceptions.Procedure; import io.airbyte.commons.string.Strings; import io.airbyte.commons.util.AutoCloseableIterator; +import io.airbyte.integrations.util.ApmTraceUtils; import io.airbyte.integrations.util.ConnectorExceptionUtil; import io.airbyte.protocol.models.v0.AirbyteConnectionStatus; import io.airbyte.protocol.models.v0.AirbyteMessage; @@ -92,6 +94,7 @@ public IntegrationRunner(final Source source) { validator = jsonSchemaValidator; } + @Trace(operationName = "RUN_OPERATION") public void run(final String[] args) throws Exception { final IntegrationConfig parsed = cliParser.parse(args); try { @@ -155,6 +158,7 @@ private void runInternal(final IntegrationConfig parsed) throws Exception { // to // find the root exception that corresponds to a configuration error. If that does not exist, we // just return the original exception. + ApmTraceUtils.addExceptionToTrace(e); final Throwable rootThrowable = ConnectorExceptionUtil.getRootConfigError(e); final String displayMessage = ConnectorExceptionUtil.getDisplayMessage(rootThrowable); // If the source connector throws a config error, a trace message with the relevant message should diff --git a/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/util/ApmTraceUtils.java b/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/util/ApmTraceUtils.java new file mode 100644 index 0000000000000..555c7d4dd6c86 --- /dev/null +++ b/airbyte-integrations/bases/base-java/src/main/java/io/airbyte/integrations/util/ApmTraceUtils.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.integrations.util; + +import datadog.trace.api.DDTags; +import datadog.trace.api.interceptor.MutableSpan; +import io.opentracing.Span; +import io.opentracing.log.Fields; +import io.opentracing.tag.Tags; +import io.opentracing.util.GlobalTracer; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Map; + +/** + * Collection of utility methods to help with performance tracing. + */ +public class ApmTraceUtils { + + /** + * String format for the name of tags added to spans. + */ + public static final String TAG_FORMAT = "airbyte.%s.%s"; + + /** + * Standard prefix for tags added to spans. + */ + public static final String TAG_PREFIX = "metadata"; + + /** + * Adds all the provided tags to the currently active span, if one exists.
+ * All tags added via this method will use the default {@link #TAG_PREFIX} namespace. + * + * @param tags A map of tags to be added to the currently active span. + */ + public static void addTagsToTrace(final Map tags) { + addTagsToTrace(tags, TAG_PREFIX); + } + + /** + * Adds all provided tags to the currently active span, if one exists, under the provided tag name + * namespace. + * + * @param tags A map of tags to be added to the currently active span. + * @param tagPrefix The prefix to be added to each custom tag name. + */ + public static void addTagsToTrace(final Map tags, final String tagPrefix) { + addTagsToTrace(GlobalTracer.get().activeSpan(), tags, tagPrefix); + } + + /** + * Adds all the provided tags to the provided span, if one exists. + * + * @param span The {@link Span} that will be associated with the tags. + * @param tags A map of tags to be added to the currently active span. + * @param tagPrefix The prefix to be added to each custom tag name. + */ + public static void addTagsToTrace(final Span span, final Map tags, final String tagPrefix) { + if (span != null) { + tags.entrySet().forEach(entry -> { + span.setTag(formatTag(entry.getKey(), tagPrefix), entry.getValue().toString()); + }); + } + } + + /** + * Adds an exception to the currently active span, if one exists. + * + * @param t The {@link Throwable} to be added to the currently active span. + */ + public static void addExceptionToTrace(final Throwable t) { + addExceptionToTrace(GlobalTracer.get().activeSpan(), t); + } + + /** + * Adds an exception to the provided span, if one exists. + * + * @param span The {@link Span} that will be associated with the exception. + * @param t The {@link Throwable} to be added to the provided span. + */ + public static void addExceptionToTrace(final Span span, final Throwable t) { + if (span != null) { + span.setTag(Tags.ERROR, true); + span.log(Map.of(Fields.ERROR_OBJECT, t)); + } + } + + /** + * Adds all the provided tags to the root span. + * + * @param tags A map of tags to be added to the root span. + */ + public static void addTagsToRootSpan(final Map tags) { + final Span activeSpan = GlobalTracer.get().activeSpan(); + if (activeSpan instanceof MutableSpan) { + final MutableSpan localRootSpan = ((MutableSpan) activeSpan).getLocalRootSpan(); + tags.entrySet().forEach(entry -> { + localRootSpan.setTag(formatTag(entry.getKey(), TAG_PREFIX), entry.getValue().toString()); + }); + } + } + + /** + * Adds an exception to the root span, if an active one exists. + * + * @param t The {@link Throwable} to be added to the provided span. + */ + public static void recordErrorOnRootSpan(final Throwable t) { + final Span activeSpan = GlobalTracer.get().activeSpan(); + if (activeSpan != null) { + activeSpan.setTag(Tags.ERROR, true); + activeSpan.log(Map.of(Fields.ERROR_OBJECT, t)); + } + if (activeSpan instanceof MutableSpan) { + final MutableSpan localRootSpan = ((MutableSpan) activeSpan).getLocalRootSpan(); + localRootSpan.setError(true); + localRootSpan.setTag(DDTags.ERROR_MSG, t.getMessage()); + localRootSpan.setTag(DDTags.ERROR_TYPE, t.getClass().getName()); + final StringWriter errorString = new StringWriter(); + t.printStackTrace(new PrintWriter(errorString)); + localRootSpan.setTag(DDTags.ERROR_STACK, errorString.toString()); + } + } + + /** + * Formats the tag key using {@link #TAG_FORMAT} provided by this utility, using the default tag + * prefix {@link #TAG_PREFIX}. + * + * @param tagKey The tag key to format. + * @return The formatted tag key. + */ + public static String formatTag(final String tagKey) { + return formatTag(tagKey, TAG_PREFIX); + } + + /** + * Formats the tag key using {@link #TAG_FORMAT} provided by this utility with the provided tag + * prefix. + * + * @param tagKey The tag key to format. + * @param tagPrefix The prefix to be added to each custom tag name. + * @return The formatted tag key. + */ + public static String formatTag(final String tagKey, final String tagPrefix) { + return String.format(TAG_FORMAT, tagPrefix, tagKey); + } + +} diff --git a/airbyte-integrations/connectors/source-jdbc/build.gradle b/airbyte-integrations/connectors/source-jdbc/build.gradle index cb142aeab7114..488357c8ec515 100644 --- a/airbyte-integrations/connectors/source-jdbc/build.gradle +++ b/airbyte-integrations/connectors/source-jdbc/build.gradle @@ -25,6 +25,7 @@ dependencies { implementation project(':airbyte-integrations:connectors:source-relational-db') implementation 'org.apache.commons:commons-lang3:3.11' + implementation libs.bundles.datadog testImplementation project(':airbyte-test-utils') diff --git a/airbyte-integrations/connectors/source-jdbc/src/main/java/io/airbyte/integrations/source/jdbc/AbstractJdbcSource.java b/airbyte-integrations/connectors/source-jdbc/src/main/java/io/airbyte/integrations/source/jdbc/AbstractJdbcSource.java index 371e61739d3da..ddf9e47b8ab02 100644 --- a/airbyte-integrations/connectors/source-jdbc/src/main/java/io/airbyte/integrations/source/jdbc/AbstractJdbcSource.java +++ b/airbyte-integrations/connectors/source-jdbc/src/main/java/io/airbyte/integrations/source/jdbc/AbstractJdbcSource.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; +import datadog.trace.api.Trace; import io.airbyte.commons.functional.CheckedConsumer; import io.airbyte.commons.json.Jsons; import io.airbyte.commons.map.MoreMaps; @@ -114,6 +115,7 @@ protected AutoCloseableIterator queryTableFullRefresh(final JdbcDataba * * @return list of consumers that run queries for the check command. */ + @Trace(operationName = CHECK_TRACE_OPERATION_NAME) protected List> getCheckOperations(final JsonNode config) throws Exception { return ImmutableList.of(database -> { LOGGER.info("Attempting to get metadata from the database to see if we can connect."); diff --git a/airbyte-integrations/connectors/source-postgres-strict-encrypt/Dockerfile b/airbyte-integrations/connectors/source-postgres-strict-encrypt/Dockerfile index 5fee22eb9a506..6cdb8854dfea2 100644 --- a/airbyte-integrations/connectors/source-postgres-strict-encrypt/Dockerfile +++ b/airbyte-integrations/connectors/source-postgres-strict-encrypt/Dockerfile @@ -16,5 +16,5 @@ ENV APPLICATION source-postgres-strict-encrypt COPY --from=build /airbyte /airbyte -LABEL io.airbyte.version=2.0.4 +LABEL io.airbyte.version=2.0.5 LABEL io.airbyte.name=airbyte/source-postgres-strict-encrypt diff --git a/airbyte-integrations/connectors/source-postgres/Dockerfile b/airbyte-integrations/connectors/source-postgres/Dockerfile index aa621bd05f0cd..8bd693da5b92f 100644 --- a/airbyte-integrations/connectors/source-postgres/Dockerfile +++ b/airbyte-integrations/connectors/source-postgres/Dockerfile @@ -16,5 +16,5 @@ ENV APPLICATION source-postgres COPY --from=build /airbyte /airbyte -LABEL io.airbyte.version=2.0.4 +LABEL io.airbyte.version=2.0.5 LABEL io.airbyte.name=airbyte/source-postgres diff --git a/airbyte-integrations/connectors/source-postgres/build.gradle b/airbyte-integrations/connectors/source-postgres/build.gradle index 25ad1091c1cb2..90236cd25b35f 100644 --- a/airbyte-integrations/connectors/source-postgres/build.gradle +++ b/airbyte-integrations/connectors/source-postgres/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.11' implementation libs.postgresql + implementation libs.bundles.datadog testImplementation testFixtures(project(':airbyte-integrations:bases:debezium')) testImplementation testFixtures(project(':airbyte-integrations:connectors:source-jdbc')) diff --git a/airbyte-integrations/connectors/source-postgres/src/main/java/io/airbyte/integrations/source/postgres/PostgresSource.java b/airbyte-integrations/connectors/source-postgres/src/main/java/io/airbyte/integrations/source/postgres/PostgresSource.java index aaf7bf5258a79..983ea0bc8e661 100644 --- a/airbyte-integrations/connectors/source-postgres/src/main/java/io/airbyte/integrations/source/postgres/PostgresSource.java +++ b/airbyte-integrations/connectors/source-postgres/src/main/java/io/airbyte/integrations/source/postgres/PostgresSource.java @@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import io.airbyte.commons.exceptions.ConfigErrorException; +import datadog.trace.api.Trace; import io.airbyte.commons.features.EnvVariableFeatureFlags; import io.airbyte.commons.features.FeatureFlags; import io.airbyte.commons.functional.CheckedConsumer; @@ -57,6 +58,7 @@ import io.airbyte.integrations.source.relationaldb.models.CdcState; import io.airbyte.integrations.source.relationaldb.models.DbState; import io.airbyte.integrations.source.relationaldb.state.StateManager; +import io.airbyte.integrations.util.ApmTraceUtils; import io.airbyte.integrations.util.HostPortResolver; import io.airbyte.protocol.models.CommonField; import io.airbyte.protocol.models.v0.AirbyteCatalog; @@ -212,6 +214,7 @@ protected Set getExcludedViews() { } @Override + @Trace(operationName = DISCOVER_TRACE_OPERATION_NAME) public AirbyteCatalog discover(final JsonNode config) throws Exception { final AirbyteCatalog catalog = super.discover(config); @@ -281,6 +284,7 @@ List getReplicationSlot(final JdbcDatabase database, final JsonNode co } } + @Trace(operationName = CHECK_TRACE_OPERATION_NAME) @Override public List> getCheckOperations(final JsonNode config) throws Exception { @@ -503,6 +507,7 @@ public static void main(final String[] args) throws Exception { } @Override + @Trace(operationName = CHECK_TRACE_OPERATION_NAME) public AirbyteConnectionStatus check(final JsonNode config) throws Exception { if (PostgresUtils.isCdc(config)) { if (config.has(SSL_MODE) && config.get(SSL_MODE).has(MODE)) { diff --git a/airbyte-integrations/connectors/source-relational-db/build.gradle b/airbyte-integrations/connectors/source-relational-db/build.gradle index a58ae385673e6..fb68ad573760e 100644 --- a/airbyte-integrations/connectors/source-relational-db/build.gradle +++ b/airbyte-integrations/connectors/source-relational-db/build.gradle @@ -14,6 +14,7 @@ dependencies { implementation project(':airbyte-config:config-models') implementation 'org.apache.commons:commons-lang3:3.11' + implementation libs.bundles.datadog testImplementation project(':airbyte-test-utils') diff --git a/airbyte-integrations/connectors/source-relational-db/src/main/java/io/airbyte/integrations/source/relationaldb/AbstractDbSource.java b/airbyte-integrations/connectors/source-relational-db/src/main/java/io/airbyte/integrations/source/relationaldb/AbstractDbSource.java index 090fd2968fd4b..c96be4d31b30e 100644 --- a/airbyte-integrations/connectors/source-relational-db/src/main/java/io/airbyte/integrations/source/relationaldb/AbstractDbSource.java +++ b/airbyte-integrations/connectors/source-relational-db/src/main/java/io/airbyte/integrations/source/relationaldb/AbstractDbSource.java @@ -8,6 +8,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import datadog.trace.api.Trace; import io.airbyte.commons.exceptions.ConfigErrorException; import io.airbyte.commons.exceptions.ConnectionErrorException; import io.airbyte.commons.features.EnvVariableFeatureFlags; @@ -31,6 +33,7 @@ import io.airbyte.integrations.source.relationaldb.state.StateManager; import io.airbyte.integrations.source.relationaldb.state.StateManagerFactory; import io.airbyte.integrations.util.ConnectorExceptionUtil; +import io.airbyte.integrations.util.ApmTraceUtils; import io.airbyte.protocol.models.CommonField; import io.airbyte.protocol.models.JsonSchemaPrimitiveUtil.JsonSchemaPrimitive; import io.airbyte.protocol.models.JsonSchemaType; @@ -62,6 +65,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; + +import io.opencensus.trace.Span; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,11 +77,16 @@ public abstract class AbstractDbSource extends BaseConnector implements Source, AutoCloseable { + public static final String CHECK_TRACE_OPERATION_NAME = "check-operation"; + public static final String DISCOVER_TRACE_OPERATION_NAME = "discover-operation"; + public static final String READ_TRACE_OPERATION_NAME = "read-operation"; + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDbSource.class); // TODO: Remove when the flag is not use anymore private final FeatureFlags featureFlags = new EnvVariableFeatureFlags(); @Override + @Trace(operationName = CHECK_TRACE_OPERATION_NAME) public AirbyteConnectionStatus check(final JsonNode config) throws Exception { try { final Database database = createDatabase(config); @@ -86,6 +96,7 @@ public AirbyteConnectionStatus check(final JsonNode config) throws Exception { return new AirbyteConnectionStatus().withStatus(Status.SUCCEEDED); } catch (final ConnectionErrorException ex) { + ApmTraceUtils.addExceptionToTrace(ex); final String message = getErrorMessage(ex.getStateCode(), ex.getErrorCode(), ex.getExceptionMessage(), ex); AirbyteTraceMessageUtility.emitConfigErrorTrace(ex, message); @@ -93,6 +104,7 @@ public AirbyteConnectionStatus check(final JsonNode config) throws Exception { .withStatus(Status.FAILED) .withMessage(message); } catch (final Exception e) { + ApmTraceUtils.addExceptionToTrace(e); LOGGER.info("Exception while checking connection: ", e); return new AirbyteConnectionStatus() .withStatus(Status.FAILED) @@ -103,6 +115,7 @@ public AirbyteConnectionStatus check(final JsonNode config) throws Exception { } @Override + @Trace(operationName = DISCOVER_TRACE_OPERATION_NAME) public AirbyteCatalog discover(final JsonNode config) throws Exception { try { final Database database = createDatabase(config); @@ -525,6 +538,7 @@ protected Set getPrivilegesTableForCurrentUser(final JdbcDatabase databas * @param config database implementation-specific configuration. * @return database spec config */ + @Trace(operationName = DISCOVER_TRACE_OPERATION_NAME) public abstract JsonNode toDatabaseConfig(JsonNode config); /** @@ -534,6 +548,7 @@ protected Set getPrivilegesTableForCurrentUser(final JdbcDatabase databas * @return database instance * @throws Exception might throw an error during connection to database */ + @Trace(operationName = DISCOVER_TRACE_OPERATION_NAME) protected abstract Database createDatabase(JsonNode config) throws Exception; /** @@ -575,6 +590,7 @@ protected Set getExcludedViews() { * @return list of the source tables * @throws Exception access to the database might lead to an exceptions. */ + @Trace(operationName = DISCOVER_TRACE_OPERATION_NAME) protected abstract List>> discoverInternal( final Database database) throws Exception; diff --git a/connectors.md b/connectors.md index e44a3ae7f8363..5966c58ff09e2 100644 --- a/connectors.md +++ b/connectors.md @@ -177,7 +177,7 @@ | **PokeAPI** | PokeAPI icon | Source | airbyte/source-pokeapi:0.1.5 | alpha | [link](https://docs.airbyte.com/integrations/sources/pokeapi) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-pokeapi) | `6371b14b-bc68-4236-bfbd-468e8df8e968` | | **Polygon Stock API** | Polygon Stock API icon | Source | airbyte/source-polygon-stock-api:0.1.1 | alpha | [link](https://docs.airbyte.com/integrations/sources/polygon-stock-api) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-polygon-stock-api) | `5807d72f-0abc-49f9-8fa5-ae820007032b` | | **PostHog** | PostHog icon | Source | airbyte/source-posthog:0.1.8 | beta | [link](https://docs.airbyte.com/integrations/sources/posthog) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-posthog) | `af6d50ee-dddf-4126-a8ee-7faee990774f` | -| **Postgres** | Postgres icon | Source | airbyte/source-postgres:2.0.4 | generally_available | [link](https://docs.airbyte.com/integrations/sources/postgres) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-postgres) | `decd338e-5647-4c0b-adf4-da0e75f5a750` | +| **Postgres** | Postgres icon | Source | airbyte/source-postgres:2.0.5 | generally_available | [link](https://docs.airbyte.com/integrations/sources/postgres) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-postgres) | `decd338e-5647-4c0b-adf4-da0e75f5a750` | | **Postmark App** | Postmark App icon | Source | airbyte/source-postmarkapp:0.1.0 | alpha | [link](https://docs.airbyte.com/integrations/sources/postmarkapp) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-postmarkapp) | `cde75ca1-1e28-4a0f-85bb-90c546de9f1f` | | **PrestaShop** | PrestaShop icon | Source | airbyte/source-prestashop:0.3.1 | beta | [link](https://docs.airbyte.com/integrations/sources/prestashop) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-prestashop) | `d60a46d4-709f-4092-a6b7-2457f7d455f5` | | **Primetric** | Primetric icon | Source | airbyte/source-primetric:0.1.0 | alpha | [link](https://docs.airbyte.com/integrations/sources/primetric) | [code](https://github.com/airbytehq/airbyte/tree/master/airbyte-integrations/connectors/source-primetric) | `f636c3c6-4077-45ac-b109-19fc62a283c1` | diff --git a/docs/integrations/sources/postgres.md b/docs/integrations/sources/postgres.md index 183ecaff57be3..2238fb85e43e8 100644 --- a/docs/integrations/sources/postgres.md +++ b/docs/integrations/sources/postgres.md @@ -396,6 +396,7 @@ The root causes is that the WALs needed for the incremental sync has been remove | Version | Date | Pull Request | Subject | |:--------|:-----------|:----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.0.5 | 2022-03-21 | [21533](https://github.com/airbytehq/airbyte/pull/21533) | Add integration with datadog | | 2.0.4 | 2023-03-21 | [24147](https://github.com/airbytehq/airbyte/pull/24275) | Fix error with CDC checkpointing | | 2.0.3 | 2023-03-14 | [24000](https://github.com/airbytehq/airbyte/pull/24000) | Removed check method call on read. | | 2.0.2 | 2023-03-13 | [23112](https://github.com/airbytehq/airbyte/pull/21727) | Add state checkpointing for CDC sync. |