Scoped

The scoped modifier in C# restricts the lifetime of a variable, particularly when dealing with ref structs. 

It ensures that the variable's lifetime is limited to the current method and prevents it from being extended beyond that scope. 

This helps in managing the lifetime of ref structs to prevent potential issues like dangling references or unintended lifetime extension.

using System;

public ref struct MyRefStruct
{
    public int Value;
}

public class Program
{
    // Method with scoped ref parameter
    public static void ModifyRefStruct(scoped ref MyRefStruct data)
    {
        // Since data is scoped, it's guaranteed to only exist within this method
        data.Value = 42;
    }

    public static void Main()
    {
        MyRefStruct refStruct = new MyRefStruct();
        refStruct.Value = 10;

        // Call the method with scoped ref parameter
        ModifyRefStruct(scoped refStruct);

        // Access the modified value
        Console.WriteLine("Modified Value: " + refStruct.Value); // Output: 42
    }
}

Refereneces:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations#reference-variables

Array ^

The ^ operator is used for indexing from the end of an array or collection. Specifically, ^1 represents the last element, ^2 represents the second-to-last element, 


  void Display(int[] s) => Console.WriteLine(string.Join(" ", s));
  int[] xs = [0, 0, 0];
Display(xs);

ref int element = ref xs[0];
element = 1;
Display(xs);

element = ref xs[^1];
element = 3;
Display(xs);
// Output:
// 0 0 0
// 1 0 0
// 1 0 3
Refereneces:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations#reference-variables

Reference types vs Value types

Both value types and reference types are used to represent data, but they behave differently in terms of memory allocation, assignment, and passing to methods.

Memory Allocation:
Value Types:
Value types are stored directly in memory where they are declared. They typically reside on the stack. Examples of value types include simple types like int, float, char, and structs.

Reference Types:
Reference types are stored in memory on the heap.
When you declare a reference type variable, the variable itself stores a reference (or memory address) to the actual data on the heap.
Examples of reference types include classes, arrays, and interfaces.

Assignment:
Value Types:
When you assign a value type variable to another variable, a copy of the value is created.
Modifications to one variable do not affect the other.

Reference Types:
When you assign a reference type variable to another variable, you're actually copying the reference to the same underlying object in memory.
Both variables will refer to the same object, so changes made through one variable will be reflected when accessing the object through the other variable.

Passing to Methods:
Value Types:
When you pass a value type variable to a method, a copy of the variable's value is passed.
Any modifications made to the parameter inside the method do not affect the original variable.

Reference Types:
When you pass a reference type variable to a method, you're passing the reference to the same object in memory.
Therefore, changes made to the object inside the method will affect the object outside the method.

Nullability:
Value Types:
Value types cannot be null unless they are nullable value types, which are declared using the ? modifier (e.g., int?, float?).
Nullable value types can represent the value of the underlying type or a null value.

Reference Types:
Reference types can be null by default. If a reference type variable is not initialized, it will point to null, indicating that it does not reference any object in memory.

Bubble Sort


Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order.
The pass through the list is repeated until the list is sorted.
It is called Bubble Sort because smaller elements "bubble" to the top of the list with each pass.


function bubbleSort(arr) {
    var n = arr.length;
    var swapped;
    do {
        swapped = false;
        for (var i = 0; i < n - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                // Swap arr[i] and arr[i + 1]
                var temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
                swapped = true;
            }
        }
    } while (swapped);
    return arr;
}

var array = [64, 34, 25, 12, 22, 11, 90];
console.log("Original array: " + array);
console.log("Sorted array: " + bubbleSort(array));

Time Complexity:
Worst Case: O(n^2)
The worst case scenario occurs when the input array is sorted in reverse order. In this case, Bubble Sort performs n passes through the array, and in each pass, it makes a swap for each pair of adjacent elements. This results in a time complexity of O(n^2).
Space Complexity:
Bubble Sort is an in-place sorting algorithm, meaning it does not require additional space proportional to the input size.
It sorts the elements within the given array itself, so the space complexity is O(1), indicating constant space usage regardless of the input size.
Refereneces:
https://s-satsangi.medium.com/insertion-sort-selection-sort-and-bubble-sort-5eb16d55a4de

Sealed Class

The sealed keyword is used to prevent a class from being inherited or to prevent a method from being overridden.
When a class is marked as sealed, it means that it cannot be used as a base class for further inheritance.
Similarly, when a method is marked as sealed, it means that it cannot be overridden in derived classes.

Sealed Class:

public sealed class FinalClass
{
    // Class members and methods
}

// This will cause a compile-time error
public class DerivedClass : FinalClass
{
    // Cannot inherit from a sealed class
}

Sealed Method:

public class BaseClass
{
    public virtual void Method1()
    {
        Console.WriteLine("Method1 in BaseClass");
    }

    public sealed void Method2()
    {
        Console.WriteLine("Method2 in BaseClass");
    }
}

public class DerivedClass : BaseClass
{
    // This will cause a compile-time error
    public override void Method1()
    {
        Console.WriteLine("Method1 in DerivedClass");
    }
}

Express Route

 Gateway types

When you create a virtual network gateway, you need to specify several settings. One of the required settings, -GatewayType, specifies whether the gateway is used for ExpressRoute, or VPN traffic.

  • Vpn - To send encrypted traffic across the public Internet, you use the gateway type 'Vpn'. This type of gateway is also referred to as a VPN gateway. Site-to-Site, Point-to-Site, and VNet-to-VNet connections all use a VPN gateway.

  • ExpressRoute - To send network traffic on a private connection, you use the gateway type 'ExpressRoute'. This type of gateway is also referred to as an ExpressRoute gateway and is used when configuring ExpressRoute.

Each virtual network can have only one virtual network gateway per gateway type. For example, you can have one virtual network gateway that uses -GatewayType Vpn, and one that uses -GatewayType ExpressRoute.

Gateway SKUs

When you create a virtual network gateway, you need to specify the gateway SKU that you want to use. When you select a higher gateway SKU, more CPUs and network bandwidth are allocated to the gateway, and as a result, the gateway can support higher network throughput to the virtual network.

ExpressRoute virtual network gateways can use the following SKUs:


Microsoft Entra Joined Devices

What are Microsoft Entra Joined Devices?

Microsoft Entra joined devices are part of Microsoft's identity and access management solution that allows devices to be securely registered and managed within Azure Active Directory (Azure AD). This integration ensures that only trusted devices can access corporate resources, providing an additional layer of security. There are two main types of device management in Azure AD:

  1. Azure AD Joined: Devices are directly joined to Azure AD, ideal for devices that are solely used for work and don't need to be part of an on-premises domain. This is common for organizations fully operating in the cloud.

  2. Azure AD Registered: Typically for personal or BYOD (Bring Your Own Device) scenarios, where devices are simply registered in Azure AD for access management without being fully joined. This offers flexibility while still maintaining a level of control and security.

Example Scenario: Implementing Azure AD Join

Let's consider a scenario where an organization wants to implement Azure AD Join for its corporate laptops to ensure secure access to its Office 365 applications and internal resources.

  1. Setup Azure AD for Device Management: The IT administrator ensures Azure AD is configured for device management, defining policies for access and security.

  2. Join Devices to Azure AD: On each corporate laptop, the administrator accesses the "Access work or school" settings and selects the option to "Connect" the device to Azure AD, entering their corporate credentials when prompted.

  3. Verify Device Join: Once the device is joined, it's listed under "Devices" in the Azure AD portal, where it can be managed by IT administrators. Policies for conditional access, compliance, and other security measures are applied to ensure secure access to resources.

The Significance of Entra Joined Devices

Implementing Microsoft Entra joined devices in Azure offers numerous benefits:

  • Enhanced Security: Ensures that only authenticated and compliant devices can access corporate resources, reducing the risk of unauthorized access.

  • Streamlined Management: Provides centralized management of devices through the Azure AD portal, allowing for easy application of security policies and access controls.

  • Improved User Experience: Users enjoy seamless access to resources without repeatedly entering credentials, thanks to single sign-on (SSO) capabilities.

  • Compliance and Reporting: Offers detailed reporting on device status, access patterns, and compliance, aiding in regulatory compliance efforts.

Activity log alerts

Demystifying Activity Log Alerts in Azure

  • In the sprawling ecosystem of Azure, keeping a vigilant eye on your resources and operations is not just beneficial; it's essential for maintaining the health, security, and efficiency of your services. Enter Activity Log Alerts, a powerful feature within Azure that allows you to set up real-time notifications for specific events occurring within your Azure subscription. Let's break down what Activity Log Alerts are and how you can leverage them to safeguard and optimize your Azure environment.

    Understanding Activity Log Alerts

    Activity Log Alerts are automated notifications triggered by specific events recorded in the Azure Activity Log, a comprehensive log that captures an array of events from subscriptions, including resource modifications, service health incidents, and more. These alerts are pivotal for proactive monitoring and immediate response to critical changes or potential issues within your Azure resources.

    Key Components of an Activity Log Alert

    An Activity Log Alert is composed of several elements that define what event will trigger the alert and how you'll be notified. These elements include:

    • Category: Specifies the type of event to monitor, such as Administrative actions, Service Health, Autoscale activities, Policy changes, or Recommendations.
    • Scope: Determines the level at which the alert operates – this can be at the resource, resource group, or subscription level.
    • Resource Group: Identifies where the alert rule is stored within Azure.
    • Resource Type: Defines the namespace for the target resource of the alert.
    • Operation Name: Specifies the particular operation within the category that triggers the alert.
    • Level: Indicates the severity of the event (Verbose, Informational, Warning, Error, or Critical).
    • Status: Reflects the outcome of the event (Started, Failed, or Succeeded).
    • Event Initiated By: Identifies the user or service that triggered the event, using an email address or a Microsoft Entra identifier.

    Practical Example: Setting Up an Alert for VM Deletion

    Imagine you want to be notified whenever a Virtual Machine (VM) is deleted within your Azure subscription. Here's a simplified example of how you might configure an Activity Log Alert for this scenario:

    1. Navigate to the Azure Portal: Go to the Activity Log section.
    2. Create a New Alert Rule: Select the "+ Add activity log alert" option.
    3. Configure the Alert Rule:
      • Category: Choose "Administrative".
      • Scope: Select the subscription or specific resource group you want to monitor.
      • Resource Type: Specify "Microsoft.Compute/virtualMachines".
      • Operation Name: Enter "Delete Virtual Machine".
      • Level: Choose "Critical".
      • Status: Set to "Succeeded" to trigger the alert only when a VM deletion is successfully completed.
      • Action Group: Define how you want to be notified (e.g., email, SMS, or webhook).

    Why Activity Log Alerts Matter

    By judiciously using Activity Log Alerts, you can enhance your Azure management strategy in several ways:

    • Proactive Monitoring: Stay ahead of potential issues by being alerted to critical events as they happen.
    • Security and Compliance: Quickly detect and respond to unauthorized or suspicious activities.
    • Operational Efficiency: Automate the monitoring of routine operations and resource health to focus on more strategic tasks.

    Conclusion

    Activity Log Alerts in Azure are a cornerstone of effective cloud resource management, offering the visibility and agility needed to maintain a secure and efficient cloud environment. By setting up tailored alerts, you can ensure that your team is always informed about the activities that matter most to your organization's operational integrity and security posture.

Side Car

Understanding the Sidecar Pattern in Docker

In the world of containerized applications, design patterns play a critical role in solving common problems in a systematic and repeatable way. One such pattern, the sidecar pattern, has gained popularity for its versatility and effectiveness in enhancing and extending the functionality of a primary container without altering its original behavior.

What is a Sidecar Pattern?

The sidecar pattern involves deploying a secondary container alongside a primary application container, where both containers share the same lifecycle and network space. This sidecar container extends or enhances the functionality of the primary container by managing tasks such as logging, monitoring, configuration, and networking services, without the primary container needing to know about these auxiliary functions.

Benefits of Using the Sidecar Pattern

  • Modularity: Separates auxiliary features from the main application logic, promoting cleaner and more manageable code.
  • Scalability: Allows for the independent scaling of application components and sidecars based on demand.
  • Reusability: Sidecar containers can be reused across multiple applications, reducing development time and effort.

Example: Implementing Logging with a Sidecar Container

To illustrate the sidecar pattern in action, let's consider an example where we deploy a logging sidecar container alongside a web application container. The goal is for the sidecar container to handle all logging tasks, thereby decoupling the logging concerns from the main application.

Step 1: Define Your Primary Application Container

First, we define our primary web application container in a docker-compose.yml file. This container runs a simple web server.

version: '3' services: web-app: image: my-web-app:latest volumes: - /var/log/web-app:/var/log networks: - webnet

Step 2: Add the Logging Sidecar Container

Next, we introduce the logging sidecar container. This container has access to the same volume as the web application, allowing it to read and manage the application's logs.

log-sidecar: image: my-logging-app:latest volumes: - /var/log/web-app:/var/log networks: - webnet networks: webnet:

In this setup, my-logging-app is a custom logging application designed to monitor the /var/log/web-app directory for any new logs generated by the my-web-app container and process them accordingly.

Bringing It All Together

With both the primary application container and the sidecar container defined in the docker-compose.yml file, they can be deployed together as a single unit. The sidecar container enhances the primary application by taking over the responsibility of logging, demonstrating the sidecar pattern's ability to modularize and extend container functionality effectively.

Conclusion

The sidecar pattern in Docker offers a powerful approach to adding functionality to your containers without increasing their complexity. By deploying a sidecar container alongside your primary application container, you can keep your applications lean, modular, and maintainable. Whether it's for logging, monitoring, or any other auxiliary service, the sidecar pattern is an invaluable tool in the modern developer's toolkit.