TwitterLoggingServiceExt/TLSExt.h (22 lines of code) (raw):
//
// TLSExt.h
// TwitterLoggingService
//
// Created on 6/28/19.
// Copyright © 2020 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol TLSExtOSLogActivityMonitor;
@class TLSLogMessageInfo;
//! Domain for `TLSExt` errors
FOUNDATION_EXTERN NSErrorDomain const TLSExtErrorDomain;
//! block for providing a log message info to log
typedef void(^TLSExtOSLogActivityLogMessageBlock)(TLSLogMessageInfo *info);
//! Set the start time of `os_log` entries (can be rough estimate). For computing the relative time elapsed of any given entry. Leaving unset will use the first encountered `os_log` entry's timestamp (until this function is called).
FOUNDATION_EXTERN void TLSExtSetOSLogActivityStartTimestamp(NSDate *timestamp);
/**
Register a `TLSExtOSLogActivityMonitor` for monitoring `os_log` messages.
The registration process will also load the private __LoggingSupport.framework__.
@param monitor the `TLSExtOSLogActivityMonitor` to observe events with
@param outError an `NSError` if registration failed
@return returns `YES` if the _monitor_ could register successfully. `NO` if registration failed.
@warning Since this function requires using a private Apple framework, this should ONLY ever be used by non-production apps. Running this code (and potentially even just compiling it!) will result in the app being rejected by Apple. For development purposes ONLY! See `TLSLogExt`.
*/
FOUNDATION_EXTERN BOOL TLSExtRegisterOSLogActivityMonitor(id<TLSExtOSLogActivityMonitor> monitor, NSError * __nullable * __nullable outError);
//! Convenience function to create a `TLSExtOSLogActivityMonitor` instance. See `TLSExtOSLogActivityMonitor`.
FOUNDATION_EXTERN id<TLSExtOSLogActivityMonitor> TLSExtOLSLogActivityMonitorCreate(NSString * __nullable defaultChannel,
TLSExtOSLogActivityLogMessageBlock __nullable logMessageBlock,
TLSExtOSLogActivityLogMessageBlock __nullable activityStreamEventBlock) NS_RETURNS_RETAINED;
/**
A protocol for monitoring `os_log` entries.
Currenly supports _log message_ and _activity stream event_ entries.
@note log message entries that are _debug_ level will not be passed to the monitor (just too verbose).
@note log message entries that come from `NSLog` will not be passed to the monitor.
@warning all source messages are from `os_log` so it is critical that no output messages go to
`os_log` or you will hit an infinite loop! Take care you do not log these messages to
`TLSOSLogOutputStream`. `TLSNSLogOutputStream` will be fine since `NSLog` messages are filtered
out by the __TLSExt__ system that captures `os_log` messages.
*/
@protocol TLSExtOSLogActivityMonitor <NSObject>
@optional
/**
default channel for the `TLSLogMessageInfo` if a channel cannot be surmised.
If not implemented or `nil`, will fall back to `@"OSLog"`.
*/
- (nullable NSString *)tlsext_defaultChannel;
/** callback when a _log message_ entry is encountered */
- (void)tlsext_logMessage:(TLSLogMessageInfo *)info;
/** callback when an _activity stream event_ occurs */
- (void)tlsext_activityStreamEvent:(TLSLogMessageInfo *)info;
// TODO: add support for additional entries like trace messages
@end
#if APPLEDOC
/**
# __Twitter Logging Service Extensions__ (aka __TLSExt__)
__TLSExt__ provides extra functionality outside of __TLS__ itself and can be compiled and linked by
any app consuming __TLS__.
The features of __TLSExt__ are tied to Private frameworks from Apple and are therefore deemed
_unsafe_ for shipping with production code.
@warning Only compile / link __TLSExt__ into non-production builds! Compiling/linking __TLSExt__ into production builds __will__ result in app store rejection!
@note __TLSExt__ depends on __TLS__, but it would be fairly simple to change the `TLSLogMessageInfo` uses into something that doesn't depend on __TLS__ if you want to capture `os_log` activity without depending on __TLS__.
## TLSExt Errors
FOUNDATION_EXTERN NSString * const TLSExtErrorDomain;
## os_log activity monitoring
__TLSExt__ provides APIs to observe `os_log` activity. This is a great feature when capturing logs
to debug issues that might only be seen in the logs from Apple frameworks, or if `os_log` ends up
being a logging mechanism for an app.
At Twitter, we elect to capture the `os_log` activity and write it to disk in a rolling log. When
an employee encounters an issue and they file a bug report from our dogfood app, these logs (among
others) are zipped up and sent to our bug reporting system. We do not link __TLSExt__ at all in
production -- it is strictly a tool for non-production builds.
### Set the start time for activity monitoring
Call `TLSExtSetOSLogActivityStartTimestamp` with and `NSDate` timestamp to set the starting time
when `os_log` activity started (can be rough estimate). Leaving unset will use the first encountered `os_log` entry's timestamp (until this function is called).
FOUNDATION_EXTERN void TLSExtSetOSLogActivityStartTimestamp(NSDate *timestamp);
### Create an os_log activity monitor instance
Use `TLSExtOLSLogActivityMonitorCreate` convenience function to create a `TLSExtOSLogActivityMonitor`
instance. See `TLSExtOSLogActivityMonitor`.
FOUNDATION_EXTERN id \<TLSExtOSLogActivityMonitor\> TLSExtOLSLogActivityMonitorCreate(
NSString * __nullable defaultChannel,
TLSExtOSLogActivityLogMessageBlock __nullable logMessageBlock,
TLSExtOSLogActivityLogMessageBlock __nullable activityStreamEventBlock
) NS_RETURNS_RETAINED;
Or instantiate a custom implementation of `TLSExtOSLogActivityMonitor` protocol
### Registering an os_log activity monitor
Register a `TLSExtOSLogActivityMonitor` for monitoring `os_log` messages with `TLSExtRegisterOSLogActivityMonitor`
FOUNDATION_EXTERN BOOL TLSExtRegisterOSLogActivityMonitor(id \<TLSExtOSLogActivityMonitor\> monitor,
NSError * __nullable * __nullable outError);
Returns `YES` if the _monitor_ could register successfully. `NO` if registration failed.
### CFNETWORK_DIAGNOSTICS monitoring
With __TLSExt__ support of `os_log` monitoring, it is now possible to easily capture `CFNetwork`
logs to help debug while developing. What used to require a special profile installed on a specific
device followed by a sysdiagnose (takes 10 minutes to gather!), now can just be captured in whatever
logs you prefer.
To enable `CFNetwork` logs, you must set the `"CFNETWORK_DIAGNOSTICS"` environment variable to a
desired logging level (`"1"`, `"2"` or `"3"`), and it must be done _before_ any `NSURLSession`
instances are instantiated.
setenv("CFNETWORK_DIAGNOSTICS", "1", 1);
3 ways to do it:
1. Set the environment variable before running the given app (edit target app's scheme: under Run > Arguments > Environment Variables).
2. Set the environment variable early during execution, such as during the `main` function starting.
3. Set the environment variable with a C constructor (so it runs before `main`).
*/
NS_ROOT_CLASS @interface TLSExt
@end
#endif
NS_ASSUME_NONNULL_END