#URL
https://login.microsoftonline.com/{Tenant ID}/oauth2/v2.0/token
#METHOD
POST
#X-WWW-FORM-URLENCODED
#X-WWW-FORM-URLENCODED
grant_type=client_credentials
&client_id={Client ID}
&client_secret={Client Secret}
&scope=https://management.azure.com/.default
Tuesday, February 18, 2025
How to Obtain an Access Token for Azure Cost Management API Calls
Monday, February 17, 2025
Optimizing Data Retention for Specific Tables in Azure Log Analytics Workspace
Application Insights plays a crucial role in applications hosted on Microsoft Azure. It is important to periodically review the associated Log Analytics Workspace instances to ensure they are properly governed and optimized.
The following areas should be examined for these resources in alignment with the Azure Well-Architected Framework.
- Reliability
- Security
- Cost Optimization
- Operational Excellence
- Performance Efficiency
It is evident that AppTraces have increased recently, which may negatively impact overall query performance.
My Log Analytics Workspace is set to the default 90-day data retention period, which I prefer to keep unchanged to achieve cost optimization.
Since the outlier is only in the AppTraces table, I want to reduce the retention period specifically for that table. The expectation is to maintain a lower data volume in that container while keeping the overall workspace retention unchanged.
Following was the approach I used.
Navigate to Tables in the Log Analytics Workspace and select the AppTraces table.
Click on Manage Table to access the table settings.
Change the retention period to 60 days, which overrides the default retention setting for this table only.
That's it! The AppTraces table will now retain data for 60 days, reducing log volume while keeping the overall workspace retention unchanged.
Let's consider the opposite approach: How can you increase data retention while still optimizing costs?
You can also use this approach to optimize costs. For example, if you need to increase the retention period from 90 to 120 days, instead of applying the change to all tables, you can selectively extend retention only for the tables that truly require it. This helps balance cost efficiency and data availability.
Additional retention will incur costs based on the amount of storage consumed.
Thursday, January 16, 2025
Using Azure Cost Management API to Analyze Resource Group Expenditures by Cost Unit
- Cost Analysis
- Budgets
- Cost Alerts
- Cost Allocation
- Exports
- Recommendations
- Multi-Cloud Support
- Governance and Accountability
- Integration with Power BI
- API
#URL
https://management.azure.com/subscriptions/{Tenant ID}/resourceGroups/{Resource Group}/providers/Microsoft.CostManagement/query?api-version=2024-08-01
#METHOD
POST
#AUTHORIZATION
Bearer Token
#BODY
{
"type": "Usage",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"type": "Dimension",
"name": "ResourceType"
},
{
"type": "Dimension",
"name": "MeterCategory"
}
]
}
}
You can use this approach to generate an access token{
"id": "subscriptions/{Tenant ID}/resourcegroups/{Resource Group}/providers/Microsoft.CostManagement/query/5c25de9e-06aa-4839-81b4-64273e0bc86f",
"name": "5c25de9e-06aa-4839-81b4-64273e0bc86f",
"type": "Microsoft.CostManagement/query",
"location": null,
"sku": null,
"eTag": null,
"properties": {
"nextLink": null,
"columns": [
{
"name": "PreTaxCost",
"type": "Number"
},
{
"name": "ResourceType",
"type": "String"
},
{
"name": "MeterCategory",
"type": "String"
},
{
"name": "Currency",
"type": "String"
}
],
"rows": [
[
34.957915,
"microsoft.apimanagement/service",
"API Management",
"AUD"
],
[
0.0016342144,
"microsoft.keyvault/vaults",
"Key Vault",
"AUD"
],
[
0.036166705555556,
"microsoft.loadtestservice/loadtests",
"Azure Load Testing",
"AUD"
],
[
0.034666562722667,
"microsoft.operationalinsights/workspaces",
"Log Analytics",
"AUD"
],
[
0.000007542612,
"microsoft.storage/storageaccounts",
"Bandwidth",
"AUD"
],
[
0.0001935796,
"microsoft.storage/storageaccounts",
"Storage",
"AUD"
],
[
0.0,
"microsoft.web/sites",
"Azure App Service",
"AUD"
],
[
0.000000359172,
"microsoft.web/sites",
"Bandwidth",
"AUD"
]
]
}
}
Wednesday, January 15, 2025
Mocking Custom Responses with Azure API Management – Custom Mock Response from External Files
This article is the third part of a multi-part series. In this section, I will explain how to render custom mock responses from JSON files stored in a storage container. Below are the different parts of this article series.
- Mocking Custom Responses with Azure API Management – Simple Mock Response
- Mocking Custom Responses with Azure API Management – Custom Mock Response
- Mocking Custom Responses with Azure API Management – Custom Mock Response from External Files
{
"id": 1,
"name": "Introduction to Azure",
"category": "Cloud Computing",
"description": "A beginner-friendly course covering the fundamentals of Microsoft Azure.",
"duration": "4 weeks",
"instructor": "John Doe"
}
<inbound>
<base />
<choose>
<when condition="@(context.Request.Url.Query.GetValueOrDefault("id") == "1")">
<send-request mode="new" response-variable-name="response" timeout="10" ignore-error="false">
<set-url>@($"https://rgstoragefedora001.blob.core.windows.net/data/Subject/1.json?sp=r&st=2024-03-08T12:01:42Z&se=2024-03-08T20:01:42Z&spr=https&sv=2022-11-02&sr=b&sig=DrqWZJxGP38PNJYFKCoMgIqn6AjNC71nw0x%2FjITu4aM%3D")</set-url>
<set-method>GET</set-method>
</send-request>
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@(new JObject(((IResponse)context.Variables["response"]).Body.As<JObject>()).ToString())</set-body>
</return-response>
</when>
<when condition="@(context.Request.Url.Query.GetValueOrDefault("id") == "2")">
<send-request mode="new" response-variable-name="response" timeout="10" ignore-error="false">
<set-url>@($"https://rgstoragefedora001.blob.core.windows.net/data/Subject/2.json?sp=r&st=2024-03-08T12:34:15Z&se=2024-03-08T20:34:15Z&spr=https&sv=2022-11-02&sr=b&sig=OVhf3uGIASMHWHtg8F%2BypQzLatI9DeEzqoFns2iGOUk%3D")</set-url>
<set-method>GET</set-method>
</send-request>
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>@(new JObject(((IResponse)context.Variables["response"]).Body.As<JObject>()).ToString())</set-body>
</return-response>
</when>
<otherwise>
<return-response>
<set-status code="404" reason="Not Found" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>{
"error": "Student ID not found"
}</set-body>
</return-response>
</otherwise>
</choose>
</inbound>
Tuesday, December 24, 2024
Mocking Custom Responses with Azure API Management – Custom Mock Response
This article is the second part of a three-part series. We will discuss how to render custom mock responses using APIM policy. Below are the different parts of this article series.
- Mocking Custom Responses with Azure API Management – Simple Mock Response
- Mocking Custom Responses with Azure API Management – Custom Mock Response
- Mocking Custom Responses with Azure API Management – Custom Mock Response from External Files
Custom mock responses
Often, we need more than just a 200 OK response without a body. Instead, we require comprehensive responses formatted as JSON messages. Adding to the complexity, the response often needs to vary based on specific query string parameters.
Here’s the approach I used to generate custom mock responses in Azure API Management based on varying query string parameters.
Navigate to your API Management instance and select the specific API operation you want to configure.
Click on the Inbound Processing section and open the Policy Code Editor.
We will modify the inbound section of the policy. We will add a policy segment to dynamically generate the response body based on a specified query string parameter.
Here is the code I used
<inbound>
<base />
<choose>
<when condition="@(context.Request.Url.Query.GetValueOrDefault("id") == "1")">
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>{
"studentId": "1",
"name": "Jane Smith",
"grade": "B"
}</set-body>
</return-response>
</when>
<when condition="@(context.Request.Url.Query.GetValueOrDefault("id") == "2")">
<return-response>
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>{
"studentId": "2",
"name": "Jane Smith",
"grade": "B",
}</set-body>
</return-response>
</when>
<otherwise>
<return-response>
<set-status code="404" reason="Not Found" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>{
"error": "Student ID not found"
}</set-body>
</return-response>
</otherwise>
</choose>
</inbound>
You can test the outcome by navigating to the Test console and specifying the appropriate query string parameter, as shown below.
Then, submit the request to verify that the appropriate response is returned based on the specified query string parameter.
Tuesday, December 17, 2024
Ensuring Static IP for Azure App Service When Accessing External APIs Over the Internet
- Integrate the Web App with a Subnet in a Virtual Network
- Create a Public IP
- Create and Configure a NAT Gateway
- Associate the Web App with the NAT Gateway
- Test
[ApiController]
[Route("api/[controller]")]
public class GatewayTestController : ControllerBase
{
private readonly HttpClient _httpClient;
public GatewayTestController(HttpClient httpClient)
{
_httpClient = httpClient;
}
[HttpGet]
public async Task GetOutboundIp()
{
// Call external API over internet
var response = await _httpClient.GetAsync("https://httpbin.org/ip");
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode, "Failed to get outbound IP");
}
var callerIP = await response.Content.ReadAsStringAsync();
return Ok(callerIP);
}
}
Monday, December 9, 2024
Structured Approach to a Successful Azure Integration Services Implementation
- Project Plan Development: Establish the project’s scope, objectives, timelines, budget, and deliverables. This foundational task involves identifying stakeholder requirements and defining a roadmap for successful implementation.
- Discovery Workshop(s): Engage stakeholders in collaborative sessions to gather requirements, align expectations, and document business processes to ensure the integration aligns with organizational goals.
- Develop High-level Architecture: Define the overall architectural vision, including system components and their interactions, to serve as the blueprint for detailed designs.
- Develop Low-level Architecture: Provide a granular view of individual components, interfaces, and data flows to guide development and implementation teams.
- Design Documentation: Compile detailed design specifications, architectural diagrams, and decision logs to serve as reference material for all stakeholders.
- Design Walk-Through Workshop(s): Present the architecture and design plans to stakeholders for validation, feedback, and alignment before moving to implementation.
- Proof of Concept: Build a small-scale prototype to validate critical components, test assumptions, and mitigate risks before full-scale development begins.
- Integration Environment Readiness: Set up environments, such as staging and testing platforms, to support development and ensure readiness for system integration. It is essential to ensure that both source and target environments are prepared for implementation. If the environments are in different locations (e.g., cloud vs. on-premises), the team must exercise extra caution regarding security and access management.
- Landing Zone Configuration: Establish a secure and scalable Azure foundation, ensuring compliance with best practices for networking, identity, and governance.
- DevOps Environment Configuration: Set up CI/CD pipelines, repositories, and automated workflows to streamline development and deployment processes.
- Specific AIS Component Configuration: Configure Azure Integration Services components like Logic Apps, Service Bus, and API Management as per the design.
- Development of Components: Build custom integrations, workflows, and connectors required for the solution based on detailed designs. Most of the development will be conducted using Azure Functions and Logic App workflows. It is crucial to follow a well-structured solution design that incorporates appropriate cloud components. Additionally, adopting a "shift-left" approach to security is highly recommended to address potential risks early in the development lifecycle
- Implement Disaster Recovery & High Availability: Establish redundancy, failover mechanisms, and recovery processes to ensure resilience and minimal downtime.
- Data Migration: Plan, map, and execute the migration of legacy data to the new system, ensuring data integrity and minimal disruption.
- Unit Testing: Validate individual components or modules to ensure they meet functional requirements and perform as expected.
- Integration Testing: Assess the system as a whole to verify that all components communicate and function seamlessly together.
- Vulnerability Assessment & Penetration Testing: Identify security vulnerabilities and test the system’s ability to withstand potential threats or breaches.
- User Acceptance Testing: Engage end-users to validate the system against business requirements and ensure it meets their needs.
- Configure CI/CD Pipelines: Finalize and optimize pipelines to automate deployment processes, enhancing efficiency and consistency.
- Deployment to Non-Prod Environments: Deploy the solution to development and staging environments for final validation and testing.
- Deployment to Prod Environments: Execute the live deployment of the solution in production, ensuring minimal downtime and proper configuration.
- Post-Deployment Verification: Validate the deployment success by verifying all functionalities, data, and integrations are working as intended.
- Establish Monitoring & Logging: Configure monitoring tools and logging mechanisms to ensure ongoing visibility into system performance and health.
- Issue Resolution: Address any post-deployment issues or bugs, ensuring the system operates smoothly and meets expectations.
- Project Closure Documentation: Prepare final documentation, including lessons learned, handover details, and user manuals, to conclude the project formally.