Skip to content
This repository has been archived by the owner on Jul 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from fbeltrao/initial-version
Browse files Browse the repository at this point in the history
Initial version
  • Loading branch information
SergeyKanzhelev authored Feb 21, 2020
2 parents 3137657 + c6e0e95 commit 13c48d0
Show file tree
Hide file tree
Showing 73 changed files with 3,240 additions and 10 deletions.
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,5 @@ MigrationBackup/

# Ionide (cross platform F# VS Code tools) working folder
.ionide/

.env
57 changes: 57 additions & 0 deletions DotNetObservabilitySample.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29613.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.RabbitMQProcessor", "src\Sample.RabbitMQProcessor\Sample.RabbitMQProcessor.csproj", "{B2900141-0E8C-46EE-908E-F98218960804}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Common", "src\Sample.Common\Sample.Common.csproj", "{39CCAC82-947E-4229-85C1-C34D3B569BE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.TimeApi", "src\Sample.TimeApi\Sample.TimeApi.csproj", "{883EB697-F742-422B-ADC9-3A89C00B5424}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.MainApi", "src\Sample.MainApi\Sample.MainApi.csproj", "{4EA49E72-7529-4CFD-8942-0086BC0E43F4}"
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{D9851614-526F-43C3-B9E2-F93B0F0E1448}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.RabbitMQCollector", "src\Sample.RabbitMQCollector\Sample.RabbitMQCollector.csproj", "{7A7BF83E-DA37-47FC-83CF-104D3EA9B36F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B2900141-0E8C-46EE-908E-F98218960804}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2900141-0E8C-46EE-908E-F98218960804}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2900141-0E8C-46EE-908E-F98218960804}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2900141-0E8C-46EE-908E-F98218960804}.Release|Any CPU.Build.0 = Release|Any CPU
{39CCAC82-947E-4229-85C1-C34D3B569BE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39CCAC82-947E-4229-85C1-C34D3B569BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39CCAC82-947E-4229-85C1-C34D3B569BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39CCAC82-947E-4229-85C1-C34D3B569BE4}.Release|Any CPU.Build.0 = Release|Any CPU
{883EB697-F742-422B-ADC9-3A89C00B5424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{883EB697-F742-422B-ADC9-3A89C00B5424}.Debug|Any CPU.Build.0 = Debug|Any CPU
{883EB697-F742-422B-ADC9-3A89C00B5424}.Release|Any CPU.ActiveCfg = Release|Any CPU
{883EB697-F742-422B-ADC9-3A89C00B5424}.Release|Any CPU.Build.0 = Release|Any CPU
{4EA49E72-7529-4CFD-8942-0086BC0E43F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4EA49E72-7529-4CFD-8942-0086BC0E43F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EA49E72-7529-4CFD-8942-0086BC0E43F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EA49E72-7529-4CFD-8942-0086BC0E43F4}.Release|Any CPU.Build.0 = Release|Any CPU
{D9851614-526F-43C3-B9E2-F93B0F0E1448}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9851614-526F-43C3-B9E2-F93B0F0E1448}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9851614-526F-43C3-B9E2-F93B0F0E1448}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9851614-526F-43C3-B9E2-F93B0F0E1448}.Release|Any CPU.Build.0 = Release|Any CPU
{7A7BF83E-DA37-47FC-83CF-104D3EA9B36F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A7BF83E-DA37-47FC-83CF-104D3EA9B36F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A7BF83E-DA37-47FC-83CF-104D3EA9B36F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A7BF83E-DA37-47FC-83CF-104D3EA9B36F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5170C652-61A9-4542-954E-246518C6C40B}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
version = 0.2
EndGlobalSection
EndGlobal
7 changes: 7 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet" value="https://www.myget.org/F/opentelemetry/api/v3/index.json" />
</packageSources>
<disabledPackageSources />
</configuration>
147 changes: 137 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ languages:
- csharp
products:
- dotnet
description: "Add 150 character max description"
description: "Adding observability to ASP.NET Core application using OpenTelemetry and Application Insights"
urlFragment: "update-this-to-unique-url-stub"
---

Expand All @@ -18,15 +18,16 @@ Guidance on onboarding samples to docs.microsoft.com/samples: https://review.doc
Taxonomies for products and languages: https://review.docs.microsoft.com/new-hope/information-architecture/metadata/taxonomies?branch=master
-->

Give a short description for your sample here. What does it do and why is it important?
This sample application takes a look at current options to implement observability in a ASP.NET Core. It uses OpenTelemetry and Application Insights SDKs to illustrate how logging, tracing and metrics to monitor an application. It contains a distributed transaction example trace including REST, dependencies and RabbitMQ processing.

## Contents
![Sample application](./media/sample-app-overview.png)

Outline the file contents of the repository. It helps users navigate the codebase, build configuration and any related assets.
## Contents

| File/folder | Description |
|-------------------|--------------------------------------------|
| `src` | Sample source code. |
| `quickstart` | Quick start using docker-compose and pre-built images. |
| `.gitignore` | Define what to ignore at commit time. |
| `CHANGELOG.md` | List of changes to the sample. |
| `CONTRIBUTING.md` | Guidelines for contributing to the sample. |
Expand All @@ -35,19 +36,145 @@ Outline the file contents of the repository. It helps users navigate the codebas

## Prerequisites

Outline the required components and tools that a user might need to have on their machine in order to run the sample. This can be anything from frameworks, SDKs, OS versions or IDE releases.
Sample application can be executed in two ways:

- Using docker-compose. It is a great way to get started.
- Downloading source code and running it locally. Using Visual Studio or another IDE. In this case the .NET Core 3.1 SDK is required. To use Jaeger and Prometheues Docker is recommended.

## Setup - Quickstart with docker-compose

To run the application using pre-built images and docker-compose following the guideline below:

### Using OpenTelemetry

1. Clone this repository
1. Open terminal under `quickstart/sample`
1. Execute `docker-compose up` (-d if you don't wish to see console logs)
1. View traces in [Jaeger](http://localhost:16686/)
1. View metrics by searching for "Enqueued_Item" in [Prometheus](http://localhost:9090)
1. Build dashboards in [Grafana](http://localhost:3000/) (admin/password1)

### Using Application Insights SDK

1. Clone this repository
1. Open terminal under `quickstart/sample`
1. Create file `quickstart/sample/.env` with following content:

```env
USE_APPLICATIONINSIGHTS=true
USE_OPENTELEMETRY=false
AI_INSTRUMENTATIONKEY=<ENTER-APPLICATION-INSIGHTS-INSTRUMENTATION-KEY>
```

4. Execute `docker-compose up` (-d if you don't wish to see console logs)
5. View logs, traces and metrics in Azure Portal Application Insights

## Setup - Compile/debug locally

Clone or download the sample from this repository, then open the solution found in root folder using your favorite IDE.

Before running ensure the following dependencies are available:

- SQL Server is available at `server=localhost;user id=sa;password=Pass@Word1;`<br/>
A way to accomplish it is to run as a linux docker container:

```bash
docker run --name sqlserver -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Pass@Word1" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-GA-ubuntu-16.04
```

- When using OpenTelemetry, ensure Jaeger is running locally

```bash
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 9411:9411 \
jaegertracing/all-in-one
```

- When using OpenTelemetry, in order to visualize metrics ensure Grafana and Prometheus are running locally. A docker-compose file is ready to run under `quickstart/prometheus-grafana`. Open terminal in the mentioned folder and execute `docker-compose up -d`.<br/>To visualize it, open Grafana on your browser at [http://localhost:3000](http://localhost:3000) (credentials are admin/password1). Next, add Prometheus as data source (URL is http://prometheus:9090).

- When using Application Insights, ensure the instrumentation key is set (a simpler way to provide settings to all applications is to create file appsettings.Development.json in folder ./shared):

```json
{
"SampleApp": {
"UseApplicationInsights": "true",
"UseOpenTelemetry": "false",
"ApplicationInsightsInstrumentationKey": "<Instrumentation key>"
}
}
```

## Setup
#### Generating load

Explain how to prepare the sample once the user clones or downloads the repository. The section should outline every step necessary to install dependencies and set up any settings (for example, API keys and output folders).
The application will only collect data once it starts to receive load. To generate load use the following scripts:

## Running the sample
Enqueuing from "WebSiteA" every 2 seconds

Outline step-by-step instructions to execute the sample and see its output. Include steps for executing the sample from the IDE, starting specific services in the Azure portal or anything related to the overall launch of the code.
```cmd
watch -n 2 curl --request GET http://localhost:5001/api/enqueue/WebSiteA
```

```powershell
while (1) {Invoke-WebRequest -Uri http://localhost:5001/api/enqueue/WebSiteA; sleep 2}
```

Enqueuing from "WebSiteB" every 10 seconds

```cmd
watch -n 10 curl --request GET http://localhost:5001/api/enqueue/WebSiteB
```

```powershell
while (1) {Invoke-WebRequest -Uri http://localhost:5001/api/enqueue/WebSiteB; sleep 10}
```

Enqueuing from "WebSiteC" every 30 seconds

```cmd
watch -n 30 curl --request GET http://localhost:5001/api/enqueue/WebSiteC
```

```powershell
while (1) {Invoke-WebRequest -Uri http://localhost:5001/api/enqueue/WebSiteC; sleep 30}
```

## Key concepts

Provide users with more context on the tools and services used in the sample. Explain some of the code that is being used and how services interact with each other.
Goal of the sample application is to demonstrate ways you can add the 3 observability pillars to your ASP.NET Core application:

### Logging

Collects information about events happening in the system, helping the team analyze unexpected application behavior. Searching through the logs of suspect services can provide the necessary hint to identify the problem root cause: service is throwing out of memory exceptions, app configuration does not reflect expected values, calls to external service have incorrect address, calls to external service returns unexpected results, incoming requests have unexpected input, etc.

Logging with Application Insights:

![Logging](./media/ai-search-logs.png)

### Traces

Collects information in order to create an end-to-end view of how transactions are executed in a distributed system. A trace is like a stack trace spanning multiple applications. Once a problem has been recognized, traces are a good starting point in identifying the source in distributed operations: calls from service A to B are taking longer than normal, service payment calls are failing, etc.

Traces with Jaeger:

![Jaeger Tracing](./media/jaeger-tracing.png)

Traces with Application Insights:

![Application Insights Tracing](./media/ai-tracing.png)

### Metrics

Provide a near real-time indication of how the system is running. Can be leveraged to build alerts, allowing proactive reactance to unexpected values. As opposed to logs and traces, the amount of data collected using metrics remains constant as the system load increases. Application problems are often first detected through abnormal metric values: CPU usage is higher than before, payment error count is spiking, queued item count keeps growing.

Metrics with
![Grafane/Prometheus Metrics](./media/grafana-metrics.png)

## Contributing

Expand Down
18 changes: 18 additions & 0 deletions docker-compose.dcproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
<PropertyGroup Label="Globals">
<ProjectVersion>2.1</ProjectVersion>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectGuid>d9851614-526f-43c3-b9e2-f93b0f0e1448</ProjectGuid>
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
<DockerServiceUrl>{Scheme}://localhost:{ServicePort}/api/dbtime</DockerServiceUrl>
<DockerServiceName>sample.mainapi</DockerServiceName>
</PropertyGroup>
<ItemGroup>
<None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.yml" />
<None Include=".dockerignore" />
</ItemGroup>
</Project>
15 changes: 15 additions & 0 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.4'

services:
sample.mainapi:
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "5001:80"

sample.timeapi:
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "5002:80"

Loading

0 comments on commit 13c48d0

Please sign in to comment.