Skip to content
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
48 changes: 48 additions & 0 deletions .github/workflows/update-md-date.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Update Last Modified Date

on:
pull_request:
branches:
- main

permissions:
contents: write
pull-requests: write

jobs:
update-date:
runs-on: ubuntu-latest

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: pip install python-dateutil

- name: Configure Git
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"

- name: Update last modified date in Markdown files
run: python .github/workflows/update_date.py

- name: Pull (merge) remote changes, commit, and push if needed
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
git pull origin "$BRANCH" || echo "No merge needed"
git add -A
git commit -m "Update last modified date in Markdown files" || echo "No changes to commit"
git remote set-url origin https://x-access-token:${TOKEN}@github.com/${{ github.repository }}
git push origin HEAD:"$BRANCH"
49 changes: 49 additions & 0 deletions .github/workflows/update_date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
import subprocess
from datetime import datetime, timezone

# Get the list of modified files
result = subprocess.run(['git', 'diff', '--name-only', 'HEAD~1'], stdout=subprocess.PIPE)
modified_files = result.stdout.decode('utf-8').split()

# Debugging: Print the list of modified files
print("Modified files:", modified_files)

# Filter for Markdown files
modified_md_files = [f for f in modified_files if f.endswith('.md')]

# Debugging: Print the list of modified Markdown files
print("Modified Markdown files:", modified_md_files)

# Current date
current_date = datetime.now(timezone.utc).strftime('%Y-%m-%d')

# Function to update the last modified date in a file
def update_date_in_file(file_path):
with open(file_path, 'r') as file:
lines = file.readlines()

updated = False
with open(file_path, 'w') as file:
for line in lines:
if line.startswith('Last updated:'):
file.write(f'Last updated: {current_date}\n')
updated = True
else:
file.write(line)
if not updated:
file.write(f'\nLast updated: {current_date}\n')

# Check if there are any modified Markdown files
if not modified_md_files:
print("No modified Markdown files found.")
exit(0)

# Update the date in each modified Markdown file
for file_path in modified_md_files:
print(f"Updating file: {file_path}") # Debugging: Print the file being updated
update_date_in_file(file_path)

# Add and commit changes
subprocess.run(['git', 'add', '-A'])
subprocess.run(['git', 'commit', '-m', 'Update last modified date in Markdown files'])
86 changes: 86 additions & 0 deletions .github/workflows/use-visitor-counter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Use Visitor Counter Logic

on:
pull_request:
branches:
- main
schedule:
- cron: '0 0 * * *' # Runs daily at midnight
workflow_dispatch: # Allows manual triggering

permissions:
contents: write
pull-requests: write

jobs:
update-visitor-count:
runs-on: ubuntu-latest

steps:
- name: Checkout current repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Shallow clone visitor counter logic
run: git clone --depth=1 https://github.com/brown9804/github-visitor-counter.git

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies for github-visitor-counter
run: |
cd github-visitor-counter
npm ci

- name: Run visitor counter logic (updates markdown badges and metrics.json)
run: node github-visitor-counter/update_repo_views_counter.js
env:
TRAFFIC_TOKEN: ${{ secrets.TRAFFIC_TOKEN }}
REPO: ${{ github.repository }}

- name: Move generated metrics.json to root
run: mv github-visitor-counter/metrics.json .

- name: List files for debugging
run: |
ls -l
ls -l github-visitor-counter

- name: Clean up visitor counter logic
run: rm -rf github-visitor-counter

- name: Configure Git author
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

# Commit and push logic for PR events (merge, not rebase)
- name: Commit and push changes (PR)
if: github.event_name == 'pull_request'
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git fetch origin
git checkout ${{ github.head_ref }}
git pull origin ${{ github.head_ref }} || echo "No merge needed"
git add -A
git commit -m "Update visitor count" || echo "No changes to commit"
git remote set-url origin https://x-access-token:${TOKEN}@github.com/${{ github.repository }}
git push origin HEAD:${{ github.head_ref }}

# Commit and push logic for non-PR events (merge, not rebase)
- name: Commit and push changes (non-PR)
if: github.event_name != 'pull_request'
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git fetch origin
git checkout ${{ github.ref_name }} || git checkout -b ${{ github.ref_name }} origin/${{ github.ref_name }}
git pull origin ${{ github.ref_name }} || echo "No merge needed"
git add -A
git commit -m "Update visitor count" || echo "No changes to commit"
git remote set-url origin https://x-access-token:${TOKEN}@github.com/${{ github.repository }}
git push origin HEAD:${{ github.ref_name }}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Last updated: 2025-08-27

<!-- START BADGE -->
<div align="center">
<img src="https://img.shields.io/badge/Total%20views-1342-limegreen" alt="Total views">
<p>Refresh Date: 2025-08-29</p>
<img src="https://img.shields.io/badge/Total%20views-42-limegreen" alt="Total views">
<p>Refresh Date: 2025-09-05</p>
</div>
<!-- END BADGE -->
37 changes: 37 additions & 0 deletions metrics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"date": "2025-07-07",
"count": 330,
"uniques": 20
},
{
"date": "2025-07-08",
"count": 159,
"uniques": 6
},
{
"date": "2025-07-10",
"count": 482,
"uniques": 1
},
{
"date": "2025-07-11",
"count": 170,
"uniques": 4
},
{
"date": "2025-07-12",
"count": 7,
"uniques": 1
},
{
"date": "2025-07-14",
"count": 130,
"uniques": 2
},
{
"date": "2025-07-15",
"count": 2,
"uniques": 1
}
]
122 changes: 77 additions & 45 deletions scenario1-high-decay/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,100 @@ Last updated: 2025-08-27

> This scenario is intended to demonstrate rapid temporary file accumulation and disk degradation in Azure Functions.

<details>
<summary><b>List of References</b> (Click to expand)</summary>

- [Kudu service overview](https://learn.microsoft.com/en-us/azure/app-service/resources-kudu)
- [log levels types](https://learn.microsoft.com/en-us/azure/azure-functions/configure-monitoring?tabs=v2#configure-log-levels)
- [How to configure monitoring for Azure Functions](https://learn.microsoft.com/en-us/azure/azure-functions/configure-monitoring?tabs=v2)
- [host.json reference for Azure Functions 2.x and later](https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json#override-hostjson-values)
- [Sampling overrides %](https://learn.microsoft.com/en-us/azure/azure-monitor/app/java-standalone-config#sampling-overrides)
- [Sampling in Azure Monitor Application Insights with OpenTelemetry](https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-sampling)

</details>

> [!NOTE]
> Expected Results: <br/>
> - Rapid temp file accumulation in `C:\local\Temp` <br/>
> - Disk decay within 1-2 days <br/>
> - Restart clears only partial space due to locked files

## Infrastructure Setup

- **App Service Plan (Windows)** - P1v3 tier for high-load testing
- See: [./terraform-infrastructure/variables.tf](./terraform-infrastructure/variables.tf) (lines 12-21)
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (lines 35-45)
- **Deployment Method**: Standard deployment (extracted .zip)
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (line 115)

```terraform
# Service Plan
sku_name = "P1v3"
```

<img width="1908" height="842" alt="image" src="https://github.com/user-attachments/assets/fd5b96e4-be63-4319-b533-5c0fe18ec862" />

- **Deployment Method (Function App Environment Variables)**: Standard deployment (extracted .zip)

```terraform
# Force standard deployment instead of mounted package
"WEBSITE_RUN_FROM_PACKAGE" = "0"
```
- **Application Insights**: Full logging (no sampling)
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (lines 47-56)

<img width="1903" height="842" alt="image" src="https://github.com/user-attachments/assets/412aeee4-3c7d-43b6-82ea-87050e30f4fe" />

- **Diagnostics Settings (Function App Environment Variables)**: Detailed diagnostics enabled

```terraform
# No sampling configured - full logging
sampling_percentage = 100
# Enable full diagnostics for troubleshooting
"WEBSITE_ENABLE_DETAILED_DIAGNOSTICS" = "true"
```
- **Verbose Diagnostics**: Enabled
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (line 118)

<img width="1917" height="796" alt="image" src="https://github.com/user-attachments/assets/bf8e1b7f-bc4a-4c1d-aced-e06f92df5185" />

- **Logging Configuration (Function App Environment Variables)**: Verbose logging enabled. Click here to understand more about [log levels types](https://learn.microsoft.com/en-us/azure/azure-functions/configure-monitoring?tabs=v2#configure-log-levels)

```terraform
# Enable full diagnostics
"WEBSITE_ENABLE_DETAILED_DIAGNOSTICS" = "true"
# Set verbose logging level for better diagnostics but higher disk usage
"AzureFunctionsJobHost__logging__LogLevel__Default" = "Information"
```

<img width="1898" height="828" alt="image" src="https://github.com/user-attachments/assets/6a10498c-fa5d-4e01-a392-0da31ae89cfb" />

- **SCM Separation (Function App Environment Variables)**: Enabled to ensure Kudu and function app run as separate processes

```terraform
# Enable SCM separation for diagnostics
"WEBSITE_DISABLE_SCM_SEPARATION" = "false"
```
- **Storage Logging**: Enabled
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (line 124)

<img width="1907" height="842" alt="image" src="https://github.com/user-attachments/assets/d2128b76-38e1-4e3a-af3f-835db68b428f" />

- **Temp Access (Function App Environment Variables)**: Explicitly enabled for diagnostics and reporting

```terraform
# Log to storage account (increases I/O operations)
"AzureWebJobsDashboard" = azurerm_storage_account.storage.primary_connection_string
# Enable temp file access for diagnostics
"WEBSITE_ENABLE_TEMP_ACCESS" = "true"
```
- **WEBSITE_RUN_FROM_PACKAGE**: Disabled (set to "0")
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (line 115)
- **Key Vault Integration**: Secrets stored in Azure Key Vault
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (lines 147-193)
- **Managed Identity**: System-assigned identity for Key Vault access
- See: [./terraform-infrastructure/main.tf](./terraform-infrastructure/main.tf) (lines 96-98)

## Expected Results
<img width="1907" height="841" alt="image" src="https://github.com/user-attachments/assets/9fbb1211-5d5c-4356-b18f-deef61963150" />

- Rapid temp file accumulation in `C:\local\Temp`
- Disk decay within 1-2 days
- Restart clears only partial space due to locked files
> Overall:

## Deployment Instructions
<img width="973" height="825" alt="image" src="https://github.com/user-attachments/assets/4563a3f1-7168-4b86-b629-6210e99b8f90" />

> For detailed deployment instructions including VS Code deployment and Azure DevOps pipeline samples, see the [DEPLOYMENT.md](./DEPLOYMENT.md) guide.
- **Application Insights**: Full logging (no sampling). Click here to understand more about [Sampling overrides %](https://learn.microsoft.com/en-us/azure/azure-monitor/app/java-standalone-config#sampling-overrides)

1. Go to the terraform-infrastructure directory:
```
cd scenario-1-high-decay/terraform-infrastructure
```
```terraform
# No sampling configured - full logging
sampling_percentage = 100
```

2. Update the `terraform.tfvars` file with your Azure subscription ID and preferred configuration values.
<img width="1903" height="837" alt="image" src="https://github.com/user-attachments/assets/24197ef8-b302-480e-825b-4ddb34e18598" />

3. Initialize Terraform:
```
terraform init
```
- **Key Vault Integration**: Secrets stored in Azure Key Vault
- **Managed Identity**: System-assigned identity for Key Vault access

4. Apply the Terraform configuration:
```
terraform apply
```
## Deployment Instructions

5. After infrastructure deployment, follow the deployment approaches in [DEPLOYMENT.md](./DEPLOYMENT.md) to publish the function app.
1. Please follow the [Terraform Deployment guide](./terraform-infrastructure/README.md) to deploy the necessary Azure resources for the workshop.
2. After infrastructure deployment, follow the deployment approaches in [Deployment Guide](./DEPLOYMENT.md) to publish the function app.

## Testing

Expand All @@ -86,13 +115,16 @@ Last updated: 2025-08-27

> Monitor the function app using:

- Azure Portal > Function App > Platform features > Advanced tools (Kudu)
- Azure Portal > Function App > Development Tools > Advanced tools ([Kudu](https://learn.microsoft.com/en-us/azure/app-service/resources-kudu))

https://github.com/user-attachments/assets/0e529115-13ae-4a2f-83ad-35c33be8bb67

- Application Insights
- Azure Monitor metrics

<!-- START BADGE -->
<div align="center">
<img src="https://img.shields.io/badge/Total%20views-1342-limegreen" alt="Total views">
<p>Refresh Date: 2025-08-29</p>
<img src="https://img.shields.io/badge/Total%20views-42-limegreen" alt="Total views">
<p>Refresh Date: 2025-09-05</p>
</div>
<!-- END BADGE -->
Loading