Skip to content

Commit caf84ed

Browse files
authored
Flesh out the log event and log writer classes (#2175)
* Add timekeeping infrastructure. * Add the log proto protocol. * Flesh out the log event a bit. * Flesh out the log writer. * Put in comments for the log proto protocol. * Move queue to a private header and update the TODO. * Add comment about the QoS tier * Fix style
1 parent 546bf67 commit caf84ed

File tree

11 files changed

+274
-3
lines changed

11 files changed

+274
-3
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
NS_ASSUME_NONNULL_BEGIN
20+
21+
/** A struct to hold data pertaining to a snapshot in time. */
22+
typedef struct {
23+
/** The current time in millis. */
24+
int64_t timeMillis;
25+
26+
/** The device uptime in millis. */
27+
int64_t uptimeMillis;
28+
29+
/** The timezone offset in millis. */
30+
int64_t timezoneOffsetMillis;
31+
} GDLLogClockSnapshot;
32+
33+
/** This class manages the device clock and produces snapshots of the current time. */
34+
@interface GDLLogClock : NSObject
35+
36+
// TODO(mikehaney24): - (GDLLogClockSnapshot)snapshot;
37+
38+
@end
39+
40+
NS_ASSUME_NONNULL_END
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GDLLogClock.h"
18+
19+
@implementation GDLLogClock
20+
21+
@end

GoogleDataLogger/GoogleDataLogger/Classes/GDLLogEvent.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,54 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19+
#import "GDLLogClock.h"
20+
#import "GDLLogProto.h"
21+
22+
NS_ASSUME_NONNULL_BEGIN
23+
24+
/** The different possible log quality of service specifiers. High values indicate high priority. */
25+
typedef NS_ENUM(NSInteger, GDLLogQoS) {
26+
/** The QoS tier wasn't set, and won't ever be sent. */
27+
GDLLogQoSUnknown = 0,
28+
29+
/** This log is internal telemetry data that should not be sent on its own if possible. */
30+
GDLLogQoSTelemetry = 1,
31+
32+
/** This log should be sent, but in a batch only roughly once per day. */
33+
GDLLogQoSDaily = 2,
34+
35+
/** This log should be sent when requested by the uploader. */
36+
GDLLogQosDefault = 3,
37+
38+
/** This log should be sent immediately along with any other data that can be batched. */
39+
GDLLogQoSFast = 4
40+
};
41+
1942
@interface GDLLogEvent : NSObject
2043

44+
/** The log map identifier, to allow backends to map the extension property to a proto. */
45+
@property(readonly, nonatomic) NSString *logMapID;
46+
47+
/** The log object itself, encapsulated in the transport of your choice, as long as it implements
48+
* the GDLLogProto protocol. */
49+
@property(nonatomic) id<GDLLogProto> extension;
50+
51+
/** The quality of service tier this log belongs to. */
52+
@property(nonatomic) GDLLogQoS qosTier;
53+
54+
/** The clock snapshot at the time of logging. */
55+
@property(nonatomic) GDLLogClockSnapshot clockSnapshot;
56+
57+
// Please use the designated initializer.
58+
- (instancetype)init NS_UNAVAILABLE;
59+
60+
/** Initializes an instance using the given logMapID.
61+
*
62+
* @param logMapID The log map identifier.
63+
* @return An instance of this class.
64+
*/
65+
- (instancetype)initWithLogMapID:(NSString *)logMapID NS_DESIGNATED_INITIALIZER;
66+
2167
@end
68+
69+
NS_ASSUME_NONNULL_END

GoogleDataLogger/GoogleDataLogger/Classes/GDLLogEvent.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,13 @@
1818

1919
@implementation GDLLogEvent
2020

21+
- (instancetype)initWithLogMapID:(NSString *)logMapID {
22+
NSAssert(logMapID.length > 0, @"Please give a valid log map ID");
23+
self = [super init];
24+
if (self) {
25+
_logMapID = logMapID;
26+
}
27+
return self;
28+
}
29+
2130
@end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
/** This protocol defines the common interface that log protos should implement regardless of the
20+
* underlying transport technology (protobuf, nanopb, etc).
21+
*/
22+
@protocol GDLLogProto <NSObject>
23+
24+
/** Returns the serialized proto bytes of the implementing log proto.
25+
*
26+
* @return the serialized proto bytes of the implementing log proto.
27+
*/
28+
- (NSData *)protoBytes;
29+
30+
@end

GoogleDataLogger/GoogleDataLogger/Classes/GDLLogWriter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,25 @@
1616

1717
#import <Foundation/Foundation.h>
1818

19+
@class GDLLogEvent;
20+
21+
@protocol GDLLogTransformer;
22+
1923
/** Manages the writing and log-time transforming of logs. */
2024
@interface GDLLogWriter : NSObject
2125

26+
/** Instantiates or returns the log writer singleton.
27+
*
28+
* @return The singleton instance of the log writer.
29+
*/
30+
+ (instancetype)sharedInstance;
31+
32+
/** Writes the result of applying the given transformers' -transform method on the given log.
33+
*
34+
* @param log The log to apply transformers on.
35+
* @param logTransformers The list of transformers to apply.
36+
*/
37+
- (void)writeLog:(GDLLogEvent *)log
38+
afterApplyingTransformers:(nullable NSArray<id<GDLLogTransformer>> *)logTransformers;
39+
2240
@end

GoogleDataLogger/GoogleDataLogger/Classes/GDLLogWriter.m

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,46 @@
1515
*/
1616

1717
#import "GDLLogWriter.h"
18+
#import "GDLLogWriter_Private.h"
1819

19-
@implementation GDLLogWriter : NSObject
20+
#import <GoogleDataLogger/GDLLogTransformer.h>
21+
22+
#import "GDLLogStorage.h"
23+
24+
@implementation GDLLogWriter
25+
26+
// This class doesn't have to be a singleton, but allocating an instance for every logger could be
27+
// wasteful.
28+
+ (instancetype)sharedInstance {
29+
static GDLLogWriter *logWriter;
30+
static dispatch_once_t onceToken;
31+
dispatch_once(&onceToken, ^{
32+
logWriter = [[self alloc] init];
33+
});
34+
return logWriter;
35+
}
36+
37+
- (instancetype)init {
38+
self = [super init];
39+
if (self) {
40+
_logWritingQueue = dispatch_queue_create("com.google.GDLLogWriter", DISPATCH_QUEUE_SERIAL);
41+
}
42+
return self;
43+
}
44+
45+
- (void)writeLog:(GDLLogEvent *)log
46+
afterApplyingTransformers:(NSArray<id<GDLLogTransformer>> *)logTransformers {
47+
NSAssert(log, @"You can't write a nil log");
48+
dispatch_async(_logWritingQueue, ^{
49+
GDLLogEvent *transformedLog = log;
50+
for (id<GDLLogTransformer> transformer in logTransformers) {
51+
transformedLog = [transformer transform:transformedLog];
52+
if (!transformedLog) {
53+
return;
54+
}
55+
}
56+
// TODO(mikehaney24): [[GDLLogStorage sharedInstance] storeLog:transformedLog];
57+
});
58+
}
2059

2160
@end

GoogleDataLogger/GoogleDataLogger/Classes/GDLLogger.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ - (void)logDataEvent:(GDLLogEvent *)logEvent {
6060
}
6161

6262
- (GDLLogEvent *)newEvent {
63-
return [[GDLLogEvent alloc] init];
63+
return [[GDLLogEvent alloc] initWithLogMapID:_logMapID];
6464
}
6565

6666
@end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2018 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "GDLLogWriter.h"
18+
19+
@interface GDLLogWriter ()
20+
21+
/** The queue on which all work will occur. */
22+
@property(nonatomic) dispatch_queue_t logWritingQueue;
23+
24+
@end

GoogleDataLogger/Tests/GDLLogEventTest.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ @interface GDLLogEventTest : XCTestCase
2525
@implementation GDLLogEventTest
2626

2727
- (void)testInit {
28-
XCTAssertNotNil([[GDLLogEvent alloc] init]);
28+
XCTAssertNotNil([[GDLLogEvent alloc] initWithLogMapID:@"1"]);
29+
XCTAssertThrows([[GDLLogEvent alloc] initWithLogMapID:@""]);
2930
}
3031

3132
@end

GoogleDataLogger/Tests/GDLLogWriterTest.m

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,23 @@
1616

1717
#import <XCTest/XCTest.h>
1818

19+
#import <GoogleDataLogger/GDLLogTransformer.h>
20+
21+
#import "GDLLogEvent.h"
1922
#import "GDLLogWriter.h"
23+
#import "GDLLogWriter_Private.h"
24+
25+
@interface GDLLogWriterTestNilingTransformer : NSObject <GDLLogTransformer>
26+
27+
@end
28+
29+
@implementation GDLLogWriterTestNilingTransformer
30+
31+
- (GDLLogEvent *)transform:(GDLLogEvent *)logEvent {
32+
return nil;
33+
}
34+
35+
@end
2036

2137
@interface GDLLogWriterTest : XCTestCase
2238

@@ -29,4 +45,29 @@ - (void)testInit {
2945
XCTAssertNotNil([[GDLLogWriter alloc] init]);
3046
}
3147

48+
/** Tests the pointer equality of result of the -sharedInstance method. */
49+
- (void)testSharedInstance {
50+
XCTAssertEqual([GDLLogWriter sharedInstance], [GDLLogWriter sharedInstance]);
51+
}
52+
53+
- (void)testWriteLogWithoutTransformers {
54+
GDLLogWriter *writer = [GDLLogWriter sharedInstance];
55+
GDLLogEvent *log = [[GDLLogEvent alloc] initWithLogMapID:@"1"];
56+
XCTAssertNoThrow([writer writeLog:log afterApplyingTransformers:nil]);
57+
dispatch_sync(writer.logWritingQueue, ^{
58+
// TODO(mikehaney24): Assert that storage contains the log.
59+
});
60+
}
61+
62+
- (void)testWriteLogWithTransformersThatNilTheLog {
63+
GDLLogWriter *writer = [GDLLogWriter sharedInstance];
64+
GDLLogEvent *log = [[GDLLogEvent alloc] initWithLogMapID:@"2"];
65+
NSArray<id<GDLLogTransformer>> *transformers =
66+
@[ [[GDLLogWriterTestNilingTransformer alloc] init] ];
67+
XCTAssertNoThrow([writer writeLog:log afterApplyingTransformers:transformers]);
68+
dispatch_sync(writer.logWritingQueue, ^{
69+
// TODO(mikehaney24): Assert that storage does not contain the log.
70+
});
71+
}
72+
3273
@end

0 commit comments

Comments
 (0)