Skip to content
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
26 changes: 25 additions & 1 deletion azure/activity_logs_monitoring/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,38 @@ class EventhubLogHandler {
this.records.push(originalRecord);
}
} else {
this.records.push(originalRecord);
this.records.push(this.fixPropertiesJsonString(originalRecord));
}
} else {
record = this.addTagsToStringLog(record);
this.records.push(record);
}
}

fixPropertiesJsonString(record) {
try {
// Check if properties field is a string
if (typeof record.properties === 'string') {
// If it is a string, check if it is a malformed JSON String
// By checking for ':'
if (record.properties.includes("':'")) {
// If the check is true, find / replace single quotes
// with double quotes, to make a proper JSON
// which is then converted into a JSON Object
record.properties = JSON.parse(record.properties.replace(/'/g, '"'));
return record;
}else {
return record;
}
} else {
return record;
}
} catch {
this.context.error('Unable to fix properties field to JSON Object');
return record;
}
}
Comment on lines 392 to 408
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fixPropertiesJsonString(record) {
try {
// Check if properties field is a string
if (typeof record.properties === 'string') {
// If it is a string, check if it is a malformed JSON String
// By checking for ':'
if (record.properties.includes("':'")) {
// If the check is true, find / replace single quotes
// with double quotes, to make a proper JSON
// which is then converted into a JSON Object
record.properties = JSON.parse(record.properties.replace(/'/g, '"'));
return record;
}else {
return record;
}
} else {
return record;
}
} catch {
this.context.error('Unable to fix properties field to JSON Object');
return record;
}
}
fixPropertiesJsonString(record) {
// Check if properties field is a malformed JSON String
if (Object.hasOwn(record, 'properties') && (typeof record.properties === 'string') && (record.properties.includes("':'"))) {
try {
// If the check is true, find and replace single quotes
// with double quotes, to make a proper JSON
// which is then converted into a JSON Object
parsedProperties = JSON.parse(record.properties.replace(/'/g, '"'));
record.properties = parsedProperties;
} catch {
this.context.error('Unable to fix properties field to JSON Object');
}
return record;
}

This function has a lot of return paths that all seem to do the same thing. This could be simplified a bit to have a single return and combine our checks into a single statement to verify whether or not record.properties has one of these malformed objects.

We'll need to do a little verification on our end to make this work with live data and double check the behavior of nested message and level fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattsp1290 I went ahead and took the changes that you've recommended. I added a couple of return clauses that ensures:

  • When the if statement fails, we should return the record as is
  • If the conversion fails, we should return the record as is
    fixPropertiesJsonString(record) {
        // Check if properties field is a malformed JSON String
        if (Object.hasOwn(record, 'properties') && (typeof record.properties === 'string') && (record.properties.includes("':'"))) {
            try {
                // If the check is true, find and replace single quotes
                // with double quotes, to make a proper JSON
                // which is then converted into a JSON Object
                record.properties = JSON.parse(record.properties.replace(/'/g, '"'));
                return record;
            } catch {
                this.context.error('Unable to fix properties field to JSON Object');
                return record;
            }
        } else {
            return record;
        }
    }

I have also added a couple of additional test cases, that will test nested objects.


handleLogs(logs) {
let logsType = this.getLogFormat(logs);
switch (logsType) {
Expand Down
34 changes: 34 additions & 0 deletions azure/test/activity_logs_monitoring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -818,3 +818,37 @@ describe('Log Splitting', function() {
});
});
});
describe('EventhubLogHandler Fix Properties Json String', function() {

beforeEach(function() {
this.forwarder = setUp();
});

it('parses properties string with single quotes into object', function() {
const record = { properties: "{'key':'value'}" };
const result = this.forwarder.fixPropertiesJsonString(record);
assert.equal(
'object',
typeof result.properties
)
});

it("leaves properties string unchanged when it doesn't match the malformed pattern", function() {
const record = { properties: 'some plain string without colons' };
const result = this.forwarder.fixPropertiesJsonString(record);
assert.equal(
'string',
typeof result.properties
)
});

it('logs an error and returns original record when replacement results in invalid JSON', function() {
// includes the "':'" marker so the function attempts replacement, but JSON remains invalid
const badRecord = { properties: "Look i know i shouldn't but, i will do this ':' " };
const result = this.forwarder.fixPropertiesJsonString(badRecord);
assert.equal(
'string',
typeof result.properties
)
});
});