Feature/4454 tracking config

This commit is contained in:
Frank Rotermund
2023-05-02 10:55:41 +00:00
committed by Arnfried Griesert
parent 280d19922f
commit f7b22e1f1a
7 changed files with 146 additions and 41 deletions

View File

@@ -534,8 +534,15 @@ class BWIBuildSettings: NSObject {
var bwiShowHappyBirthdayCampaign = false
var bwiHappyBirthdayCampaignIdentifier: String = "2022"
var bwiDisableSecuritySettingsUntrustedDevices = true
// MARK: - analytics with matomo
var bwiMatomoTrackingDefaultState = false
var bwiMatomoEnabled = false
var matomoNameProd = ""
var matomoNameBeta = ""
var matomoServerProd = ""
var bwiShowNewFeatures = true
// MARK: - Message Bubbles bwi show in our menu and only for beta builds

View File

@@ -52,6 +52,7 @@ targets:
- path: ../bwi/NotificationTimes/Date+fromHourMinute.swift
- path: ../bwi/MatomoAnalytics/BWIAnalytics.swift
- path: ../bwi/MatomoAnalytics/BWIAnalyticsAccountDataService.swift
- path: ../bwi/MatomoAnalytics/AnalyticsConfiguration.swift
- path: ../bwi/MatomoAnalytics/E2EEError.swift
- path: ../Riot/Managers/Settings/RiotSettings.swift
- path: ../Config/BuildSettings.swift

View File

@@ -23,5 +23,4 @@ struct AppConfig: Codable, Equatable {
var contentScannerUrl: String? = nil
var pusherUrl: String? = nil
var permalinkUrl: String? = nil
var analyticsURL: String? = nil
}

View File

@@ -84,10 +84,6 @@ extension UserDefaults
}
func registerForAppConfig() {
// configObserver = UserDefaults.standard.observe(\.appConfigData, options:[.new,.old])
// { (object, change) in
// self.handleAppConfig()
// }
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: OperationQueue.main) { [self] (note) in
handleAppConfig()
@@ -162,14 +158,4 @@ extension UserDefaults
return BWIBuildSettings.shared.clientPermalinkBaseUrl
}
}
func analyticsUrl() -> String {
if let url = appConfig.analyticsURL {
return "https://" + url
} else if let url = ServerURLHelper.shared.analytics() {
return url
} else {
return BWIBuildSettings.shared.bwiAnalyticsServerUrlString
}
}
}

View File

@@ -0,0 +1,99 @@
//
/*
* Copyright (c) 2022 BWI GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Foundation
struct AnalyticsConfiguration {
private enum ConfigType: String {
case productive, beta, test, userdefined, undefined
}
private struct Config {
let baseUrl: String
let siteID: String
let sendMessageDimensionIndex: Int
}
private var currentConfigs: [String:Config] = [:]
private var selectedConfigType: ConfigType = .undefined
mutating func readConfig( jsonFile: String ) {
let fileURL = URL(fileURLWithPath: jsonFile)
do {
let jsonData = try Data(contentsOf: fileURL)
let json = try JSONSerialization.jsonObject(with: jsonData, options: [])
if let dictionary = json as? [String: Any] {
if let configArray = dictionary["config"] as? [[String: Any]] {
for configDict in configArray {
// Access the values in each dictionary
if let type = configDict["type"] as? String,
let baseURL = configDict["baseURL"] as? String,
let siteID = configDict["siteID"] as? String,
let sendMessageDimensionIndex = configDict["sendMessageDimensionIndex"] as? String {
currentConfigs[type] = Config(baseUrl: baseURL, siteID: siteID, sendMessageDimensionIndex: Int(sendMessageDimensionIndex)!)
}
}
}
}
} catch {
}
selectedConfigType = self.computeConfigurationType()
}
func selectedBaseURL() -> String? {
if let config = currentConfigs[selectedConfigType.rawValue] {
return config.baseUrl
}
return nil
}
func selectedSiteID() -> String? {
if let config = currentConfigs[selectedConfigType.rawValue] {
return config.siteID
}
return nil
}
func selectedSendMessageDimensionIndex() -> Int? {
if let config = currentConfigs[selectedConfigType.rawValue] {
return config.sendMessageDimensionIndex
}
return nil
}
private func computeConfigurationType() -> ConfigType {
if currentConfigs[ConfigType.userdefined.rawValue] != nil {
return .userdefined
}
if AppInfo.current.displayName == BWIBuildSettings.shared.matomoNameProd {
return .productive
}
if AppInfo.current.displayName == BWIBuildSettings.shared.matomoNameBeta {
if AppConfigService.shared.serverUrl() == BWIBuildSettings.shared.matomoServerProd {
return .beta
} else {
return .test
}
}
return .undefined
}
}

View File

@@ -47,6 +47,8 @@ import MatomoTracker
private var session: MXSession? = nil
private var analyticsConfig: AnalyticsConfiguration
private override init() {
if !BWIBuildSettings.shared.secondaryAppName.isEmpty {
appName = BWIBuildSettings.shared.secondaryAppName
@@ -55,16 +57,26 @@ import MatomoTracker
}
appVersion = AppInfo.current.appVersion?.bundleShortVersion ?? ""
analyticsConfig = AnalyticsConfiguration()
if BWIBuildSettings.shared.bwiMatomoEnabled {
if let path = Bundle.main.path(forResource: "trackingConfig", ofType: "json") {
analyticsConfig.readConfig(jsonFile: path)
}
// bwi: Analytics use custom config
guard let url = URL(string: AppConfigService.shared.analyticsUrl()) else {
guard let urlPath = analyticsConfig.selectedBaseURL(),
let url = URL(string: urlPath),
let siteID = analyticsConfig.selectedSiteID() else {
matomo = nil
return
}
matomo = MatomoTracker.init(siteId: BWIBuildSettings.shared.bwiAnalyticsAppId, baseURL:url, userAgent: nil)
matomo = MatomoTracker.init(siteId: siteID, baseURL:url, userAgent: nil)
matomo?.isOptedOut = false
matomo?.dispatchInterval = 5.0
matomo?.logger = DefaultLogger(minLevel: .verbose)
@@ -91,19 +103,19 @@ import MatomoTracker
// reset clientId on logout using internal matomo keys
func resetUserdefaults() {
// bwi: Analytics use custom config
let suiteName = BWIBuildSettings.shared.bwiAnalyticsAppId + AppConfigService.shared.analyticsUrl()
if let userdefaults = UserDefaults(suiteName: suiteName) {
userdefaults.removeObject(forKey: "PiwikTotalNumberOfVistsKey")
userdefaults.removeObject(forKey: "PiwikCurrentVisitTimestampKey")
userdefaults.removeObject(forKey: "PiwikPreviousVistsTimestampKey")
userdefaults.removeObject(forKey: "PiwikFirstVistsTimestampKey")
userdefaults.removeObject(forKey: "PiwikVisitorIDKey")
userdefaults.removeObject(forKey: "PiwikForcedVisitorIDKey")
userdefaults.removeObject(forKey: "PiwikVisitorUserIDKey")
userdefaults.removeObject(forKey: "PiwikOptOutKey")
userdefaults.removeObject(forKey: "PiwikLastOrderDateKey")
}
if let siteID = analyticsConfig.selectedSiteID(),
let baseURL = analyticsConfig.selectedBaseURL(),
let userdefaults = UserDefaults(suiteName: siteID + baseURL) {
userdefaults.removeObject(forKey: "PiwikTotalNumberOfVistsKey")
userdefaults.removeObject(forKey: "PiwikCurrentVisitTimestampKey")
userdefaults.removeObject(forKey: "PiwikPreviousVistsTimestampKey")
userdefaults.removeObject(forKey: "PiwikFirstVistsTimestampKey")
userdefaults.removeObject(forKey: "PiwikVisitorIDKey")
userdefaults.removeObject(forKey: "PiwikForcedVisitorIDKey")
userdefaults.removeObject(forKey: "PiwikVisitorUserIDKey")
userdefaults.removeObject(forKey: "PiwikOptOutKey")
userdefaults.removeObject(forKey: "PiwikLastOrderDateKey")
}
}
// Uses Userdefaults instead of Account Data because it needs to be shown on every login
@@ -158,9 +170,11 @@ import MatomoTracker
func trackSlowMessage( dimension: String, value: Int) {
if fastRunning {
// bwi: Analytics use custom config
matomo?.setDimension(dimension, forIndex: 2)
matomo?.track(eventWithCategory: "Performance", action: "SendMessage", name: nil, number: NSNumber(value: value), url:nil)
matomo?.remove(dimensionAtIndex: 2)
if let dimensionIndex = analyticsConfig.selectedSendMessageDimensionIndex() {
matomo?.setDimension(dimension, forIndex: dimensionIndex)
matomo?.track(eventWithCategory: "Performance", action: "SendMessage", name: nil, number: NSNumber(value: value), url:nil)
matomo?.remove(dimensionAtIndex: dimensionIndex)
}
}
}
}
@@ -227,9 +241,9 @@ extension BWIAnalytics : MXAnalyticsDelegate {
func trackE2EEError(_ errorCode: Int) {
if let errorCode = AnalyticsE2EEErrorCode(rawValue: errorCode) {
self.trackBwiValue(NSNumber(value: 1), "Encryption", "SendMessage", errorCode.description)
self.trackBwiValue(NSNumber(value: 1), "Encryption", "ViewMessage", errorCode.description)
} else {
self.trackBwiValue(NSNumber(value: 1), "Encryption", "SendMessage", "Unknown_Error")
self.trackBwiValue(NSNumber(value: 1), "Encryption", "ViewMessage", "Unknown_Error")
}
}
@@ -237,11 +251,11 @@ extension BWIAnalytics : MXAnalyticsDelegate {
func trackE2EEErrors(_ reason: DecryptionFailureReason, count: Int) {
switch reason {
case .unspecified:
self.trackBwiValue(NSNumber(value: count), "Encryption", "SendMessage", "Unknown_Error")
self.trackBwiValue(NSNumber(value: count), "Encryption", "ViewMessage", "Unknown_Error")
case .olmIndexError:
self.trackBwiValue(NSNumber(value: count), "Encryption", "SendMessage", AnalyticsE2EEErrorCode(rawValue: 3)!.description)
self.trackBwiValue(NSNumber(value: count), "Encryption", "ViewMessage", AnalyticsE2EEErrorCode(rawValue: 3)!.description)
case .olmKeysNotSent:
self.trackBwiValue(NSNumber(value: count), "Encryption", "SendMessage", AnalyticsE2EEErrorCode(rawValue: 4)!.description)
self.trackBwiValue(NSNumber(value: count), "Encryption", "ViewMessage", AnalyticsE2EEErrorCode(rawValue: 4)!.description)
}
}
}

View File

@@ -51,9 +51,8 @@ import Foundation
if let server = dict[serverUrlKey],
let flavor = dict[flavorUrlKey],
let name = dict[nameKey],
let permalink = dict[permalinkKey] ,
let analytics = dict[analyticsKey] {
serverSettings.append(ServerSetting(name:name, serverUrl: server, pusherUrl: "", flavor: flavor, permalink:permalink, analytics: analytics))
let permalink = dict[permalinkKey] {
serverSettings.append(ServerSetting(name:name, serverUrl: server, pusherUrl: "", flavor: flavor, permalink:permalink, analytics: ""))
}
}
}