Exemplo n.º 1
0
    def update_project_symbol_source(self, project: Project,
                                     allow_multiple: bool) -> json.JSONData:
        """Updates this configuration in the Project's symbol sources.

        If a symbol source of type ``appStoreConnect`` already exists the ID must match and it
        will be updated.  If no ``appStoreConnect`` source exists yet it is added.

        :param allow_multiple: Whether multiple appStoreConnect sources are allowed for this
           project.

        :returns: The new value of the sources.  Use this in a call to
           `ProjectEndpoint.create_audit_entry()` to create an audit log.

        :raises ValueError: if an ``appStoreConnect`` source already exists but the ID does not
           match
        """
        with transaction.atomic():
            all_sources_raw = project.get_option(SYMBOL_SOURCES_PROP_NAME)
            all_sources = json.loads(
                all_sources_raw) if all_sources_raw else []
            for i, source in enumerate(all_sources):
                if source.get("type") == SYMBOL_SOURCE_TYPE_NAME:
                    if source.get("id") == self.id:
                        all_sources[i] = self.to_json()
                        break
                    elif not allow_multiple:
                        raise ValueError(
                            "Existing appStoreConnect symbolSource config does not match id"
                        )
            else:
                # No matching existing appStoreConnect symbol source, append it.
                all_sources.append(self.to_json())
            project.update_option(SYMBOL_SOURCES_PROP_NAME,
                                  json.dumps(all_sources))
        return all_sources
Exemplo n.º 2
0
def update_build_refresh_date(project: Project, config_id: str) -> None:
    serialized_option = project.get_option(
        appconnect.APPSTORECONNECT_BUILD_REFRESHES_OPTION, default="{}")
    build_refresh_dates = json.loads(serialized_option)
    build_refresh_dates[config_id] = datetime.now()
    serialized_refresh_dates = json.dumps_htmlsafe(build_refresh_dates)
    project.update_option(appconnect.APPSTORECONNECT_BUILD_REFRESHES_OPTION,
                          serialized_refresh_dates)
Exemplo n.º 3
0
 def all_for_project(cls,
                     project: Project) -> "List[AppStoreConnectConfig]":
     sources = []
     raw = project.get_option(SYMBOL_SOURCES_PROP_NAME, default="[]")
     all_sources = json.loads(raw)
     for source in all_sources:
         if source.get("type") == SYMBOL_SOURCE_TYPE_NAME:
             sources.append(cls.from_json(source))
     return sources
Exemplo n.º 4
0
 def all_config_ids(project: Project) -> List[str]:
     """Return the config IDs of all appStoreConnect symbol sources configured in the project."""
     raw = project.get_option(SYMBOL_SOURCES_PROP_NAME)
     if not raw:
         raw = "[]"
     all_sources = json.loads(raw)
     return [
         s.get("id") for s in all_sources
         if s.get("type") == SYMBOL_SOURCE_TYPE_NAME and s.get("id")
     ]
def get_app_store_config(
        project: Project,
        credentials_id: Optional[str]) -> Optional[json.JSONData]:
    """Returns the appStoreConnect symbol source config for a project."""
    sources_config = project.get_option(SYMBOL_SOURCES_PROP_NAME)

    if credentials_id is None:
        return None
    try:
        sources = json.loads(sources_config)
        for source in sources:
            if (source.get("type") == "appStoreConnect"
                    and source.get("id") == credentials_id.lower()):
                return source
        return None
    except BaseException as e:
        raise ValueError("bad sources") from e
Exemplo n.º 6
0
    def from_project_config(cls, project: Project,
                            config_id: str) -> "AppStoreConnectConfig":
        """Creates a new instance from the symbol source configured in the project.

        :raises KeyError: if the config is not found.
        :raises InvalidConfigError if the stored config is somehow invalid.
        """
        raw = project.get_option(SYMBOL_SOURCES_PROP_NAME, default="[]")
        all_sources = json.loads(raw)
        for source in all_sources:
            if source.get("type") == SYMBOL_SOURCE_TYPE_NAME and (
                    source.get("id") == config_id):
                return cls.from_json(source)
        else:
            raise KeyError(
                f"No {SYMBOL_SOURCE_TYPE_NAME} symbol source found with id {config_id}"
            )
Exemplo n.º 7
0
def get_transaction_metrics_settings(
        project: Project, breakdowns_config: Optional[Mapping[str, Any]]):
    metrics = []
    custom_tags = []

    if features.has("organizations:transaction-metrics-extraction",
                    project.organization):
        metrics.extend(sorted(TRANSACTION_METRICS))
        # TODO: for now let's extract all known measurements. we might want to
        # be more fine-grained in the future once we know which measurements we
        # really need (or how that can be dynamically determined)
        metrics.extend(sorted(ALL_MEASUREMENT_METRICS))

        if breakdowns_config is not None:
            # we already have a breakdown configuration that tells relay which
            # breakdowns to compute for an event. metrics extraction should
            # probably be in sync with that, or at least not extract more metrics
            # than there are breakdowns configured.
            try:
                for breakdown_name, breakdown_config in breakdowns_config.items(
                ):
                    assert breakdown_config["type"] == "spanOperations"

                    for op_name in breakdown_config["matches"]:
                        metrics.append(
                            f"sentry.transactions.breakdowns.{breakdown_name}.{op_name}"
                        )
            except Exception:
                capture_exception()

        # Tells relay which user-defined tags to add to each extracted
        # transaction metric.  This cannot include things such as `os.name`
        # which are computed on the server, they have to come from the SDK as
        # event tags.
        try:
            custom_tags.extend(
                project.get_option("sentry:transaction_metrics_custom_tags")
                or ())
        except Exception:
            capture_exception()

    return {
        "extractMetrics": metrics,
        "extractCustomTags": custom_tags,
        "satisfactionThresholds": _get_satisfaction_thresholds(project),
    }
Exemplo n.º 8
0
    def from_project_config(cls, project: Project,
                            config_id: str) -> "AppStoreConnectConfig":
        """Creates a new instance from the symbol source configured in the project.

        :raises KeyError: if the config is not found.
        :raises InvalidConfigError if the stored config is somehow invalid.
        """
        raw = project.get_option(SYMBOL_SOURCES_PROP_NAME)

        # UI bug: the UI writes an empty string when removing the last symbol source from
        # the list.  So we need to cater for both `None` and `''` being returned from
        # .get_option().
        if not raw:
            raw = "[]"

        all_sources = json.loads(raw)
        for source in all_sources:
            if source.get("type") == SYMBOL_SOURCE_TYPE_NAME and (
                    source.get("id") == config_id):
                return cls.from_json(source)
        else:
            raise KeyError(
                f"No {SYMBOL_SOURCE_TYPE_NAME} symbol source found with id {config_id}"
            )