Skip to content

Commit 9b5f166

Browse files
Nr 331577: Log common block (#337)
* NR-331557: Common Block impl * NR-331577: Impl Log common block * NR-233726: gzip logs
1 parent 925dbff commit 9b5f166

File tree

2 files changed

+173
-53
lines changed

2 files changed

+173
-53
lines changed

Agent/Utilities/NRLogger.m

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#import "NRMASupportMetricHelper.h"
1616
#import "NRMAFlags.h"
1717
#import "NRAutoLogCollector.h"
18+
#import "NRMAHarvesterConnection+GZip.h"
1819

1920
NRLogger *_nr_logger = nil;
2021

@@ -286,10 +287,14 @@ - (void)addLogMessage:(NSDictionary *)message : (BOOL) agentLogsOn {
286287
});
287288
}
288289

289-
- (NSData*) jsonDictionary:(NSDictionary*)message {
290+
- (NSMutableDictionary*) commonBlockDict {
290291
NSString* NRSessionId = [[[NewRelicAgentInternal sharedInstance] currentSessionId] copy];
291292
NRMAHarvesterConfiguration *configuration = [NRMAHarvestController configuration];
293+
294+
// The following line generates the native platform name which is used as "collector.name" in the log payload.
292295
NSString* nativePlatform = [NewRelicInternalUtils agentName];
296+
297+
// The following code generates the variable name that is chosen between native platform name or the Hybrid platform name which is used as "instrumentation.name" in the log payload.
293298
NSString* platform = [NewRelicInternalUtils stringFromNRMAApplicationPlatform:[NRMAAgentConfiguration connectionInformation].deviceInformation.platform];
294299
NSString* name = [NRMAAgentConfiguration connectionInformation].deviceInformation.platform == NRMAPlatform_Native ? nativePlatform : platform;
295300

@@ -316,6 +321,20 @@ - (NSData*) jsonDictionary:(NSDictionary*)message {
316321
entityGuid = @"";
317322
}
318323

324+
NSMutableDictionary *commonAttributes = [NSMutableDictionary dictionary];
325+
[commonAttributes setObject:entityGuid forKey:NRLogMessageEntityGuidKey];
326+
if (NRSessionId) [commonAttributes setObject:NRSessionId forKey:NRLogMessageSessionIdKey];
327+
[commonAttributes setObject:NRLogMessageMobileValue forKey:NRLogMessageInstrumentationProviderKey];
328+
if (name) [commonAttributes setObject:name forKey:NRLogMessageInstrumentationNameKey];
329+
[commonAttributes setObject:[NRMAAgentConfiguration connectionInformation].deviceInformation.agentVersion forKey:NRLogMessageInstrumentationVersionKey];
330+
if (nativePlatform) [commonAttributes setObject:nativePlatform forKey:NRLogMessageInstrumentationCollectorKey];
331+
if (nrAppId) [commonAttributes setObject:nrAppId forKey:NRLogMessageAppIdKey];
332+
333+
return commonAttributes;
334+
}
335+
336+
- (NSData*) jsonDictionary:(NSDictionary*)message {
337+
319338
NSMutableDictionary *requiredAttributes = [NSMutableDictionary dictionary];
320339

321340
id value = [message objectForKey:NRLogMessageLevelKey];
@@ -336,19 +355,6 @@ - (NSData*) jsonDictionary:(NSDictionary*)message {
336355
value = [[message objectForKey:NRLogMessageMessageKey]stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
337356
if (value) [requiredAttributes setObject:value forKey:NRLogMessageMessageKey]; // 6
338357

339-
if (NRSessionId) [requiredAttributes setObject:NRSessionId forKey:NRLogMessageSessionIdKey]; // 7
340-
if (nrAppId) [requiredAttributes setObject:nrAppId forKey:NRLogMessageAppIdKey]; // 8
341-
if (entityGuid) [requiredAttributes setObject:entityGuid forKey:NRLogMessageEntityGuidKey]; // 9
342-
343-
[requiredAttributes setObject:NRLogMessageMobileValue forKey:NRLogMessageInstrumentationProviderKey]; // 10
344-
[requiredAttributes setObject:name forKey:NRLogMessageInstrumentationNameKey]; // 11
345-
346-
value = [NRMAAgentConfiguration connectionInformation].deviceInformation.agentVersion;
347-
if (value) [requiredAttributes setObject:value forKey:NRLogMessageInstrumentationVersionKey]; // 12
348-
349-
[requiredAttributes setObject:nativePlatform forKey:NRLogMessageInstrumentationCollectorKey]; // 13
350-
351-
352358
NSMutableDictionary *providedAttributes = [message mutableCopy];
353359
[providedAttributes removeObjectsForKeys:@[NRLogMessageLevelKey,NRLogMessageFileKey,NRLogMessageLineNumberKey,NRLogMessageMethodKey,NRLogMessageTimestampKey,NRLogMessageMessageKey]];
354360
[providedAttributes addEntriesFromDictionary:requiredAttributes];
@@ -531,8 +537,30 @@ - (void)enqueueLogUpload {
531537
return;
532538
}
533539

534-
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
535-
NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
540+
// the text of the file contents is just comma separated dict objects
541+
// Add the user provided attributes to the message.
542+
NSMutableDictionary *commonBlock = [self commonBlockDict];
543+
544+
NSError* error = nil;
545+
546+
NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
547+
options:0
548+
error:&error];
549+
550+
if (error) {
551+
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
552+
}
553+
554+
// New version of the line
555+
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
556+
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
557+
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
558+
559+
// Old version of the line
560+
// NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
561+
562+
// Here we add gzip compression to the log data.
563+
NSData* formattedData = [NRMAHarvesterConnection gzipData:[logMessagesJson dataUsingEncoding:NSUTF8StringEncoding]];
536564

537565
// We clear the log when we save the existing logs to uploadQueue.
538566
[self clearLog];
@@ -582,6 +610,10 @@ - (void) processNextUploadTask {
582610
[req setValue:self->logIngestKey forHTTPHeaderField:@"X-App-License-Key"];
583611
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
584612

613+
//NSString* contentEncoding = message.length <= 512 ? kNRMAIdentityHeader : kNRMAGZipHeader;
614+
615+
[req setValue:kNRMAGZipHeader forHTTPHeaderField:kNRMAContentEncodingHeader];
616+
585617
req.HTTPMethod = @"POST";
586618

587619
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:req fromData:formattedData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

Tests/Unit-Tests/NewRelicAgentTests/Uncategorized/NRLoggerTests.m

Lines changed: 125 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
#import "NRAutoLogCollector.h"
2626
#import <os/log.h>
2727

28+
@interface NRLogger()
29+
+ (NRLogger *)logger;
30+
- (NSMutableDictionary*) commonBlockDict;
31+
@end
32+
2833
@implementation NRLoggerTests
2934
- (void) setUp
3035
{
@@ -69,8 +74,6 @@ - (void) setUp
6974
weakSelf.fileDescriptor = 0;
7075
}
7176
});
72-
73-
7477
}
7578
- (void) tearDown
7679
{
@@ -108,20 +111,40 @@ - (void) testNRLogger {
108111

109112
sleep(5);
110113

111-
NSError* error;
114+
NSError* error = nil;
112115
NSData* logData = [NRLogger logFileData:&error];
113116
if(error){
114117
NSLog(@"%@", error.localizedDescription);
115118
}
116119

117-
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
120+
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];
121+
122+
NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
123+
options:0
124+
error:&error];
125+
126+
if (error) {
127+
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
128+
XCTAssertNil(error, @"Error creating log payload");
129+
return;
130+
}
131+
132+
error = nil;
133+
// New version of the line
134+
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
135+
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
136+
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
137+
118138
NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
119139

120-
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData
140+
NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
121141
options:0
122-
error:nil];
142+
error:&error];
123143
NSLog(@"decode=%@", decode);
124144

145+
NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
146+
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];
147+
125148
NSArray * expectedValues = @[
126149
@{@"message": @"Info Log..."},
127150
@{@"message": @"Error Log..."},
@@ -131,31 +154,19 @@ - (void) testNRLogger {
131154
@{@"message": @"Debug Log..."},
132155
@{@"message": @"This is a test message for the New Relic logging system."},
133156
];
157+
134158
// check for existence of 6 logs.
135159
int foundCount = 0;
136160
// For each expected message.
137161
for (NSDictionary *dict in expectedValues) {
138162
// Iterate through the collected message logs.
139-
for (NSDictionary *dict2 in decode) {
163+
for (NSDictionary *dict2 in decodedArray) {
140164
//
141165
NSString* currentMessage = [dict objectForKey:@"message"];
166+
167+
// Check the logs entries
142168
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
143169
foundCount += 1;
144-
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
145-
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationProviderKey] isEqualToString:NRLogMessageMobileValue],@"instrumentation provider set incorrectly");
146-
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationVersionKey] isEqualToString:@"DEV"],@"instrumentation name set incorrectly");
147-
148-
#if TARGET_OS_WATCH
149-
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"watchOSAgent"],@"instrumentation name set incorrectly");
150-
#else
151-
if ([[[UIDevice currentDevice] systemName] isEqualToString:@"tvOS"]) {
152-
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"tvOSAgent"],@"instrumentation name set incorrectly");
153-
154-
}
155-
else {
156-
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"iOSAgent"],@"instrumentation name set incorrectly");
157-
}
158-
#endif
159170
}
160171
// Verify added attributes with logAttributes.
161172
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
@@ -166,6 +177,22 @@ - (void) testNRLogger {
166177
}
167178

168179
XCTAssertEqual(foundCount, 7, @"Seven messages should be found.");
180+
181+
// Verify Common Block
182+
XCTAssertTrue([[decodedCommonBlock objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
183+
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationProviderKey] isEqualToString:NRLogMessageMobileValue],@"instrumentation provider set incorrectly");
184+
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationVersionKey] isEqualToString:@"DEV"],@"instrumentation name set incorrectly");
185+
186+
#if TARGET_OS_WATCH
187+
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"watchOSAgent"],@"instrumentation name set incorrectly");
188+
#else
189+
if ([[[UIDevice currentDevice] systemName] isEqualToString:@"tvOS"]) {
190+
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"tvOSAgent"],@"instrumentation name set incorrectly");
191+
}
192+
else {
193+
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"iOSAgent"],@"instrumentation name set incorrectly");
194+
}
195+
#endif
169196
}
170197

171198

@@ -223,13 +250,34 @@ - (void) testRemoteLogLevels {
223250
if(error){
224251
NSLog(@"%@", error.localizedDescription);
225252
}
226-
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
253+
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];
254+
255+
NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
256+
options:0
257+
error:&error];
258+
259+
if (error) {
260+
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
261+
XCTAssertNil(error, @"Error creating log payload");
262+
return;
263+
}
264+
265+
error = nil;
266+
// New version of the line
267+
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
268+
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
269+
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
270+
227271
NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
228-
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData
272+
273+
NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
229274
options:0
230-
error:nil];
275+
error:&error];
231276
NSLog(@"decode=%@", decode);
232277

278+
NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
279+
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];
280+
233281
NSArray * expectedValues = @[
234282
@{@"message": @"Info Log..."},
235283
@{@"message": @"Error Log..."},
@@ -244,12 +292,11 @@ - (void) testRemoteLogLevels {
244292
// For each expected message.
245293
for (NSDictionary *dict in expectedValues) {
246294
// Iterate through the collected message logs.
247-
for (NSDictionary *dict2 in decode) {
295+
for (NSDictionary *dict2 in decodedArray) {
248296
//
249297
NSString* currentMessage = [dict objectForKey:@"message"];
250298
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
251299
foundCount += 1;
252-
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
253300
}
254301
// Verify added attributes with logAttributes.
255302
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
@@ -314,13 +361,34 @@ - (void) testLocalLogLevels {
314361
if(error){
315362
NSLog(@"%@", error.localizedDescription);
316363
}
317-
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
364+
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];
365+
366+
NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
367+
options:0
368+
error:&error];
369+
370+
if (error) {
371+
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
372+
XCTAssertNil(error, @"Error creating log payload");
373+
return;
374+
}
375+
376+
error = nil;
377+
// New version of the line
378+
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
379+
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
380+
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
381+
318382
NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
319-
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData
383+
384+
NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
320385
options:0
321-
error:nil];
386+
error:&error];
322387
NSLog(@"decode=%@", decode);
323388

389+
NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
390+
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];
391+
324392
NSArray * expectedValues = @[
325393
@{@"message": @"Info Log..."},
326394
@{@"message": @"Error Log..."},
@@ -335,12 +403,11 @@ - (void) testLocalLogLevels {
335403
// For each expected message.
336404
for (NSDictionary *dict in expectedValues) {
337405
// Iterate through the collected message logs.
338-
for (NSDictionary *dict2 in decode) {
406+
for (NSDictionary *dict2 in decodedArray) {
339407
//
340408
NSString* currentMessage = [dict objectForKey:@"message"];
341409
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
342410
foundCount += 1;
343-
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
344411
}
345412
// Verify added attributes with logAttributes.
346413
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
@@ -400,13 +467,35 @@ - (void) testAutoCollectedLogs {
400467
if(error){
401468
NSLog(@"%@", error.localizedDescription);
402469
}
403-
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
470+
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];
471+
472+
NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
473+
options:0
474+
error:&error];
475+
476+
if (error) {
477+
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
478+
XCTAssertNil(error, @"Error creating log payload");
479+
return;
480+
}
481+
482+
error = nil;
483+
// New version of the line
484+
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
485+
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
486+
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
487+
404488
NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
405-
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData
489+
490+
NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
406491
options:0
407-
error:nil];
492+
error:&error];
408493
NSLog(@"decode=%@", decode);
409494

495+
NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
496+
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];
497+
498+
410499
NSArray * expectedValues = @[
411500
@{@"message": @"NSLog Test"},
412501
@{@"message": @"This is a default os_log message."},
@@ -419,12 +508,11 @@ - (void) testAutoCollectedLogs {
419508
// For each expected message.
420509
for (NSDictionary *dict in expectedValues) {
421510
// Iterate through the collected message logs.
422-
for (NSDictionary *dict2 in decode) {
511+
for (NSDictionary *dict2 in decodedArray) {
423512
//
424513
NSString* currentMessage = [dict objectForKey:@"message"];
425514
if ([[dict2 objectForKey:@"message"] containsString: currentMessage]) {
426515
foundCount += 1;
427-
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
428516
}
429517
// Verify added attributes with logAttributes.
430518
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {

0 commit comments

Comments
 (0)