Skip to content

Commit 50c3a2e

Browse files
Merge pull request #22 from platzi/amines/21
Amines/21
2 parents 9ea254c + 67b2cc7 commit 50c3a2e

File tree

8 files changed

+282
-5
lines changed

8 files changed

+282
-5
lines changed

.github/workflows/pull_request_review.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ on:
55
branches:
66
- main
77

8+
env:
9+
AZURE_MONITOR_CONNECTION_STRING: ${{ secrets.AZURE_MONITOR_KEY }}
10+
811
jobs:
912
build-and-test:
1013
runs-on: ubuntu-latest

docs/clase13.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838

3939
- name: Terraform init
4040
id: init
41-
run: terraform init -backend-config="sas_token={{secrets.SAS_TOKEN}}
41+
run: terraform init -backend-config="{{secrets.SAS_TOKEN}}"
4242

4343
- name: Terraform validate
4444
id: validate

docs/clase14.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Material de la clase 14
2+
3+
Aquí tienes el material para la clase 14
4+
5+
El formato de JSON que necesitas para tus credenciales es el siguiente:
6+
7+
```json
8+
{
9+
"clientSecret": "<password>",
10+
"subscriptionId": "<subscriptionId>",
11+
"tenantId": "<tenant>",
12+
"clientId": "<appId>"
13+
}
14+
```
15+
16+
Luego sigue el código para actualizar la Github Action
17+
18+
```yml
19+
name: API Contactos CI/CD
20+
21+
on:
22+
push:
23+
branches: [ "main" ]
24+
25+
env:
26+
IMAGE_BASE_NAME: aminespinoza/apicontactos:latest
27+
RESOURCE_GROUP: rg--warm-wren
28+
ENVIRONMENT_NAME: devops-env
29+
30+
jobs:
31+
API_Image:
32+
runs-on: ubuntu-latest
33+
defaults:
34+
run:
35+
working-directory: src/ApiContactos
36+
steps:
37+
- name: Check out the repo
38+
uses: actions/checkout@v3
39+
40+
- name: Azure Login
41+
uses: Azure/[email protected]
42+
with:
43+
creds: ${{ secrets.AZURE_CREDENTIALS }}
44+
45+
- name: Install az containerapp extension
46+
run: |
47+
az config set extension.use_dynamic_install=yes_without_prompt
48+
49+
- name: Build Docker NET image
50+
run: |
51+
docker build --platform linux -t $IMAGE_BASE_NAME .
52+
53+
- name: Login to Docker Hub
54+
uses: docker/login-action@v2
55+
with:
56+
username: ${{ secrets.DOCKERHUB_USERNAME }}
57+
password: ${{ secrets.DOCKERHUB_TOKEN }}
58+
59+
- name: Deploy image to hub
60+
run: |
61+
docker push $IMAGE_BASE_NAME
62+
63+
- name: Deploy Container App
64+
run: |
65+
az containerapp up --name contactosapi --image $IMAGE_BASE_NAME --resource-group $RESOURCE_GROUP --environment $ENVIRONMENT_NAME --ingress external --target-port 8080
66+
```

docs/clase15.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Material para la clase 15
2+
3+
Agrega los siguientes paquetes de Nuget.
4+
5+
```bash
6+
dotnet add package OpenTelemetry.Extensions.Hosting
7+
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
8+
dotnet add package OpenTelemetry.Instrumentation.Http
9+
dotnet add package Azure.Monitor.OpenTelemetry.Exporter
10+
11+
```
12+
13+
Crea el archivo appsettings.json (asegúrate de NO SUBIR ESTE ARCHIVO A TU CONTROL DE VERSIONES).
14+
15+
```json
16+
{
17+
"AzureMonitor": {
18+
"ConnectionString": "InstrumentationKey=<your-instrumentation-key>;IngestionEndpoint=https://<your-ingestion-endpoint>"
19+
}
20+
}
21+
```
22+
23+
Actualiza tu archivo Program.cs
24+
25+
```csharp
26+
using OpenTelemetry.Resources;
27+
using OpenTelemetry.Trace;
28+
using OpenTelemetry.Metrics;
29+
using Azure.Monitor.OpenTelemetry.Exporter;
30+
31+
var builder = WebApplication.CreateBuilder(args);
32+
33+
builder.Services.AddOpenTelemetry()
34+
.WithMetrics(metricsBuilder =>
35+
{
36+
metricsBuilder
37+
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ApiContactos"))
38+
.AddAspNetCoreInstrumentation()
39+
.AddHttpClientInstrumentation()
40+
.AddAzureMonitorMetricExporter(o =>
41+
{
42+
o.ConnectionString = builder.Configuration["AzureMonitor:ConnectionString"]
43+
?? Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
44+
});
45+
})
46+
.WithTracing(tracingBuilder =>
47+
{
48+
tracingBuilder
49+
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ApiContactos"))
50+
.AddAspNetCoreInstrumentation()
51+
.AddHttpClientInstrumentation()
52+
.AddAzureMonitorTraceExporter(o =>
53+
{
54+
o.ConnectionString = builder.Configuration["AzureMonitor:ConnectionString"];
55+
});
56+
});
57+
58+
builder.Services.AddEndpointsApiExplorer();
59+
builder.Services.AddSwaggerGen();
60+
61+
var app = builder.Build();
62+
app.UseSwagger();
63+
app.UseSwaggerUI();
64+
app.UseHttpsRedirection();
65+
66+
var summaries = new[]
67+
{
68+
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
69+
};
70+
71+
app.MapGet("/weatherforecast", () =>
72+
{
73+
var forecast = Enumerable.Range(1, 5).Select(index =>
74+
new WeatherForecast
75+
(
76+
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
77+
Random.Shared.Next(-20, 55),
78+
summaries[Random.Shared.Next(summaries.Length)]
79+
))
80+
.ToArray();
81+
return forecast;
82+
})
83+
.WithName("GetWeatherForecast")
84+
.WithOpenApi();
85+
86+
app.Run();
87+
88+
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
89+
{
90+
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
91+
}
92+
93+
public partial class Program { }
94+
```

docs/clase16.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Material para la clase 16
2+
3+
Estas son las consultas que vas a utilizar:
4+
5+
```kql
6+
requests
7+
| where success == 'True'
8+
9+
requests
10+
| summarize AverageDuration = avg(duration)
11+
12+
requests
13+
| summarize OperationCount = count() by operation_Name
14+
| sort by OperationCount desc
15+
| top 1 by OperationCount
16+
```

docs/clase18.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Material para la clase 18
2+
3+
Agrega este nuevo método.
4+
5+
```csharp
6+
app.MapGet("/obtenercontactos", () =>
7+
{
8+
var contactos = new List<string> { "Amin Espinoza", "Oscar Barajas", "Pepe Rodelo" };
9+
return contactos;
10+
})
11+
.WithName("ObtenerContactos")
12+
.WithOpenApi();
13+
14+
app.Run();
15+
```
16+
17+
Después agrega la prueba para esta nueva funcionalidad.
18+
19+
```csharp
20+
using System.Net;
21+
using System.Text.Json;
22+
using Microsoft.AspNetCore.Mvc.Testing;
23+
using Xunit;
24+
25+
public class ContactosTest : IClassFixture<WebApplicationFactory<Program>>
26+
{
27+
private readonly WebApplicationFactory<Program> _factory;
28+
29+
public ContactosTest(WebApplicationFactory<Program> factory)
30+
{
31+
_factory = factory;
32+
}
33+
34+
[Fact]
35+
public async Task ObtenerContactos_ReturnsExpectedContactList()
36+
{
37+
// Arrange
38+
var client = _factory.CreateClient();
39+
40+
// Act
41+
var response = await client.GetAsync("/obtenercontactos");
42+
43+
// Assert
44+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
45+
46+
var responseString = await response.Content.ReadAsStringAsync();
47+
var contactos = JsonSerializer.Deserialize<List<string>>(responseString, new JsonSerializerOptions
48+
{
49+
PropertyNameCaseInsensitive = true
50+
});
51+
52+
Assert.NotNull(contactos);
53+
Assert.Equal(3, contactos.Count);
54+
Assert.Contains("Amin Espinoza", contactos);
55+
Assert.Contains("Oscar Barajas", contactos);
56+
Assert.Contains("Pepe Rodelo", contactos);
57+
}
58+
}
59+
```
60+
61+
Modifica el acceso a tus variables de ambiente.
62+
63+
```csharp
64+
o.ConnectionString = builder.Configuration["AzureMonitor:ConnectionString"]
65+
?? Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
66+
```

src/ContactosAPI/ContactosAPI.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.3.0" />
1011
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.12" />
12+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
13+
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
14+
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.1" />
1115
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
1216
</ItemGroup>
1317

src/ContactosAPI/Program.cs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
1+
using OpenTelemetry.Resources;
2+
using OpenTelemetry.Trace;
3+
using OpenTelemetry.Metrics;
4+
using Azure.Monitor.OpenTelemetry.Exporter;
5+
16
var builder = WebApplication.CreateBuilder(args);
27

3-
// Add services to the container.
4-
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
8+
builder.Services.AddOpenTelemetry()
9+
.WithMetrics(metricsBuilder =>
10+
{
11+
metricsBuilder
12+
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ApiContactos"))
13+
.AddAspNetCoreInstrumentation()
14+
.AddHttpClientInstrumentation()
15+
.AddAzureMonitorMetricExporter(o =>
16+
{
17+
o.ConnectionString = builder.Configuration["AzureMonitor:ConnectionString"]
18+
?? Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
19+
});
20+
})
21+
.WithTracing(tracingBuilder =>
22+
{
23+
tracingBuilder
24+
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ApiContactos"))
25+
.AddAspNetCoreInstrumentation()
26+
.AddHttpClientInstrumentation()
27+
.AddAzureMonitorTraceExporter(o =>
28+
{
29+
o.ConnectionString = builder.Configuration["AzureMonitor:ConnectionString"]
30+
?? Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
31+
});
32+
});
33+
534
builder.Services.AddEndpointsApiExplorer();
635
builder.Services.AddSwaggerGen();
736

837
var app = builder.Build();
9-
1038
app.UseSwagger();
1139
app.UseSwaggerUI();
1240
app.UseHttpsRedirection();
@@ -38,4 +66,4 @@ record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
3866
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
3967
}
4068

41-
public partial class Program { }
69+
public partial class Program { }

0 commit comments

Comments
 (0)