Skip to content

Commit

Permalink
Merge pull request #10 from NullIsOne/analytics-proxy
Browse files Browse the repository at this point in the history
Analytics proxy
  • Loading branch information
NullIsOne authored Apr 3, 2024
2 parents 791da3f + a81e172 commit acc7080
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
- collecting of analytic events with playback data for Kinescope dashboard
- textField in example project to allow user to input videoId
- ability to manage options menu on player view
- ability to listen analytic events in `KinescopeAnalyticsDelegate`
16 changes: 16 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,19 @@ To add new localization to strings from SDK, add in your project file "Kinescope
# Error Handling

KinescopePlayerView has inbox error handling logic and retry-mechanism. If video is not available or some error occured player will try to retry failed operation 10 times with 5 seconds delay between each attempt. If all attempts failed player will show error overlay with refresh button.

# Analytics

KinescopePlayer automaticaly send analytic events to Kinescope dashboard. You can get access to this events by implementing `KinescopeAnalyticsDelegate` protocol and set it like below

```swift
Kinescope.shared.setAnalytics(delegate: yourDelegate)
```

In delegate you can check all playback data which we sending to Kinescope dashboard.

If you want to log only events without playback data, you can intercept them using `logger`.

```swift
Kinescope.shared.set(logger: KinescopeDefaultLogger(), levels: [KinescopeLoggerLevel.analytics])
```
9 changes: 9 additions & 0 deletions Example/KinescopeExample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

private func setupSDK() {
Kinescope.shared.setConfig(.init())
Kinescope.shared.setAnalytics(delegate: self)
Kinescope.shared.set(logger: KinescopeDefaultLogger(), levels: KinescopeLoggerLevel.allCases)
}

Expand All @@ -50,3 +51,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

}

extension AppDelegate: KinescopeAnalyticsDelegate {

func didSendAnalytics(event: String, with data: String) {
debugPrint("Catched analytic event: \(event) with data \(data)")
}

}
2 changes: 1 addition & 1 deletion Sources/KinescopeSDK/Events/InnerEventsProtoHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private extension InnerEventsProtoHandler {
$0.device = dataStorage.device.provide() ?? .init()
$0.session = dataStorage.session.provide() ?? .init()
$0.playback = dataStorage.playback.provide() ?? .init()
$0.eventTime = .init()
$0.eventTime = .init(date: Date())
return
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ extension Manager: KinescopeConfigurable {
assetService: AssetNetworkService())
self.inspector = Inspector(videosService: VideosNetworkService(transport: Transport(),
config: config))
self.analyticFactory = AnalyticHandler(service: AnalyticsNetworkService(transport: Transport(), config: config))
self.analyticFactory = AnalyticHandler(service: AnalyticsProxyService(wrappedServices: [
AnalyticsNetworkService(transport: Transport(), config: config),
AnalyticsLoggingService()
]))

}

func setAnalytics(delegate: any KinescopeAnalyticsDelegate) {
Kinescope.analyticDelegate = delegate
}

func set(logger: KinescopeLogging, levels: [KinescopeLoggingLevel]) {
self.logger = KinescopeLogger(logger: logger, levels: levels)
Expand Down
1 change: 1 addition & 0 deletions Sources/KinescopeSDK/Player/KinescopeVideoPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public class KinescopeVideoPlayer: KinescopePlayer, KinescopePlayerBody, Fullscr

public required convenience init(config: KinescopePlayerConfig) {
self.init(config: config, dependencies: KinescopeVideoPlayerDependencies())
self.configureAnalytic()
}

public func play() {
Expand Down
5 changes: 4 additions & 1 deletion Sources/KinescopeSDK/Protocols/KinescopeConfigurable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ public protocol KinescopeConfigurable {

/// - parameter config: Configuration parameters required to connection
func setConfig(_ config: KinescopeConfig)

/// - parameter delegate: Delegate to listen for analytics sended from ``KinescopeVideoPlayer``
func setAnalytics(delegate: KinescopeAnalyticsDelegate)

/// - parameter logger: opportunity to set custom logger
/// - parameter levels: levels of logging
func set(logger: KinescopeLogging, levels: [KinescopeLoggingLevel])

}
17 changes: 17 additions & 0 deletions Sources/KinescopeSDK/Service/Analytic/AnalyticsDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// KinescopeAnalyticsDelegate.swift
// KinescopeSDK
//
// Created by Nikita Korobeinikov on 02.04.2024.
//

import Foundation

/// Delegate to listen for analytics sended from ``KinescopeVideoPlayer``
public protocol KinescopeAnalyticsDelegate {
/// Fired when ``KinescopeVideoPlayer`` is sending any analytics `event`
/// - Parameters:
/// - event: name of the event
/// - data: serialized data in `String` format
func didSendAnalytics(event: String, with data: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// AnalyticsLoggingService.swift
// KinescopeSDK
//
// Created by Nikita Korobeinikov on 02.04.2024.
//

import Foundation

/// Implementation of ``AnalyticsService`` which can delegate sending to client code
final class AnalyticsLoggingService: AnalyticsService {

func send(event: Analytics_Native) {
Kinescope.analyticDelegate?.didSendAnalytics(event: event.event,
with: event.textFormatString())
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
//
// AnalyticsService.swift
// AnalyticsNetworkService.swift
// KinescopeSDK
//
// Created by Artemii Shabanov on 27.04.2021.
// Created by Nikita Korobeinikov on 02.04.2024.
//

import Foundation

protocol AnalyticsService {
func send(event: Analytics_Native)
}

/// Implementation of ``AnalyticsService`` which will send analytic via network to kinescope dashboard
final class AnalyticsNetworkService: AnalyticsService {

// MARK: - Private Properties
Expand Down
23 changes: 23 additions & 0 deletions Sources/KinescopeSDK/Service/Analytic/AnalyticsProxyService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// AnalyticsProxyService.swift
// KinescopeSDK
//
// Created by Nikita Korobeinikov on 02.04.2024.
//

import Foundation

/// Implementation of ``AnalyticsService`` which can delegate sending to other services
final class AnalyticsProxyService: AnalyticsService {

private let wrappedServices: [AnalyticsService]

init(wrappedServices: [AnalyticsService]) {
self.wrappedServices = wrappedServices
}

func send(event: Analytics_Native) {
wrappedServices.forEach { $0.send(event: event) }
}

}
12 changes: 12 additions & 0 deletions Sources/KinescopeSDK/Service/Analytic/AnalyticsService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// AnalyticsService.swift
// KinescopeSDK
//
// Created by Artemii Shabanov on 27.04.2021.
//

import Foundation

protocol AnalyticsService {
func send(event: Analytics_Native)
}
2 changes: 2 additions & 0 deletions Sources/KinescopeSDK/Shared/Kinescope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public enum Kinescope {
static var analytic: KinescopeAnalyticHandlerFactory? {
return (shared as? Manager)?.analyticFactory
}

static var analyticDelegate: KinescopeAnalyticsDelegate? = nil
}

0 comments on commit acc7080

Please sign in to comment.