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

Adding site creation among activities to log and store for future reference #3946

Merged
merged 2 commits into from
Nov 28, 2024

Conversation

Baalmart
Copy link
Contributor

@Baalmart Baalmart commented Nov 28, 2024

Description

I am just adding site creation among activities to retrieve and know who created the Site

Changes Made

  • adding site creation among activities to retrieve

Testing

  • Tested locally
  • Tested against staging environment
  • Relevant tests passed: [List test names]

Affected Services

  • Which services were modified:
    • Device Registry

Endpoints Ready for Testing

  • New endpoints ready for testing:
    • Create Site
    • Get Site Activities

API Documentation Updated?

  • Yes, API documentation was updated
  • No, API documentation does not need updating

Additional Notes

I am just adding site creation among activities to retrieve and know who created the Site

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a device_id field in activity logging to associate activities with specific devices.
    • Enhanced site creation functionality to log detailed activity records.
  • Bug Fixes

    • Improved error handling in various utility methods to ensure better logging and response management.
  • Refactor

    • Updated import paths for the ActivityModel to streamline activity-related operations across the application.
  • Documentation

    • Enhanced clarity in error messages for better debugging and monitoring.

Copy link
Contributor

coderabbitai bot commented Nov 28, 2024

Caution

Review failed

The pull request is closed.

📝 Walkthrough
📝 Walkthrough

Walkthrough

The changes in this pull request primarily focus on enhancing the Activity model within the device registry. A new field, device_id, has been added to the activitySchema to link activities with specific devices. Additionally, several import statements have been updated to reference the Activity model instead of the SiteActivity model. The create-site.js file has been modified to include activity logging during site creation, and improvements have been made to error handling in various utility functions.

Changes

File Path Change Summary
src/device-registry/models/Activity.js Added field device_id: { type: ObjectId } to activitySchema.
src/device-registry/models/test/ut_activity.js Updated import statement from @models/SiteActivity to @models/Activity.
src/device-registry/utils/create-activity.js Updated import statement from @models/SiteActivity to @models/Activity.
src/device-registry/utils/create-site.js Modified create method to accept additional parameters and log activity upon site creation.
src/device-registry/utils/generate-filter.js Updated activities method to process activity_tags as an array; enhanced error handling in multiple methods.

Possibly related PRs

Suggested reviewers

  • Codebmk
  • BenjaminSsempala
  • OchiengPaul442

🎉 In the realm of code, where changes unfold,
A new device_id in Activity we behold.
With logging enhanced, and errors refined,
Our schema grows richer, with features aligned.
So here's to the builders, with passion and might,
Crafting the future, making code bright! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Nov 28, 2024

Codecov Report

Attention: Patch coverage is 25.00000% with 9 lines in your changes missing coverage. Please review.

Project coverage is 11.73%. Comparing base (c8e68e3) to head (f5218e1).
Report is 10 commits behind head on staging.

Files with missing lines Patch % Lines
src/device-registry/utils/create-site.js 18.18% 9 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           staging    #3946   +/-   ##
========================================
  Coverage    11.73%   11.73%           
========================================
  Files          114      114           
  Lines        15318    15326    +8     
  Branches       318      318           
========================================
+ Hits          1797     1799    +2     
- Misses       13521    13527    +6     
Files with missing lines Coverage Δ
src/device-registry/models/Activity.js 18.47% <ø> (ø)
src/device-registry/utils/create-activity.js 9.13% <100.00%> (ø)
src/device-registry/utils/create-site.js 5.03% <18.18%> (+0.35%) ⬆️

Copy link
Contributor

Device registry changes in this PR available for preview here

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (10)
src/device-registry/models/Activity.js (3)

34-34: Consider adding constraints to the device_id field

While adding the device_id field is a good addition for tracking device-related activities, consider whether this field should have additional constraints:

  • Should it be required for certain activity types?
  • Should it have a reference to the actual device collection?
-    device_id: { type: ObjectId },
+    device_id: { 
+      type: ObjectId,
+      ref: 'devices',
+      required: function() {
+        return ['device_creation', 'device_update', 'device_maintenance'].includes(this.activityType);
+      }
+    },

Line range hint 67-86: Add device_id to toJSON method

The new device_id field is not included in the toJSON method, which means it won't be visible in API responses.

   toJSON() {
     return {
       _id: this._id,
       device: this.device,
+      device_id: this.device_id,
       network: this.network,
       group: this.group,

Line range hint 236-248: Update remove method projection to include device_id

The remove method's projection should include the new device_id field to maintain consistency with the schema update.

   let options = {
     projection: {
       _id: 1,
       device: 1,
+      device_id: 1,
       site_id: 1,
       host_id: 1,
       user_id: 1,
src/device-registry/utils/create-activity.js (4)

Line range hint 71-308: Consider refactoring the deploy function for better maintainability

The deploy function is handling multiple responsibilities and contains deeply nested conditionals. Consider breaking it down into smaller, focused functions:

  1. Device validation
  2. Site validation
  3. Activity creation
  4. Device update
  5. Kafka notification

Here's a suggested approach for the initial validation:

+ async function validateDeploymentPrerequisites(tenant, deviceName, site_id) {
+   const [deviceExists, siteExists] = await Promise.all([
+     DeviceModel(tenant).exists({ name: deviceName }),
+     SiteModel(tenant).exists({ _id: ObjectId(site_id) })
+   ]);
+
+   if (!deviceExists || !siteExists) {
+     return {
+       success: false,
+       message: "Device or Site not found",
+       status: httpStatus.BAD_REQUEST,
+       errors: {
+         message: `Invalid request, Device ${deviceName} or Site ${site_id} not found`
+       }
+     };
+   }
+   return { success: true };
+ }

  deploy: async (request, next) => {
    try {
      const { body, query } = request;
      const { tenant, deviceName } = query;
      const { site_id } = body;

+     const validationResult = await validateDeploymentPrerequisites(tenant, deviceName, site_id);
+     if (!validationResult.success) {
+       return validationResult;
+     }

Line range hint 309-324: Enhance error handling with more descriptive messages

The error handling pattern is consistent but could be more informative. Consider:

  1. Adding error codes for better error tracking
  2. Including more context in error messages
  3. Implementing error recovery strategies where applicable
 } catch (error) {
   logger.error(`🐛🐛 Internal Server Error ${error.message}`);
+  const errorCode = 'DEPLOY_ERROR_001';
+  const errorContext = {
+    operation: 'device_deployment',
+    deviceName,
+    site_id,
+    error: error.message
+  };
   next(
     new HttpError(
       "Internal Server Error",
       httpStatus.INTERNAL_SERVER_ERROR,
-      { message: error.message }
+      { 
+        message: error.message,
+        code: errorCode,
+        context: errorContext
+      }
     )
   );
 }

Line range hint 271-291: Improve Kafka integration reliability

The current Kafka integration could be enhanced for better reliability and maintainability:

  1. Extract Kafka producer configuration to a shared utility
  2. Add retry mechanism for failed messages
  3. Implement proper error recovery
+ const MAX_RETRIES = 3;
+ const RETRY_DELAY = 1000; // ms
+
+ async function publishToKafka(topic, message, retries = MAX_RETRIES) {
+   const producer = kafka.producer({
+     groupId: constants.UNIQUE_PRODUCER_GROUP,
+   });
+   try {
+     await producer.connect();
+     await producer.send({
+       topic,
+       messages: [message],
+     });
+   } catch (error) {
+     if (retries > 0) {
+       await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
+       return publishToKafka(topic, message, retries - 1);
+     }
+     throw error;
+   } finally {
+     await producer.disconnect();
+   }
+ }

- try {
-   const kafkaProducer = kafka.producer({
-     groupId: constants.UNIQUE_PRODUCER_GROUP,
-   });
-   await kafkaProducer.connect();
-   await kafkaProducer.send({
-     topic: "activities-topic",
-     messages: [
-       {
-         action: "create",
-         value: JSON.stringify(data),
-       },
-     ],
-   });
-   await kafkaProducer.disconnect();
- } catch (error) {
-   logger.error(`internal server error -- ${error.message}`);
- }
+ try {
+   await publishToKafka("activities-topic", {
+     action: "create",
+     value: JSON.stringify(data),
+   });
+ } catch (error) {
+   logger.error(`Failed to publish to Kafka: ${error.message}`);
+   // Consider implementing a dead letter queue or alternative notification mechanism
+ }

Line range hint 644-744: Enhance batch deployment with better control and monitoring

The batch deployment implementation could benefit from:

  1. Controlled concurrency to prevent overwhelming the system
  2. Transaction handling for atomic operations
  3. Progress tracking for long-running deployments
+ const BATCH_SIZE = 5; // Process 5 deployments at a time
+ 
+ async function processBatch(deployments, tenant, next) {
+   const results = {
+     successful: [],
+     failed: [],
+     existing: []
+   };
+   
+   for (let i = 0; i < deployments.length; i += BATCH_SIZE) {
+     const batch = deployments.slice(i, i + BATCH_SIZE);
+     const batchPromises = batch.map(deployment => 
+       processDeployment(deployment, tenant, next)
+         .then(result => {
+           if (result.existing) results.existing.push(result.data);
+           else if (result.success) results.successful.push(result.data);
+           else results.failed.push(result.data);
+         })
+     );
+     await Promise.all(batchPromises);
+     
+     // Report progress
+     const progress = Math.min(100, (i + BATCH_SIZE) / deployments.length * 100);
+     logger.info(`Batch deployment progress: ${progress.toFixed(1)}%`);
+   }
+   
+   return results;
+ }

  batchDeployWithCoordinates: async (request, next) => {
    try {
      const { body, query } = request;
      const { tenant } = query;

-     const successful_deployments = [];
-     const failed_deployments = [];
-     const existing_sites = [];
-     
-     const deploymentPromises = body.map(async (deployment) => {
+     const results = await processBatch(body, tenant, next);
src/device-registry/utils/generate-filter.js (1)

1562-1564: LGTM! Consider adding input validation.

The change improves the handling of activity tags by properly converting the comma-separated string into an array for MongoDB's $in operator. This enhancement aligns well with the PR's objective of improving activity logging.

Consider adding input validation to handle edge cases:

 if (activity_tags) {
+  // Ensure activity_tags is a string and trim whitespace
+  const tagsString = activity_tags.toString().trim();
+  if (tagsString) {
-    const activityTagsArray = activity_tags.toString().split(",");
+    const activityTagsArray = tagsString.split(",").map(tag => tag.trim()).filter(Boolean);
     filter["tags"] = {};
     filter["tags"]["$in"] = activityTagsArray;
+  }
 }

This refinement:

  • Trims whitespace from the input string
  • Trims individual tags
  • Filters out empty tags
  • Guards against empty input
src/device-registry/utils/create-site.js (2)

404-417: Conditional Property Inclusion Might Skip Valid Values

Using the && operator may omit properties with falsy values like 0 or empty strings. To include all non-null values, consider checking for null or undefined instead.

Apply this change to ensure properties with valid falsy values are included:

 const siteActivityBody = {
   date: new Date(),
   description: "site created",
   activityType: "site-creation",
   site_id: createdSite._id,
-  ...(network && { network }),
-  ...(userName && { userName }),
-  ...(lastName && { lastName }),
-  ...(firstName && { firstName }),
-  ...(user_id && { user_id }),
-  ...(group && { group }),
+  ...(network != null && { network }),
+  ...(userName != null && { userName }),
+  ...(lastName != null && { lastName }),
+  ...(firstName != null && { firstName }),
+  ...(user_id != null && { user_id }),
+  ...(group != null && { group }),
 };

430-431: Consider Removing Emojis from Error Logs for Clarity

Including emojis like 🐛🐛 in error logs might reduce readability and clutter log files. Consider removing them to maintain professional and clear logging.

Also applies to: 450-450

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 34ba34d and f5218e1.

📒 Files selected for processing (5)
  • src/device-registry/models/Activity.js (1 hunks)
  • src/device-registry/models/test/ut_activity.js (1 hunks)
  • src/device-registry/utils/create-activity.js (1 hunks)
  • src/device-registry/utils/create-site.js (5 hunks)
  • src/device-registry/utils/generate-filter.js (1 hunks)
🔇 Additional comments (8)
src/device-registry/models/test/ut_activity.js (2)

6-6: LGTM! Import path updated correctly.

The import path change from @models/SiteActivity to @models/Activity aligns with the model restructuring mentioned in the PR.


Line range hint 1-70: Essential test coverage is missing for new features.

While the test structure is well-organized, several critical test cases are missing:

  1. No tests for the new device_id field that was added to the schema
  2. No tests for site creation activities, which is the main focus of this PR
  3. Empty test sections for instance methods, static methods, and CRUD operations

Consider adding these essential test cases:

 describe("Schema Definition", () => {
   // ... existing tests ...
+
+  it("Should have the 'device_id' field", () => {
+    const deviceIdField = Activity.schema.obj.device_id;
+    expect(deviceIdField).to.exist;
+    expect(deviceIdField.type).to.equal(String);
+  });
+
+  it("Should validate site creation activity type", () => {
+    const activity = new Activity({
+      email: "[email protected]",
+      activity_type: "site_creation",
+      device_id: "device123",
+      description: "Created new site"
+    });
+    expect(activity.validateSync()).to.be.undefined;
+  });
 });

 describe("Static Methods", () => {
-  // Add your static method tests here
+  describe("createSiteActivity", () => {
+    it("Should create a new site activity record", async () => {
+      const activityData = {
+        email: "[email protected]",
+        activity_type: "site_creation",
+        device_id: "device123",
+        description: "Created new site"
+      };
+      const activity = await Activity.createSiteActivity(activityData);
+      expect(activity).to.have.property('_id');
+      expect(activity.activity_type).to.equal("site_creation");
+    });
+  });
 });

Let's verify if there are any other activity-related test files that might need similar updates:

src/device-registry/models/Activity.js (2)

Line range hint 284-297: LGTM: Model creation logic is robust

The tenant-based model creation logic is well-implemented and handles the singleton pattern correctly. No changes needed here.


Line range hint 47-51: Verify activity codes for site creation

Let's ensure that the activity_codes array supports site creation tracking as per the PR objectives.

✅ Verification successful

Let me gather more information about activity types and their usage.


Activity codes schema supports site creation tracking

The verification confirms that the schema changes align with the PR objectives. Evidence found:

  • activityType: "site-creation" is used in src/device-registry/utils/create-site.js
  • Supporting constants and projections exist for site activities:
    • SITE_ACTIVITIES_INCLUSION_PROJECTION
    • SITE_ACTIVITIES_EXCLUSION_PROJECTION

The activity_codes array in the schema is appropriately structured to accommodate site creation tracking activities.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for activity type constants and verify site creation is included
rg -A 5 "ACTIVITY_TYPE|ACTIVITY_CODES" src/device-registry/config/

# Search for site creation related activities in existing data
ast-grep --pattern 'activityType: { $$ "site" $$ }'

Length of output: 692


Script:

#!/bin/bash
# Search for activity type definitions or usage in the codebase
rg -g '!*.test.*' -g '!*.spec.*' "activityType.*site" -B 2 -A 2

# Look for site-related constants or enums
rg -g '!*.test.*' -g '!*.spec.*' "SITE_" -B 2 -A 2 src/device-registry/

# Check for any site activity related code
ast-grep --pattern 'const $$ = { $$ site $$ }'

Length of output: 4318

src/device-registry/utils/create-activity.js (1)

1-1: Verify the impact of Activity model migration

The change from SiteActivity to Activity model suggests a consolidation of activity tracking. Let's ensure this change maintains backward compatibility.

✅ Verification successful

Activity model change is safe and maintains compatibility

The change from SiteActivity to Activity model is a safe refactoring that maintains backward compatibility. The Activity model schema includes all necessary site-related fields (site_id, network, etc.) and the codebase consistently uses the new model name. The schema also includes comprehensive activity tracking capabilities with proper validation and error handling.

Key evidence:

  • Activity schema includes site-specific fields: site_id, network, group
  • Model maintains existing functionality through register, list, modify, and remove methods
  • Constants reference SITE_ACTIVITIES_INCLUSION_PROJECTION showing site activity support
  • Logger name includes "site-activities-model" indicating maintained site functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining references to SiteActivity model
rg -l "SiteActivity" --type js

# Check if the Activity model includes all fields from SiteActivity
ast-grep --pattern 'const $schema = new Schema({$$$})' 

Length of output: 87


Script:

#!/bin/bash
# Let's try a broader search for model definitions and activity-related files

# Search for Activity model definition
rg -l "Activity.*Model" --type js

# Search for schema definitions related to activities
rg -A 10 "new Schema\(" --type js

# Look for files that might contain activity-related code
fd -e js -E node_modules | rg -l "activity|Activity"

# Check imports in the device registry directory
fd -e js . src/device-registry | xargs rg "require.*Activity"

Length of output: 74106


Script:

#!/bin/bash
# Let's check the Activity model schema and its usage
rg -A 10 "const activitySchema = new Schema" src/device-registry/models/Activity.js

# Check if there are any references to SiteActivity in git history
git log -p | rg "SiteActivity"

# Look for activity-related function implementations
ast-grep --pattern 'function $FUNC_NAME($$$) {
  $$$
  ActivityModel.$$$
  $$$
}'

# Check test files for activity-related tests
rg -A 5 "describe.*Activity" src/device-registry/models/test/ut_activity.js

Length of output: 723


Script:

#!/bin/bash
# Let's examine the Activity model's full schema and any site-related fields
cat src/device-registry/models/Activity.js

# Check for any activity creation functions and their usage
rg -A 10 "createActivity" src/device-registry/utils/create-activity.js

# Look for any site-related fields or methods in activity files
rg -l "site" src/device-registry/models/Activity.js src/device-registry/utils/create-activity.js

# Check test cases for activity creation
rg -A 10 "test.*create.*activity" src/device-registry/models/test/ut_activity.js

Length of output: 9591

src/device-registry/utils/create-site.js (3)

2-2: Appropriate Import of ActivityModel for Activity Logging

Importing ActivityModel is necessary for logging activities related to site creation.


19-19: Importing stringify Utility for Enhanced Logging

Including the stringify utility enhances the logging functionality by allowing structured data to be logged effectively.


324-335: Destructuring Additional User Information from Request Body

Extracting user-related parameters from body improves the detail of activity logs. Ensure that any required fields are validated before use.

Comment on lines 423 to 427
logger.error(
`Unable to Store the Site Activity for this operation ${stringify(
siteActivityBody
)} `
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid Logging Sensitive User Information

When logging errors, avoid including potentially sensitive user data like user_id or userName to protect user privacy.

Consider revising the log statement:

 logger.error(
-  `Unable to Store the Site Activity for this operation ${stringify(
-    siteActivityBody
-  )} `
+  "Unable to store the site activity for this operation."
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logger.error(
`Unable to Store the Site Activity for this operation ${stringify(
siteActivityBody
)} `
);
logger.error(
"Unable to store the site activity for this operation."
);

@Baalmart Baalmart merged commit 49e2a1f into staging Nov 28, 2024
31 checks passed
@Baalmart Baalmart deleted the en-site-creation branch November 28, 2024 13:44
@Baalmart Baalmart mentioned this pull request Nov 28, 2024
1 task
Copy link
Contributor

Device registry changes in this PR available for preview here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant