Skip to content

Commit 15319ed

Browse files
authored
Merge pull request #299261 from MicrosoftDocs/main
05/02/2025 AM Publishing
2 parents 202b9c8 + 0753483 commit 15319ed

39 files changed

+1042
-974
lines changed

articles/azure-app-configuration/feature-management-javascript-reference.md

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,96 @@ When defining an audience, users and groups can be excluded from the audience. E
449449

450450
In the above example, the feature is enabled for users named `Jeff` and `Alicia`. It's also enabled for users in the group named `Ring0`. However, if the user is named `Mark`, the feature is disabled, regardless of if they are in the group `Ring0` or not. Exclusions take priority over the rest of the targeting filter.
451451

452+
### Targeting in a Web Application
453+
454+
An example web application that uses the targeting feature filter is available in this [example](https://github.com/microsoft/FeatureManagement-JavaScript/tree/preview/examples/express-app) project.
455+
456+
In web applications, especially those with multiple components or layers, passing targeting context (`userId` and `groups`) to every feature flag check can become cumbersome and repetitive. This scenario is referred to as "ambient targeting context," where the user identity information is already available in the application context (such as in session data or authentication context) but needs to be accessible to feature management evaluations throughout the application.
457+
458+
#### ITargetingContextAccessor
459+
460+
The library provides a solution through the `ITargetingContextAccessor` pattern.
461+
462+
``` typescript
463+
interface ITargetingContext {
464+
userId?: string;
465+
groups?: string[];
466+
}
467+
468+
interface ITargetingContextAccessor {
469+
getTargetingContext: () => ITargetingContext | undefined;
470+
}
471+
```
472+
473+
Instead of explicitly passing the targeting context with each `isEnabled` or `getVariant` call, you can provide a function that knows how to retrieve the current user's targeting information from your application's context:
474+
475+
```typescript
476+
import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management";
477+
478+
// Create a targeting context accessor that uses your application's auth system
479+
const targetingContextAccessor = {
480+
getTargetingContext: () => {
481+
// In a web application, this might access request context or session data
482+
// This is just an example - implement based on your application's architecture
483+
return {
484+
userId: getCurrentUserId(), // Your function to get current user
485+
groups: getUserGroups() // Your function to get user groups
486+
};
487+
}
488+
};
489+
490+
// Configure the feature manager with the accessor
491+
const featureManager = new FeatureManager(featureProvider, {
492+
targetingContextAccessor: targetingContextAccessor
493+
});
494+
495+
// Now you can call isEnabled without explicitly providing targeting context
496+
// The feature manager will use the accessor to get the current user context
497+
const isBetaEnabled = await featureManager.isEnabled("Beta");
498+
```
499+
500+
This pattern is particularly useful in server-side web applications where user context may be available in a request scope or in client applications where user identity is managed centrally.
501+
502+
#### Using AsyncLocalStorage for request context
503+
504+
One common challenge when implementing the targeting context accessor pattern is maintaining request context throughout an asynchronous call chain. In Node.js web applications, user identity information is typically available in the request object, but becomes inaccessible once you enter asynchronous operations.
505+
506+
Node.js provides [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) from the `async_hooks` module to solve this problem. It creates a store that persists across asynchronous operations within the same logical "context" - perfect for maintaining request data throughout the entire request lifecycle.
507+
508+
Here's how to implement a targeting context accessor using AsyncLocalStorage in an express application:
509+
510+
```typescript
511+
import { AsyncLocalStorage } from "async_hooks";
512+
import express from "express";
513+
514+
const requestAccessor = new AsyncLocalStorage();
515+
516+
const app = express();
517+
// Middleware to store request context
518+
app.use((req, res, next) => {
519+
// Store the request in AsyncLocalStorage for this request chain
520+
requestAccessor.run(req, () => {
521+
next();
522+
});
523+
});
524+
525+
// Create targeting context accessor that retrieves user data from the current request
526+
const targetingContextAccessor = {
527+
getTargetingContext: () => {
528+
// Get the current request from AsyncLocalStorage
529+
const request = requestContext.getStore();
530+
if (!request) {
531+
return undefined; // Return undefined if there's no current request
532+
}
533+
// Extract user data from request (from session, auth token, etc.)
534+
return {
535+
userId: request.user?.id,
536+
groups: request.user?.groups || []
537+
};
538+
}
539+
};
540+
```
541+
452542
## Variants
453543

454544
When new features are added to an application, there may come a time when a feature has multiple different proposed design options. A common solution for deciding on a design is some form of A/B testing, which involves providing a different version of the feature to different segments of the user base and choosing a version based on user interaction. In this library, this functionality is enabled by representing different configurations of a feature with variants.
@@ -457,7 +547,7 @@ Variants enable a feature flag to become more than a simple on/off flag. A varia
457547

458548
### Getting a variant with targeting context
459549

460-
For each feature, a variant can be retrieved using the `FeatureManager`'s `getVariant` method. The variant assignment is dependent on the user currently being evaluated, and that information is obtained from the targeting context you passed in.
550+
For each feature, a variant can be retrieved using the `FeatureManager`'s `getVariant` method. The variant assignment is dependent on the user currently being evaluated, and that information is obtained from the targeting context you passed in. If you have registered a targeting context accessor to the `FeatureManager`, the targeting context will be automatically retrieved from it. But you can still override it by manually passing targeting context when calling `getVariant`.
461551

462552
```typescript
463553
const variant = await featureManager.getVariant("MyVariantFeatureFlag", { userId: "Sam" });
@@ -542,8 +632,8 @@ The process of allocating a feature's variants is determined by the `allocation`
542632

543633
```json
544634
"allocation": {
545-
"default_when_enabled": "Small",
546635
"default_when_disabled": "Small",
636+
"default_when_enabled": "Small",
547637
"user": [
548638
{
549639
"variant": "Big",
@@ -751,6 +841,32 @@ trackEvent(appInsights.defaultClient, "<TARGETING_ID>", {name: "TestEvent", pro
751841

752842
The telemetry publisher sends `FeatureEvaluation` custom events to the Application Insights when a feature flag enabled with telemetry is evaluated. The custom event follows the [FeatureEvaluationEvent](https://github.com/microsoft/FeatureManagement/tree/main/Schema/FeatureEvaluationEvent) schema.
753843

844+
### Targeting telemetry processor
845+
846+
If you have implemented [`ITargetingContextAccessor`](#itargetingcontextaccessor), you can use the built-in Application Insights telemetry processor to automatically attach targeting ID information to all telemetry by calling the `createTargetingTelemetryProcessor` function.
847+
848+
```typescript
849+
const appInsights = require("applicationinsights");
850+
appInsights.setup(process.env.APPINSIGHTS_CONNECTION_STRING).start();
851+
852+
const { createTargetingTelemetryProcessor } = require("@microsoft/feature-management-applicationinsights-node");
853+
appInsights.defaultClient.addTelemetryProcessor(
854+
createTargetingTelemetryProcessor(targetingContextAccessor)
855+
);
856+
```
857+
858+
This ensures that every telemetry item sent to Application Insights includes the user's targeting ID information (userId and groups), allowing you to correlate feature flag usage with specific users or groups in your analytics.
859+
860+
If you are using the targeting telemetry processor, instead of calling the `trackEvent` method provided by the feature management package, you can directly call the `trackEvent` method from the Application Insights SDK. The targeting ID information will be automatically attached to the custom event telemetry's `customDimensions`.
861+
862+
```typescript
863+
// Instead of calling trackEvent and passing the app insights client
864+
// trackEvent(appInsights.defaultClient, "<TARGETING_ID>", {name: "TestEvent", properties: {"Tag": "Some Value"}});
865+
866+
// directly call trackEvent method provided by App Insights SDK
867+
appInsights.defaultClient.trackEvent({ name: "TestEvent" });
868+
```
869+
754870
## Next steps
755871

756872
To learn how to use feature flags in your applications, continue to the following quickstarts.

articles/azure-app-configuration/feature-management-overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Feature | .NET | Spring | Python | JavaScript
3939
------- | ---- | ------ | ------ | ----------
4040
Targeting Filter | [GA](./feature-management-dotnet-reference.md#targeting) | GA | [GA](./feature-management-python-reference.md#targeting) | [GA](./feature-management-javascript-reference.md#targeting)
4141
Targeting Exclusion | [GA](./feature-management-dotnet-reference.md#targeting-exclusion) | GA | [GA](./feature-management-python-reference.md#targeting-exclusion) | [GA](./feature-management-javascript-reference.md#targeting-exclusion)
42-
Ambient Targeting | [GA](./feature-management-dotnet-reference.md#targeting-in-a-web-application) | WIP | WIP | WIP
42+
Ambient Targeting | [GA](./feature-management-dotnet-reference.md#targeting-in-a-web-application) | WIP | WIP | [Preview](./feature-management-javascript-reference.md#targeting-in-a-web-application)
4343
Time Window Filter | [GA](./feature-management-dotnet-reference.md#microsofttimewindow) | GA | [GA](./feature-management-python-reference.md#microsofttimewindow) | [GA](./feature-management-javascript-reference.md#microsofttimewindow)
4444
Recurring Time Window | [GA](./feature-management-dotnet-reference.md#microsofttimewindow) | GA | WIP | WIP
4545
Custom Feature Filter | [GA](./feature-management-dotnet-reference.md#implementing-a-feature-filter) | GA | [GA](./feature-management-python-reference.md#implementing-a-feature-filter) | [GA](./feature-management-javascript-reference.md#implementing-a-feature-filter)

articles/backup/backup-support-matrix-iaas.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Support matrix for Azure VM backups
33
description: Get a summary of support settings and limitations for backing up Azure VMs by using the Azure Backup service.
44
ms.topic: reference
5-
ms.date: 03/05/2025
5+
ms.date: 05/02/2025
66
ms.custom: references_regions, linux-related-content
77
ms.reviewer: nikhilsarode
88
ms.service: azure-backup
@@ -53,6 +53,8 @@ Back up a VM whose machine time is changed | Not supported.<br/><br/> If you cha
5353
Do multiple backups per day | Supported through **Enhanced policy**. <br><br> For hourly backup, the minimum recovery point objective (RPO) is 4 hours and the maximum is 24 hours. You can set the backup schedule to 4, 6, 8, 12, and 24 hours, respectively. <br><br> Note that the maximum limit of instant recovery point retention range depends on the number of snapshots you take per day. If the snapshot count is more (for example, every *4 hours* frequency in *24 hours* duration - *6* scheduled snapshots), then the maximum allowed days for retention reduces. However, if you choose lower RPO of *12* hours, the snapshot retention is increased to *30 days*. <br><br> Learn about how to [back up an Azure VM using Enhanced policy](backup-azure-vms-enhanced-policy.md).
5454
Back up a VM with a deprecated plan when the publisher has removed it from Azure Marketplace | Not supported. <br><br> Backup is possible. However, restore will fail. <br><br> If you've already configured backup for a VM with a deprecated virtual machine offer and encounter a restore error, see [Troubleshoot backup errors with Azure VMs](backup-azure-vms-troubleshoot.md#usererrormarketplacevmnotsupported---vm-creation-failed-due-to-market-place-purchase-request-being-not-present).
5555
Back up VMs with docker (containers) | Not supported
56+
[Soft Delete for backups](backup-azure-security-feature-cloud.md) | Not Supported with Azure role-based access control (Azure RBAC) permissions at the resource group level. Requires Azure RBAC permissions at the subscription level, including the `Microsoft.DataProtection/locations/checkFeatureSupport/action` permission.
57+
5658

5759
## Operating system support (Windows)
5860

@@ -124,7 +126,7 @@ Recovery points on DPM or MABS disk | 64 for file servers, and 448 for app serve
124126
--- | ---
125127
**Create a new VM** | This option quickly creates and gets a basic VM up and running from a restore point.<br/><br/> You can specify a name for the VM, select the resource group and virtual network in which it will be placed, and specify a storage account for the restored VM. The new VM must be created in the same region as the source VM.
126128
**Restore disk** | This option restores a VM disk, which can you can then use to create a new VM.<br/><br/> Azure Backup provides a template to help you customize and create a VM. <br/><br> The restore job generates a template that you can download and use to specify custom VM settings and create a VM.<br/><br/> The disks are copied to the resource group that you specify.<br/><br/> Alternatively, you can attach the disk to an existing VM, or create a new VM by using PowerShell.<br/><br/> This option is useful if you want to customize the VM, add configuration settings that weren't there at the time of backup, or add settings that must be configured via the template or PowerShell.
127-
**Replace existing** | You can restore a disk and use it to replace a disk on the existing VM.<br/><br/> The current VM must exist. If it has been deleted, you can't use this option.<br/><br/> Azure Backup takes a snapshot of the existing VM before replacing the disk, and it stores the snapshot in the staging location that you specify. Existing disks connected to the VM are replaced with the selected restore point.<br/><br/> The snapshot is copied to the vault and retained in accordance with the retention policy. <br/><br/> After the replace-disk operation, the original disk is retained in the resource group. You can choose to manually delete the original disks if they aren't needed. <br/><br/>This option is supported for unencrypted managed VMs and for VMs [created from custom images](https://azure.microsoft.com/resources/videos/create-a-custom-virtual-machine-image-in-azure-resource-manager-with-powershell/). It's not supported for unmanaged disks and VMs, classic VMs, and [generalized VMs](/azure/virtual-machines/capture-image-resource).<br/><br/> If the restore point has more or fewer disks than the current VM, the number of disks in the restore point will only reflect the VM configuration.<br><br> This option is also supported for VMs with linked resources, like [user-assigned managed identity](../active-directory/managed-identities-azure-resources/overview.md) and [Azure Key Vault](/azure/key-vault/general/overview).
129+
**Replace existing** | You can restore a disk and use it to replace a disk on the existing VM.<br/><br/> The current VM must exist. If it has been deleted, you can't use this option.<br/><br/> Azure Backup takes a snapshot of the existing VM before replacing the disk, and it stores the snapshot in the staging location that you specify. Existing disks connected to the VM are replaced with the selected restore point.<br/><br/> The snapshot is copied to the vault and retained in accordance with the retention policy. <br/><br/> After the replace-disk operation, the original disk is retained in the resource group. You can choose to manually delete the original disks if they aren't needed. <br/><br/>This option is supported for unencrypted managed VMs and for VMs [created from custom images](/azure/virtual-machines/windows/tutorial-custom-images). It's not supported for unmanaged disks and VMs, classic VMs, and [generalized VMs](/azure/virtual-machines/capture-image-resource).<br/><br/> If the restore point has more or fewer disks than the current VM, the number of disks in the restore point will only reflect the VM configuration.<br><br> This option is also supported for VMs with linked resources, like [user-assigned managed identity](../active-directory/managed-identities-azure-resources/overview.md) and [Azure Key Vault](/azure/key-vault/general/overview).
128130
**Cross Region (secondary region)** | You can use cross-region restore to restore Azure VMs in the secondary region, which is an [Azure paired region](../reliability/cross-region-replication-azure.md).<br><br> You can restore all the Azure VMs for the selected recovery point if the backup is done in the secondary region.<br><br> This feature is available for the following options:<br> - [Create a VM](./backup-azure-arm-restore-vms.md#create-a-vm) <br> - [Restore disks](./backup-azure-arm-restore-vms.md#restore-disks) <br><br> We don't currently support the [Replace existing disks](./backup-azure-arm-restore-vms.md#replace-existing-disks) option.<br><br> Backup admins and app admins have permissions to perform the restore operation on a secondary region.
129131
**Cross Subscription** | Allowed only if the [Cross Subscription Restore property](backup-azure-arm-restore-vms.md#cross-subscription-restore-for-azure-vm) is enabled for your Recovery Services vault. <br><br> You can restore Azure Virtual Machines or disks to a different subscription within the same tenant as the source subscription (as per the Azure RBAC capabilities) from restore points. <br><br> This feature is available for the following options:<br> - [Create a VM](./backup-azure-arm-restore-vms.md#create-a-vm) <br> - [Restore disks](./backup-azure-arm-restore-vms.md#restore-disks) <br><br> Cross Subscription Restore is unsupported for: <br> - [Snapshots](backup-azure-vms-introduction.md#snapshot-creation) tier recovery points. It's also unsupported for [unmanaged VMs](backup-azure-arm-restore-vms.md#restoring-unmanaged-vms-and-disks-as-managed) and [VMs with disks having Azure Encryptions (ADE)](backup-azure-vms-encryption.md#encryption-support-using-ade). <br> - [VMs with CMK encrypted disks](backup-azure-vms-encryption.md).
130132
**Cross Zonal Restore** | You can use cross-zonal restore to restore Azure zone-pinned VMs in available zones. You can restore Azure VMs or disks to different zones (one of the Azure RBAC capabilities) from restore points. Note that when you select a zone to restore, it selects the [logical zone](../reliability/availability-zones-overview.md#zonal-and-zone-redundant-services) (and not the physical zone) as per the Azure subscription you will use to restore to. <br><br> This feature is available for the following options:<br> - [Create a VM](./backup-azure-arm-restore-vms.md#create-a-vm) <br> - [Restore disks](./backup-azure-arm-restore-vms.md#restore-disks) <br><br> Cross-zonal restore is unsupported for [snapshots](backup-azure-vms-introduction.md#snapshot-creation) of restore points. It's also unsupported for [encrypted Azure VMs](backup-azure-vms-introduction.md#encryption-of-azure-vm-backups).

articles/batch/account-move.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Move an Azure Batch account to another region
33
description: Learn how to move an Azure Batch account to a different region using an Azure Resource Manager template in the Azure portal.
44
ms.topic: how-to
5-
ms.date: 02/27/2023
5+
ms.date: 04/25/2025
66
ms.custom: subject-moving-resources, devx-track-arm-template
77
---
88

articles/batch/batch-application-packages.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Deploy application packages to compute nodes
33
description: Learn how to use the application packages feature of Azure Batch to easily manage multiple applications and versions for installation on Batch compute nodes.
44
ms.topic: how-to
5-
ms.date: 04/03/2023
5+
ms.date: 04/25/2025
66
ms.devlang: csharp
77
ms.custom: H1Hack27Feb2017, devx-track-csharp
88
---

articles/batch/batch-custom-image-pools-to-azure-compute-gallery-migration-guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Migrate Azure Batch custom image pools to Azure Compute Gallery
33
description: Learn how to migrate Azure Batch custom image pools to Azure compute gallery and plan for feature end of support.
44
ms.service: azure-batch
55
ms.topic: how-to
6-
ms.date: 03/07/2023
6+
ms.date: 04/25/2025
77
---
88

99
# Migrate Azure Batch custom image pools to Azure Compute Gallery

0 commit comments

Comments
 (0)