从单个iOS应用程序

时间:2018-02-09 12:42:45

标签: ios cocoa configuration error-logging sentry

我们做什么: 我们正在构建一个用于与外部硬件设备通信的应用程序。应用程序可以从外部设备接收日志消息。应用程序已将应用程序事件记录到Sentry项目中。

我们想做什么: 我们希望应用程序将从外部设备接收的日志传递给单独的Sentry项目,而不依赖于应用程序本身记录的任何内容。为实现这一目标,我们创建了一个新项目,并使用这两个项目配置了两个Client个对象。的DSN。

问题: 事件被记录到正确的项目中,但是面包屑似乎对Client个对象使用共享存储,因此它们包含来自两个项目的事件。

是否有一种简单的方法可以为两个Client对象或其BreadcrumbStore s定义单独的套件/域/文件夹?

我们尝试过: 我们正在研究子类化SentryFileManager并将其传递给新的BreadcrumbStore,但对于这样一个微不足道的任务来说似乎不必要地复杂化。

2 个答案:

答案 0 :(得分:0)

1)子类SentryFileManager修改其路径

此问题似乎是SentryFileManagerinit(error:)的硬编码路径属性:

NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

self.sentryPath = [cachePath stringByAppendingPathComponent:@"io.sentry"];
...
self.breadcrumbsPath = [self.sentryPath stringByAppendingPathComponent:@"breadcrumbs"];
...
self.eventsPath = [self.sentryPath stringByAppendingPathComponent:@"events"];

不幸的是,它们都是私有的,因此子类化SentryFileManager仍然不会让我们访问它们。虽然我不推荐它,但我们最终使用键/值编码来设置它们以绕过编译器的访问控制。

如果目录不存在,请记住创建目录。

这个子类中没有任何东西可以继续存在。它只是使用提供的域名的唯一封装URL覆盖受保护的属性。

class DomainFileManager: SentryFileManager {

    private enum Component {
        static let sentry      = "io.sentry"
        static let breadcrumbs = "breadcrumbs"
        static let events      = "events"
    }

    private enum Key {
        static let sentryPath      = "sentryPath"
        static let breadcrumbsPath = "breadcrumbsPath"
        static let eventsPath      = "eventsPath"
    }


    private static var cacheURL: URL {
        return FileManager.default.urls(
            for: .cachesDirectory,
            in:  .userDomainMask
        )[0]
    }

    private let domainURL: URL

    private var sentryURL: URL {
        return domainURL.appendingPathComponent(Component.sentry)
    }

    private var breadcrumbsURL: URL {
        return sentryURL.appendingPathComponent(Component.breadcrumbs)
    }

    private var eventsURL: URL {
        return sentryURL.appendingPathComponent(Component.events)
    }


    init(domain: String, error: ()) throws {

        domainURL = DomainFileManager.cacheURL.appendingPathComponent(domain)

        try super.init(error: error)

        setValue(sentryURL.path, forKey: Key.sentryPath)
        setValue(breadcrumbsURL.path, forKey: Key.breadcrumbsPath)
        setValue(eventsURL.path, forKey: Key.eventsPath)

        for url in [sentryURL, breadcrumbsURL, eventsURL] {
            if !FileManager.default.fileExists(atPath: url.path) {
                try DomainFileManager.createDirectory(atPath: url.path)
            }
        }
    }
}

正如您所看到的,子类化并不是绝对必要的,但其他对象实际上不应该开始弄乱SentryFileManager的私有属性。也不应该是子类,但它们“真的不应该”少一点。

2)更新客户端痕迹导航商店

然后我们使用我们的子类为外部设备的Sentry客户端定义一个新的BreadcrumbStore

let fileManager = try DomainFileManager(domain: "domain", error: ())

client.breadcrumbs = BreadcrumbStore(fileManager: fileManager)

那么,那可能就是全部,不是吗?事实证明它不是。

3)更新客户端文件管理器

事实证明,客户端本身包含一个导致问题的私有文件管理器。突然,面包屑存储在封装的路径中,但事件使用默认的SentryFileManager存储。

我们必须再次深入研究,并使用键/值编码来规避访问控制。

let fileManager = try DomainFileManager(domain: "domain", error: ())

client.breadcrumbs = BreadcrumbStore(fileManager: fileManager)

client.setValue(fileManager, forKey: "fileManager")

那就是所有人!

答案 1 :(得分:0)

Sentry 3.10 +支持记录到多个项目