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

Repo sync #35560

Merged
merged 4 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
---
title: Handling cross-cutting concerns
shortTitle: Cross-cutting concerns
intro: '{% data variables.product.prodname_copilot_chat_short %} can help you avoid code that relates to a concern other than the core concern of the method or function in which the code is located.'
versions:
feature: copilot
category:
- 'Refactoring code'
complexity:
- Intermediate
octicon: rocket
topics:
- Copilot
---

Cross-cutting concerns are aspects of a program that affect multiple parts of the system, such as logging, security, data validation, and error handling. They can become scattered throughout a codebase, leading to code duplication and maintenance challenges.

{% data variables.product.prodname_copilot_chat_short %} can help refactor cross-cutting concerns by suggesting the implementation of Aspect-Oriented Programming (AOP) practices or using decorators and middleware patterns to centralize these concerns in a modular, maintainable way.

## Example scenario

Imagine you have a Python project that contains multiple service files in which logging occurs. The information that gets logged is defined within each of the individual service files. If the application is modified or extended in future, this design could lead to inconsistency in the content and style of log entries. You can consolidate and centralize the logging behavior to avoid this being distributed across your project.

Here are three files from our example project: the entry point file (`main.py`), the log message configuration file (`logging_config.py`), and one of the service files (`order_service.py`). The example service file shows how log information is defined alongside the business logic for a particular part of the application.

### main.py

```python
import logging
from logging_config import setup_logging
from payment_service import PaymentService
from order_service import OrderService
from shipping_service import ShippingService
from inventory_service import InventoryService
from notification_service import NotificationService

def main():
setup_logging()
payment_service = PaymentService()
order_service = OrderService()
shipping_service = ShippingService()
inventory_service = InventoryService()
notification_service = NotificationService()

# Example usage
payment_service.process_payment({"amount": 100, "currency": "USD"})
order_service.place_order({"item": "Book", "quantity": 1})
shipping_service.ship_order({"item": "Book", "quantity": 1})
inventory_service.update_inventory("Book", -1)
notification_service.send_notification("Order has been placed and shipped.")

if __name__ == "__main__":
main()
```

### logging_config.py

```python
import logging

def setup_logging():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
```

### order_service.py

```python
import logging

class OrderService:
def __init__(self):
self.logger = logging.getLogger(__name__)

def place_order(self, order):
self.logger.info("Entering place_order method.")
try:
# In here would be the business logic for placing an order
# ...
self.logger.info("Order placed successfully.")
except Exception as e:
self.logger.error(f"Error in place_order method: {e}")
raise
finally:
self.logger.info("Exiting place_order method.")
```

## Example prompt

Open the project workspace in {% data variables.product.prodname_vscode_shortname %} or {% data variables.product.prodname_vs %} and enter the following prompt in the {% data variables.product.prodname_copilot_chat_short %} view.

`@workspace Refactor this project by using AOP to avoid logging that has cross-cutting concerns`

> [!NOTE]
> The `@workspace` chat participant in {% data variables.product.prodname_vscode_shortname %} and {% data variables.product.prodname_vs %} provides {% data variables.product.prodname_copilot_short %} with context about all of the code in your workspace. You can use `@workspace` when you want {% data variables.product.prodname_copilot_short %} to consider the structure of your project and how different parts of your code interact.

## Example response

{% data variables.product.prodname_copilot_short %} responds as follows.

{% data reusables.copilot.example-prompts.response-is-an-example %}

> To refactor this project using Aspect-Oriented Programming (AOP) to handle logging as a cross-cutting concern, you can use a library like `aspectlib`. Here is how you can do it:
>
> 1. Install `aspectlib`:
>
> `pip install aspectlib`
>
> 1. Create an aspect for logging in a new file called `logging_aspect.py`:
>
> ```python
> import aspectlib
> import logging
>
> @aspectlib.Aspect(bind=True)
> def log_method_call(cutpoint, *args, **kwargs):
> logger = logging.getLogger()
> method_name = cutpoint.__name__
> logger.info(f"Entering method: {method_name}")
> try:
> result = yield aspectlib.Proceed
> logger.info(f"Method {method_name} executed successfully.")
> return result
> except Exception as e:
> logger.error(f"Error in method {method_name}: {e}")
> raise
> finally:
> logger.info(f"Exiting method: {method_name}")
> ```
>
> 1. Apply the aspect to the service methods in `main.py`:
>
> ```python
> import logging
> from logging_config import setup_logging
> from payment_service import PaymentService
> from order_service import OrderService
> from shipping_service import ShippingService
> from inventory_service import InventoryService
> from notification_service import NotificationService
> from logging_aspect import log_method_call
> import aspectlib
>
> def main():
> setup_logging()
>
> # Apply logging aspect to service methods
> aspectlib.weave(PaymentService.process_payment, log_method_call)
> aspectlib.weave(OrderService.place_order, log_method_call)
> aspectlib.weave(ShippingService.ship_order, log_method_call)
> aspectlib.weave(InventoryService.update_inventory, log_method_call)
> aspectlib.weave(NotificationService.send_notification, log_method_call)
>
> payment_service = PaymentService()
> order_service = OrderService()
> shipping_service = ShippingService()
> inventory_service = InventoryService()
> notification_service = NotificationService()
>
> # Example usage
> payment_service.process_payment({"amount": 100, "currency": "USD"})
> order_service.place_order({"item": "Book", "quantity": 1})
> shipping_service.ship_order({"item": "Book", "quantity": 1})
> inventory_service.update_inventory("Book", -1)
> notification_service.send_notification("Order has been placed and shipped.")
>
> if __name__ == "__main__":
> main()
> ```

{% data variables.product.prodname_copilot_short %} then tells you to remove the logging code from all of the service classes, and gives you the code for the revised files. For example, this is the revised version of `order_service.py`:

```python
class OrderService:
def place_order(self, order):
# In here would be the business logic for placing an order
# ...
pass
```

In the refactored version of the project, the same logging operations are performed, but the logging code is centralized in a single file.

## Further reading

{% data reusables.copilot.example-prompts.further-reading-items %}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ children:
- /refactoring-to-implement-a-design-pattern
- /refactoring-data-access-layers
- /decoupling-business-logic-from-ui-components
- /handling-cross-cutting-concerns
- /simplifying-complex-inheritance-hierarchies
- /fixing-database-deadlocks-or-data-integrity-issues
---
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ redirect_from:
> {% data reusables.copilot.signup-procedure-enterprise-msft-ea %}

1. Ensure you are signed in as an enterprise admin on {% data variables.product.github %}.
1. Navigate to the {% data variables.product.prodname_copilot_short %} signup page:
* For **{% data variables.product.prodname_copilot_business_short %}**, go to the [signup page for {% data variables.product.prodname_copilot_business_short %}](https://github.com/github-copilot/business_signup/choose_business_type).
* For **{% data variables.product.prodname_copilot_enterprise_short %}**, go to the [signup page for {% data variables.product.prodname_copilot_enterprise_short %}](https://github.com/github-copilot/enterprise_signup/choose_enterprise).
1. Navigate to the [{% data variables.product.prodname_copilot %} sign up page](https://github.com/github-copilot/purchase).
1. Ensure you are signed in to the right enterprise account. If you are not, click **{% octicon "arrow-switch" aria-hidden="true" %} Switch** and select the enterprise for which you want to purchase {% data variables.product.prodname_copilot %}. You can also append `?enterprise=YOUR-ENTERPRISE` to the URL to pre-select the enterprise.
1. Follow the steps to sign up and enable {% data variables.product.prodname_copilot_short %} for organizations in your enterprise. If you purchased {% data variables.product.prodname_copilot_enterprise_short %}, you will be able to assign either {% data variables.product.prodname_copilot_enterprise_short %} or {% data variables.product.prodname_copilot_business_short %} to each individual organization in the enterprise.

## Next steps
Expand Down
17 changes: 4 additions & 13 deletions data/reusables/copilot/signup-procedure-org.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
1. Go to the [{% data variables.product.prodname_copilot_for_business %} sign up page](https://github.com/github-copilot/business_signup/choose_business_type).
1. Select an organization for which you want to purchase {% data variables.product.prodname_copilot %} and click **Continue**.
1. Follow the steps to confirm your payment details, then click **Save**.

If you don't have a payment method on file, you'll be prompted to add one.

1. In the "Public code suggestions" dropdown, select **Allow** or **Block** to allow or block suggestions that match public code, and click **Save and continue**. You can change these preferences later by returning to your {% data variables.product.prodname_copilot %} settings.
1. Either grant access to {% data variables.product.prodname_copilot %} for all current and future users in your organization, or for specific users in your organization.
* If you selected **Allow for all members**, click **Confirm** in the "Confirm seat assignment" dialog to confirm that you want to enable {% data variables.product.prodname_copilot %} for all current and future users in your organization.
* If you selected **Selected teams/users**, you can choose **Add people** or **Add team**.
* If you selected **Add people**, in the "Enable GitHub Copilot access for selected members of ORGANIZATION" dialog, you can either search for individual members, or you can add members in bulk by uploading a CSV file.
* If you selected **Add team**, in the "Enable GitHub Copilot access for selected teams of ORGANIZATION" dialog, start typing the team name in the search bar, select the team you want to add and click **Add team(s) to access list**.
1. To finish setting up your {% data variables.product.prodname_copilot_for_business %} subscription, click **Save and finish**. Organization members will receive an email with instructions on how to start using {% data variables.product.prodname_copilot %}.
1. Navigate to the [{% data variables.product.prodname_copilot %} sign up page](https://github.com/github-copilot/purchase).
1. Ensure you are signed in to the right organization account. If you are not, click **{% octicon "arrow-switch" aria-hidden="true" %} Switch** and select the organization for which you want to purchase {% data variables.product.prodname_copilot %}.
1. Click **Enable {% data variables.product.prodname_copilot %}**.
1. Enable {% data variables.product.prodname_copilot_short %} for some or all members of your organization. For more information about assigning seats, see "[AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-access-to-github-copilot-in-your-organization/granting-access-to-copilot-for-members-of-your-organization)."
10 changes: 10 additions & 0 deletions src/audit-logs/data/ghec/enterprise.json
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,16 @@
"description": "The ability for enterprise members to update branch protection rules was enabled. Enterprise owners and members can update protected branches.",
"docs_reference_links": "N/A"
},
{
"action": "business.proxy_security_header_enabled",
"description": "The proxy security header was enabled for an enterprise. When the header is provided in requests, only Enterprise Managed Users matching the header will be able to access GitHub.",
"docs_reference_links": "N/A"
},
{
"action": "business.proxy_security_header_unsatisfied",
"description": "A user outside the enterprise tried to access GitHub while the proxy security header was enabled and provided in the request.",
"docs_reference_links": "N/A"
},
{
"action": "business.recovery_code_failed",
"description": "An enterprise owner failed to sign into a enterprise with an external identity provider (IdP) using a recovery code.",
Expand Down
Loading
Loading