Log¶
The log provider prints every call to your log, Logcat, Flutter's debug console, Xcode's console or Metro's output, instead of sending it anywhere. Use it in debug builds to see exactly what your app reports, and in what order: events, properties, sign-in, consent and start-up.
| SDK | Package |
|---|---|
| Android | io.github.mkhytarmkhoian:herald-log |
| Flutter | herald_log |
| iOS | herald-ios, module HeraldLog |
| React Native | @herald-analytics/log |
Setup¶
It writes through AnalyticsLogger, so it depends on no logging library. On Android it's a
one-method interface; on Flutter, iOS and React Native it's a function type, so debugPrint,
{ message in print(message) } or (message) => console.log(message) fits as-is. On iOS, Apple's Logger works too, and shows the lines
in the Console app as well:
// Where the log lines go.
val logger = AnalyticsLogger { Log.d("analytics", it) }
// Handles events and user properties, using Herald's ready-made factories.
val logTracker = LogAnalyticsTrackerService(
eventTrackerFactory = CompositeLogEventTrackerFactory(
ScreenViewLogEventTrackerFactory(logger), // screen views
GenericLogEventTrackerFactory(logger), // every other event
),
propertySetterFactory = CompositeLogPropertySetterFactory(
GenericLogPropertySetterFactory(logger),
),
)
// Handles the rest: start-up, sign-in and sign-out, consent.
val logService = LogAnalyticsService(logger)
val herald = Herald {
provider(
name = "log",
events = logTracker,
properties = logTracker,
identity = logService,
lifecycle = logService,
consent = logService,
)
}
// Where the log lines go: print fits as-is.
let logger: AnalyticsLogger = { message in print(message) }
// Handles events and user properties, using Herald's ready-made factories.
let logTracker = LogAnalyticsTrackerService(
eventTrackerFactory: CompositeLogEventTrackerFactory([
ScreenViewLogEventTrackerFactory(logger: logger), // screen views
GenericLogEventTrackerFactory(logger: logger), // every other event
]),
propertySetterFactory: GenericLogPropertySetterFactory(logger: logger)
)
// Handles the rest: start-up, sign-in and sign-out, consent.
let logService = LogAnalyticsService(logger: logger)
let herald = Herald(providers: [
HeraldProvider(
name: "log",
events: logTracker,
properties: logTracker,
identity: logService,
lifecycle: logService,
consent: logService
)
])
// Where the log lines go: Flutter's debugPrint fits as-is.
final AnalyticsLogger logger = debugPrint;
// Handles events and user properties, using Herald's ready-made factories.
final logTracker = LogAnalyticsTrackerService(
eventTrackerFactory: CompositeLogEventTrackerFactory([
ScreenViewLogEventTrackerFactory(logger), // screen views
GenericLogEventTrackerFactory(logger), // every other event
]),
propertySetterFactory: CompositeLogPropertySetterFactory([
GenericLogPropertySetterFactory(logger),
]),
);
// Handles the rest: start-up, sign-in and sign-out, consent.
final logService = LogAnalyticsService(logger);
final herald = Herald(
providers: [
HeraldProvider(
name: 'log',
events: logTracker,
properties: logTracker,
identity: logService,
lifecycle: logService,
consent: logService,
),
],
);
// Where the log lines go: the console fits as-is.
const logger: AnalyticsLogger = (message) => console.log(message);
// Handles events and user properties, using Herald's ready-made factories.
const logTracker = new LogAnalyticsTrackerService({
eventTrackerFactory: new CompositeLogEventTrackerFactory([
new ScreenViewLogEventTrackerFactory(logger), // screen views
new GenericLogEventTrackerFactory(logger), // every other event
]),
propertySetterFactory: new CompositeLogPropertySetterFactory([
new GenericLogPropertySetterFactory(logger),
]),
});
// Handles the rest: start-up, sign-in and sign-out, consent.
const logService = new LogAnalyticsService(logger);
const herald = new Herald({
providers: [
new HeraldProvider({
name: 'log',
events: logTracker,
properties: logTracker,
identity: logService,
lifecycle: logService,
consent: logService,
}),
],
});
Register it only in debug builds, next to your real vendors; on iOS, inside #if DEBUG, and on
React Native when __DEV__ is true.
Output¶
D/analytics: [herald] start
D/analytics: [herald] enabled true
D/analytics: [herald] user demo-user
D/analytics: [herald] event fare_selected
D/analytics: ├─ fare = 1 Day Pass
D/analytics: ├─ price = 5.0
D/analytics: └─ ryder_id = Adult
D/analytics: [herald] prop tickets_purchased = 2
D/analytics: [herald] reset
Flutter, iOS and React Native print the same lines, without Logcat's prefix. Parameters are sorted by name and aligned. A screen view is headed by its screen name.
Factories¶
The log provider has the same factories as a vendor module:
ScreenViewLogEventTrackerFactory;GenericLogEventTrackerFactoryandGenericLogPropertySetterFactory;RequireMappedLogEventTrackerFactoryandRequireMappedLogPropertySetterFactory.
End its chain with RequireMappedLogEventTrackerFactory, and a debug build reports every event that
nobody mapped.
Debug builds only
The log prints the user id and every value as-is. That's the point in a debug build, and a leak in a release build.