Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nr 331577: Log common block #337

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 42 additions & 16 deletions Agent/Utilities/NRLogger.m
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,14 @@ - (void)addLogMessage:(NSDictionary *)message : (BOOL) agentLogsOn {
});
}

- (NSData*) jsonDictionary:(NSDictionary*)message {
- (NSMutableDictionary*) commonBlockDict {
NSString* NRSessionId = [[[NewRelicAgentInternal sharedInstance] currentSessionId] copy];
NRMAHarvesterConfiguration *configuration = [NRMAHarvestController configuration];

// The following line generates the native platform name which is used as "collector.name" in the log payload.
NSString* nativePlatform = [NewRelicInternalUtils agentName];

// 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.
NSString* platform = [NewRelicInternalUtils stringFromNRMAApplicationPlatform:[NRMAAgentConfiguration connectionInformation].deviceInformation.platform];
NSString* name = [NRMAAgentConfiguration connectionInformation].deviceInformation.platform == NRMAPlatform_Native ? nativePlatform : platform;

Expand All @@ -316,6 +320,20 @@ - (NSData*) jsonDictionary:(NSDictionary*)message {
entityGuid = @"";
}

NSMutableDictionary *commonAttributes = [NSMutableDictionary dictionary];
[commonAttributes setObject:entityGuid forKey:NRLogMessageEntityGuidKey];
if (NRSessionId) [commonAttributes setObject:NRSessionId forKey:NRLogMessageSessionIdKey];
[commonAttributes setObject:NRLogMessageMobileValue forKey:NRLogMessageInstrumentationProviderKey];
if (name) [commonAttributes setObject:name forKey:NRLogMessageInstrumentationNameKey];
[commonAttributes setObject:[NRMAAgentConfiguration connectionInformation].deviceInformation.agentVersion forKey:NRLogMessageInstrumentationVersionKey];
if (nativePlatform) [commonAttributes setObject:nativePlatform forKey:NRLogMessageInstrumentationCollectorKey];
if (nrAppId) [commonAttributes setObject:nrAppId forKey:NRLogMessageAppIdKey];

return commonAttributes;
}

- (NSData*) jsonDictionary:(NSDictionary*)message {

NSMutableDictionary *requiredAttributes = [NSMutableDictionary dictionary];

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

if (NRSessionId) [requiredAttributes setObject:NRSessionId forKey:NRLogMessageSessionIdKey]; // 7
if (nrAppId) [requiredAttributes setObject:nrAppId forKey:NRLogMessageAppIdKey]; // 8
if (entityGuid) [requiredAttributes setObject:entityGuid forKey:NRLogMessageEntityGuidKey]; // 9

[requiredAttributes setObject:NRLogMessageMobileValue forKey:NRLogMessageInstrumentationProviderKey]; // 10
[requiredAttributes setObject:name forKey:NRLogMessageInstrumentationNameKey]; // 11

value = [NRMAAgentConfiguration connectionInformation].deviceInformation.agentVersion;
if (value) [requiredAttributes setObject:value forKey:NRLogMessageInstrumentationVersionKey]; // 12

[requiredAttributes setObject:nativePlatform forKey:NRLogMessageInstrumentationCollectorKey]; // 13


NSMutableDictionary *providedAttributes = [message mutableCopy];
[providedAttributes removeObjectsForKeys:@[NRLogMessageLevelKey,NRLogMessageFileKey,NRLogMessageLineNumberKey,NRLogMessageMethodKey,NRLogMessageTimestampKey,NRLogMessageMessageKey]];
[providedAttributes addEntriesFromDictionary:requiredAttributes];
Expand Down Expand Up @@ -531,9 +536,30 @@ - (void)enqueueLogUpload {
return;
}

NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
// the text of the file contents is just comma separated dict objects
// Add the user provided attributes to the message.
NSMutableDictionary *commonBlock = [self commonBlockDict];

NSError* error = nil;

NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
options:0
error:&error];

if (error) {
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
}

// New version of the line
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

// Old version of the line
// NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];

// We clear the log when we save the existing logs to uploadQueue.
[self clearLog];

Expand Down
162 changes: 125 additions & 37 deletions Tests/Unit-Tests/NewRelicAgentTests/Uncategorized/NRLoggerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
#import "NRAutoLogCollector.h"
#import <os/log.h>

@interface NRLogger()
+ (NRLogger *)logger;
- (NSMutableDictionary*) commonBlockDict;
@end

@implementation NRLoggerTests
- (void) setUp
{
Expand Down Expand Up @@ -69,8 +74,6 @@ - (void) setUp
weakSelf.fileDescriptor = 0;
}
});


}
- (void) tearDown
{
Expand Down Expand Up @@ -108,20 +111,40 @@ - (void) testNRLogger {

sleep(5);

NSError* error;
NSError* error = nil;
NSData* logData = [NRLogger logFileData:&error];
if(error){
NSLog(@"%@", error.localizedDescription);
}

NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];

NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
options:0
error:&error];

if (error) {
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
XCTAssertNil(error, @"Error creating log payload");
return;
}

error = nil;
// New version of the line
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];

NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData
NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
options:0
error:nil];
error:&error];
NSLog(@"decode=%@", decode);

NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];

NSArray * expectedValues = @[
@{@"message": @"Info Log..."},
@{@"message": @"Error Log..."},
Expand All @@ -131,31 +154,19 @@ - (void) testNRLogger {
@{@"message": @"Debug Log..."},
@{@"message": @"This is a test message for the New Relic logging system."},
];

// check for existence of 6 logs.
int foundCount = 0;
// For each expected message.
for (NSDictionary *dict in expectedValues) {
// Iterate through the collected message logs.
for (NSDictionary *dict2 in decode) {
for (NSDictionary *dict2 in decodedArray) {
//
NSString* currentMessage = [dict objectForKey:@"message"];

// Check the logs entries
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
foundCount += 1;
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationProviderKey] isEqualToString:NRLogMessageMobileValue],@"instrumentation provider set incorrectly");
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationVersionKey] isEqualToString:@"DEV"],@"instrumentation name set incorrectly");

#if TARGET_OS_WATCH
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"watchOSAgent"],@"instrumentation name set incorrectly");
#else
if ([[[UIDevice currentDevice] systemName] isEqualToString:@"tvOS"]) {
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"tvOSAgent"],@"instrumentation name set incorrectly");

}
else {
XCTAssertTrue([[dict2 objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"iOSAgent"],@"instrumentation name set incorrectly");
}
#endif
}
// Verify added attributes with logAttributes.
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
Expand All @@ -166,6 +177,22 @@ - (void) testNRLogger {
}

XCTAssertEqual(foundCount, 7, @"Seven messages should be found.");

// Verify Common Block
XCTAssertTrue([[decodedCommonBlock objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationProviderKey] isEqualToString:NRLogMessageMobileValue],@"instrumentation provider set incorrectly");
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationVersionKey] isEqualToString:@"DEV"],@"instrumentation name set incorrectly");

#if TARGET_OS_WATCH
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"watchOSAgent"],@"instrumentation name set incorrectly");
#else
if ([[[UIDevice currentDevice] systemName] isEqualToString:@"tvOS"]) {
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"tvOSAgent"],@"instrumentation name set incorrectly");
}
else {
XCTAssertTrue([[decodedCommonBlock objectForKey:NRLogMessageInstrumentationNameKey] isEqualToString:@"iOSAgent"],@"instrumentation name set incorrectly");
}
#endif
}


Expand Down Expand Up @@ -223,13 +250,34 @@ - (void) testRemoteLogLevels {
if(error){
NSLog(@"%@", error.localizedDescription);
}
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];

NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
options:0
error:&error];

if (error) {
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
XCTAssertNil(error, @"Error creating log payload");
return;
}

error = nil;
// New version of the line
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData

NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
options:0
error:nil];
error:&error];
NSLog(@"decode=%@", decode);

NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];

NSArray * expectedValues = @[
@{@"message": @"Info Log..."},
@{@"message": @"Error Log..."},
Expand All @@ -244,12 +292,11 @@ - (void) testRemoteLogLevels {
// For each expected message.
for (NSDictionary *dict in expectedValues) {
// Iterate through the collected message logs.
for (NSDictionary *dict2 in decode) {
for (NSDictionary *dict2 in decodedArray) {
//
NSString* currentMessage = [dict objectForKey:@"message"];
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
foundCount += 1;
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
}
// Verify added attributes with logAttributes.
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
Expand Down Expand Up @@ -314,13 +361,34 @@ - (void) testLocalLogLevels {
if(error){
NSLog(@"%@", error.localizedDescription);
}
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];

NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
options:0
error:&error];

if (error) {
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
XCTAssertNil(error, @"Error creating log payload");
return;
}

error = nil;
// New version of the line
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData

NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
options:0
error:nil];
error:&error];
NSLog(@"decode=%@", decode);

NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];

NSArray * expectedValues = @[
@{@"message": @"Info Log..."},
@{@"message": @"Error Log..."},
Expand All @@ -335,12 +403,11 @@ - (void) testLocalLogLevels {
// For each expected message.
for (NSDictionary *dict in expectedValues) {
// Iterate through the collected message logs.
for (NSDictionary *dict2 in decode) {
for (NSDictionary *dict2 in decodedArray) {
//
NSString* currentMessage = [dict objectForKey:@"message"];
if ([[dict2 objectForKey:@"message"] isEqualToString: currentMessage]) {
foundCount += 1;
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
}
// Verify added attributes with logAttributes.
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
Expand Down Expand Up @@ -400,13 +467,35 @@ - (void) testAutoCollectedLogs {
if(error){
NSLog(@"%@", error.localizedDescription);
}
NSString* logMessagesJson = [NSString stringWithFormat:@"[ %@ ]", [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];
NSMutableDictionary *commonBlock = [[NRLogger logger] commonBlockDict];

NSData *json = [NRMAJSON dataWithJSONObject:commonBlock
options:0
error:&error];

if (error) {
NRLOG_AGENT_ERROR(@"Failed to create log payload w error = %@", error);
XCTAssertNil(error, @"Error creating log payload");
return;
}

error = nil;
// New version of the line
NSString* logMessagesJson = [NSString stringWithFormat:@"[{ \"common\": { \"attributes\": %@}, \"logs\": [ %@ ] }]",
[[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding],
[[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding]];

NSData* formattedData = [logMessagesJson dataUsingEncoding:NSUTF8StringEncoding];
NSArray* decode = [NSJSONSerialization JSONObjectWithData:formattedData

NSDictionary* decode = [NSJSONSerialization JSONObjectWithData:formattedData
options:0
error:nil];
error:&error];
NSLog(@"decode=%@", decode);

NSArray *decodedArray = [[decode valueForKey:@"logs"] objectAtIndex:0];
NSDictionary *decodedCommonBlock = [[[decode valueForKey:@"common"] objectAtIndex:0] valueForKey:@"attributes"];


NSArray * expectedValues = @[
@{@"message": @"NSLog Test"},
@{@"message": @"This is a default os_log message."},
Expand All @@ -419,12 +508,11 @@ - (void) testAutoCollectedLogs {
// For each expected message.
for (NSDictionary *dict in expectedValues) {
// Iterate through the collected message logs.
for (NSDictionary *dict2 in decode) {
for (NSDictionary *dict2 in decodedArray) {
//
NSString* currentMessage = [dict objectForKey:@"message"];
if ([[dict2 objectForKey:@"message"] containsString: currentMessage]) {
foundCount += 1;
XCTAssertTrue([[dict2 objectForKey:@"entity.guid"] isEqualToString:@"Entity-Guid-XXXX"],@"entity.guid set incorrectly");
}
// Verify added attributes with logAttributes.
if ([[dict2 objectForKey:@"message"] isEqualToString:@"This is a test message for the New Relic logging system."]) {
Expand Down
Loading