mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-13 04:06:07 +08:00
Compare commits
No commits in common. "main" and "v1.5.0" have entirely different histories.
@ -1,3 +0,0 @@
|
||||
{
|
||||
"appHostPath": "../src/Aspire/src/AppHost/AppHost.csproj"
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-outdated-tool": {
|
||||
"version": "4.6.9",
|
||||
"commands": [
|
||||
"dotnet-outdated"
|
||||
]
|
||||
},
|
||||
"dotnet-ef": {
|
||||
"version": "10.0.3",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
},
|
||||
"aspire.cli": {
|
||||
"version": "13.1.1",
|
||||
"commands": [
|
||||
"aspire"
|
||||
]
|
||||
},
|
||||
"csharpier": {
|
||||
"version": "0.30.6",
|
||||
"commands": [
|
||||
"dotnet-csharpier"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
1390
.editorconfig
1390
.editorconfig
File diff suppressed because it is too large
Load Diff
64
.gitattributes
vendored
64
.gitattributes
vendored
@ -1,64 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
*.sh text eol=lf
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
18
.github/actions/build/action.yml
vendored
18
.github/actions/build/action.yml
vendored
@ -25,16 +25,14 @@ runs:
|
||||
# https://devblogs.microsoft.com/dotnet/dotnet-loves-github-actions/
|
||||
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net#caching-dependencies
|
||||
- name: Cache NuGet Packages
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
if: success()
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-dotnet-nuget
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '10.x.x'
|
||||
uses: actions/setup-dotnet@v3
|
||||
|
||||
# https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools
|
||||
- name: Restore .NET Tools
|
||||
@ -49,18 +47,6 @@ runs:
|
||||
# restore root solution
|
||||
run: dotnet restore
|
||||
|
||||
# npm install, runs `prepare` script automatically in the initialize step
|
||||
- name: Install NPM Dependencies
|
||||
shell: bash
|
||||
if: success()
|
||||
run: npm install
|
||||
|
||||
- name: Format Service
|
||||
shell: bash
|
||||
if: ${{ success()}}
|
||||
run: |
|
||||
npm run ci-format
|
||||
|
||||
- name: Build Service
|
||||
shell: bash
|
||||
if: ${{ success()}}
|
||||
|
||||
39
.github/pull_request_template.md
vendored
Normal file
39
.github/pull_request_template.md
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<!-- Type of change
|
||||
Please label this PR with one of the existing labels, depending on the scope of your change.
|
||||
-->
|
||||
|
||||
## What does this PR do?
|
||||
|
||||
<!-- Mandatory
|
||||
Explain here the changes you made on the PR. Please explain the WHAT: patterns used, algorithms implemented, design architecture, etc.
|
||||
-->
|
||||
|
||||
## Why is it important?
|
||||
|
||||
<!-- Mandatory
|
||||
Explain here the WHY, or the rationale / motivation for the changes.
|
||||
-->
|
||||
|
||||
## Related issues
|
||||
|
||||
<!-- Recommended
|
||||
Link related issues below. Insert the issue link or reference after the word "Closes" if merging this should automatically close it.
|
||||
|
||||
- Closes #123
|
||||
- Relates #123
|
||||
- Requires #123
|
||||
- Supersedes #123
|
||||
-->
|
||||
-
|
||||
|
||||
<!-- Recommended
|
||||
## How to test this PR
|
||||
|
||||
Explain here how this PR will be tested by the reviewer: commands, dependencies, steps, etc.
|
||||
-->
|
||||
|
||||
<!-- Optional
|
||||
## Follow-ups
|
||||
|
||||
Add here any thought that you consider could be identified as an actionable step once this PR is merged.
|
||||
-->
|
||||
6
.github/release-drafter.yml
vendored
6
.github/release-drafter.yml
vendored
@ -28,7 +28,7 @@ categories:
|
||||
- title: 👷 CI
|
||||
labels:
|
||||
- ci
|
||||
- title: ♻️ Refactor
|
||||
- title: ♻️ Changes
|
||||
labels:
|
||||
- changed
|
||||
- enhancement
|
||||
@ -91,7 +91,9 @@ autolabeler:
|
||||
body:
|
||||
- '/JIRA-[0-9]{1,4}/'
|
||||
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-template: '- $TITLE (#$NUMBER)'
|
||||
exclude-contributors:
|
||||
- 'meysamhadeli'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
|
||||
26
.github/workflows/ci.yml
vendored
26
.github/workflows/ci.yml
vendored
@ -2,25 +2,25 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main"]
|
||||
branches: [ "main" , "develop" ]
|
||||
paths-ignore:
|
||||
- "README.md"
|
||||
pull_request:
|
||||
branches: [ "main"]
|
||||
branches: [ "main" , "develop" ]
|
||||
paths-ignore:
|
||||
- "README.md"
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build and Test Flight Microservice
|
||||
- name: Build and Test Flight
|
||||
uses: ./.github/actions/build-test
|
||||
if: success()
|
||||
id: build-test-flight-step
|
||||
@ -35,7 +35,7 @@ jobs:
|
||||
service-name: 'Flight'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and Test Identity Microservice
|
||||
- name: Build and Test Identity
|
||||
uses: ./.github/actions/build-test
|
||||
if: success()
|
||||
id: build-test-identity-step
|
||||
@ -50,7 +50,7 @@ jobs:
|
||||
service-name: 'Identity'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and Test Passenger Microservice
|
||||
- name: Build and Test Passenger
|
||||
uses: ./.github/actions/build-test
|
||||
if: success()
|
||||
id: build-test-passenger-step
|
||||
@ -65,7 +65,7 @@ jobs:
|
||||
service-name: 'Passenger'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and Test Booking Microservice
|
||||
- name: Build and Test Booking
|
||||
uses: ./.github/actions/build-test
|
||||
if: success()
|
||||
id: build-test-booking-step
|
||||
@ -91,7 +91,7 @@ jobs:
|
||||
run:
|
||||
echo "Release version is:" ${{ steps.last_release.outputs.tag_name }}
|
||||
|
||||
- name: Build and Publish Identity Microservice to Docker
|
||||
- name: Build and Publish Identity to Docker
|
||||
if: ${{ github.ref == 'refs/heads/main' && success() }}
|
||||
uses: ./.github/actions/docker-build-publish
|
||||
with:
|
||||
@ -101,7 +101,7 @@ jobs:
|
||||
dockerfile-path: 'src/Services/Identity/Dockerfile'
|
||||
image-name: 'booking-microservices-identity'
|
||||
|
||||
- name: Build and Publish Flight Microservice to Docker
|
||||
- name: Build and Publish Flight to Docker
|
||||
if: ${{ github.ref == 'refs/heads/main' && success() }}
|
||||
uses: ./.github/actions/docker-build-publish
|
||||
with:
|
||||
@ -111,7 +111,7 @@ jobs:
|
||||
dockerfile-path: 'src/Services/Flight/Dockerfile'
|
||||
image-name: 'booking-microservices-flight'
|
||||
|
||||
- name: Build and Publish Passenger Microservice to Docker
|
||||
- name: Build and Publish Passenger to Docker
|
||||
if: ${{ github.ref == 'refs/heads/main' && success() }}
|
||||
uses: ./.github/actions/docker-build-publish
|
||||
with:
|
||||
@ -121,7 +121,7 @@ jobs:
|
||||
dockerfile-path: 'src/Services/Passenger/Dockerfile'
|
||||
image-name: 'booking-microservices-passenger'
|
||||
|
||||
- name: Build and Publish Booking Microservice to Docker
|
||||
- name: Build and Publish Booking to Docker
|
||||
if: ${{ github.ref == 'refs/heads/main' && success() }}
|
||||
uses: ./.github/actions/docker-build-publish
|
||||
with:
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -435,8 +435,4 @@ fabric.properties
|
||||
|
||||
*.jwk
|
||||
|
||||
# Monitoring
|
||||
**/grafana-data
|
||||
|
||||
# EventStore
|
||||
**/eventstore
|
||||
**/keys
|
||||
1
.gitpod.Dockerfile
vendored
Normal file
1
.gitpod.Dockerfile
vendored
Normal file
@ -0,0 +1 @@
|
||||
FROM gitpod/workspace-dotnet:latest
|
||||
37
.gitpod.yml
Normal file
37
.gitpod.yml
Normal file
@ -0,0 +1,37 @@
|
||||
# https://github.com/gitpod-samples/template-dotnet-core-cli-csharp
|
||||
# https://www.gitpod.io/docs/introduction/languages/dotnet
|
||||
# https://github.com/gitpod-samples/template-docker-compose
|
||||
# https://www.gitpod.io/docs/references/gitpod-yml
|
||||
# https://www.gitpod.io/docs/configure
|
||||
# https://www.gitpod.io/docs/configure/workspaces/ports
|
||||
|
||||
image:
|
||||
file: .gitpod.Dockerfile
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- muhammad-sammy.csharp
|
||||
- editorconfig.editorconfig
|
||||
- vivaxy.vscode-conventional-commits
|
||||
- humao.rest-client
|
||||
- ms-azuretools.vscode-docker
|
||||
- donjayamanne.githistory
|
||||
- pkief.material-icon-theme
|
||||
- emmanuelbeziat.vscode-great-icons
|
||||
|
||||
# https://www.gitpod.io/docs/configure/workspaces/tasks#execution-order
|
||||
# https://www.gitpod.io/docs/configure/projects/prebuilds
|
||||
tasks:
|
||||
- name: Init Docker-Compose
|
||||
# https://www.gitpod.io/docs/configure/projects/prebuilds
|
||||
# We load docker on pre-build for increasing speed
|
||||
init: |
|
||||
docker-compose pull
|
||||
docker-compose -f ./deployments/docker-compose/infrastracture.yaml up -d
|
||||
- name: Setup kubectl
|
||||
command: bash $GITPOD_REPO_ROOT/scripts/setup_kubectl_gitpod.sh
|
||||
- name: Restore & Build
|
||||
init: |
|
||||
dotnet dev-certs https
|
||||
dotnet restore
|
||||
dotnet build
|
||||
@ -1 +0,0 @@
|
||||
npx --no -- commitlint --edit ${1}
|
||||
@ -1,2 +0,0 @@
|
||||
npm run format
|
||||
npm run ci-format
|
||||
@ -1,26 +0,0 @@
|
||||
## Contribution
|
||||
|
||||
This is great that you'd like to contribute to this project. All change requests should go through the steps described below.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
**Please, make sure you open an issue before starting with a Pull Request, unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes.
|
||||
|
||||
## Conventional commits
|
||||
|
||||
Our repository follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NuGet is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/).
|
||||
|
||||
Pull requests should have a title that follows the specification, otherwise, merging is blocked. If you are not familiar with the specification simply ask maintainers to modify. You can also use this cheatsheet if you want:
|
||||
|
||||
- `fix: ` prefix in the title indicates that PR is a bug fix and PATCH release must be triggered.
|
||||
- `feat: ` prefix in the title indicates that PR is a feature and MINOR release must be triggered.
|
||||
- `docs: ` prefix in the title indicates that PR is only related to the documentation and there is no need to trigger release.
|
||||
- `chore: ` prefix in the title indicates that PR is only related to cleanup in the project and there is no need to trigger release.
|
||||
- `test: ` prefix in the title indicates that PR is only related to tests and there is no need to trigger release.
|
||||
- `refactor: ` prefix in the title indicates that PR is only related to refactoring and there is no need to trigger release.
|
||||
|
||||
## Resources
|
||||
|
||||
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
|
||||
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
|
||||
- [GitHub Help](https://help.github.com)
|
||||
@ -1,48 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="all" Version="1.1.118">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Meziantou.Analyzer" PrivateAssets="all" Version="2.0.299">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers" PrivateAssets="all" Version="4.15.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" PrivateAssets="all" Version="4.15.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Formatting.Analyzers" PrivateAssets="all" Version="4.15.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" PrivateAssets="all" Version="17.14.15">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="AsyncAwaitBestPractices" PrivateAssets="all" Version="10.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CSharpGuidelinesAnalyzer" PrivateAssets="all" Version="3.8.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="7.0.0" />
|
||||
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
|
||||
<GlobalPackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
|
||||
<AnalysisLevel>latest-Recommended</AnalysisLevel>
|
||||
<AnalysisMode>Recommended</AnalysisMode>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
232
README.md
232
README.md
@ -5,125 +5,88 @@
|
||||
<a href="https://github.com/meysamhadeli/booking-microservices/blob/main/LICENSE"><img alt="build-status" src="https://img.shields.io/github/license/meysamhadeli/booking-microservices?color=%234275f5&style=flat-square"/></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
> **The main idea of creating this project is implementing an infrastructure for up and running distributed system with the latest technology and architecture like Vertical Slice Architecture, Event Sourcing, CQRS, DDD, gRpc, MongoDB, RabbitMq, Masstransit in .Net, and we will not deal mainly with business.** 🚀
|
||||
|
||||
> 🚀 **A practical microservices with the latest technologies and architectures like Vertical Slice Architecture, Event Sourcing, CQRS, DDD, gRpc, MongoDB, RabbitMq, Masstransit, and Aspire in .Net 10.**
|
||||
|
||||
## You can find other version of this project here:
|
||||
- [Booking with Modular Monolith Architecture](https://github.com/meysamhadeli/booking-modular-monolith)
|
||||
- [Booking with Monolith Architecture](https://github.com/meysamhadeli/booking-monolith)
|
||||
|
||||
<div>
|
||||
<a href='https://codespaces.new/meysamhadeli/booking-microservices?quickstart=1'><img alt='Open in GitHub Codespaces' src='https://github.com/codespaces/badge.svg'></a>
|
||||
</div>
|
||||
<a href="https://gitpod.io/#https://github.com/meysamhadeli/booking-microservices"><img alt="Open in Gitpod" src="https://gitpod.io/button/open-in-gitpod.svg"/></a>
|
||||
|
||||
# Table of Contents
|
||||
|
||||
- [The Goals of This Project](#the-goals-of-this-project)
|
||||
- [Plan](#plan)
|
||||
- [Technologies - Libraries](#technologies---libraries)
|
||||
- [Key Features](#key-features)
|
||||
- [When to Use](#when-to-use)
|
||||
- [Challenges](#challenges)
|
||||
- [The Domain and Bounded Context - Service Boundary](#the-domain-and-bounded-context---service-boundary)
|
||||
- [Structure of Project](#structure-of-project)
|
||||
- [Development Setup](#development-setup)
|
||||
- [Dotnet Tools Packages](#dotnet-tools-packages)
|
||||
- [Husky](#husky)
|
||||
- [Upgrade Nuget Packages](#upgrade-nuget-packages)
|
||||
- [How to Run](#how-to-run)
|
||||
- [Config Certificate](#config-certificate)
|
||||
- [Aspire](#aspire)
|
||||
- [Docker Compose](#docker-compose)
|
||||
- [Kubernetes](#kubernetes)
|
||||
- [Build](#build)
|
||||
- [Run](#run)
|
||||
- [Test](#test)
|
||||
- [Documentation Apis](#documentation-apis)
|
||||
- [Support](#support)
|
||||
- [Contribution](#contribution)
|
||||
|
||||
|
||||
## The Goals of This Project
|
||||
|
||||
- :sparkle: Using `Vertical Slice Architecture` for `architecture` level.
|
||||
- :sparkle: Using `Domain Driven Design (DDD)` to implement all `business logic`.
|
||||
- :sparkle: Using `Rabbitmq` on top of `Masstransit` for `Event Driven Architecture`.
|
||||
- :sparkle: Using `gRPC` for `internal communication`.
|
||||
- :sparkle: Using `Vertical Slice Architecture` for architecture level.
|
||||
- :sparkle: Using `Domain Driven Design (DDD)` to implement all business processes in microservices.
|
||||
- :sparkle: Using `Rabbitmq` on top of `Masstransit` for `Event Driven Architecture` between our microservices.
|
||||
- :sparkle: Using `gRPC` for internal communication between our microservices.
|
||||
- :sparkle: Using `CQRS` implementation with `MediatR` library.
|
||||
- :sparkle: Using `Postgres` for `write side` database.
|
||||
- :sparkle: Using `MongoDB` for `read side` database.
|
||||
- :sparkle: Using `Event Store` for `write side` of Booking Microservice/Module to store all `historical change` of aggregate.
|
||||
- :sparkle: Using `Inbox Pattern` for ensuring message idempotency for receiver and `Exactly once Delivery`.
|
||||
- :sparkle: Using `Outbox Pattern` for ensuring no message is lost and there is at `At Least One Delivery`.
|
||||
- :sparkle: Using `Unit Testing` for testing small units and mocking our dependencies with `Nsubstitute`.
|
||||
- :sparkle: Using `End-To-End Testing` and `Integration Testing` for testing `features` with all dependencies using `testcontainers`.
|
||||
- :sparkle: Using `Postgres` for `write side` of some microservices.
|
||||
- :sparkle: Using `MongoDB` for `read side` of some microservices.
|
||||
- :sparkle: Using `Event Store` for `write side` of Booking-Microservice to store all `historical state` of aggregate.
|
||||
- :sparkle: Using `Inbox Pattern` for ensuring message idempotency for receiver and `Exactly once Delivery`.
|
||||
- :sparkle: Using `Outbox Pattern` for ensuring no message is lost and there is at `Least One Delivery`.
|
||||
- :sparkle: Using `Unit Testing`, `Integration Testing`, `End To End Testing` for testing level.
|
||||
- :sparkle: Using `Fluent Validation` and a `Validation Pipeline Behaviour` on top of `MediatR`.
|
||||
- :sparkle: Using `Minimal API` for all endpoints.
|
||||
- :sparkle: Using `AspNetCore OpenApi` for `generating` built-in support `OpenAPI documentation` in ASP.NET Core.
|
||||
- :sparkle: Using `Health Check` for `reporting` the `health` of app infrastructure components.
|
||||
- :sparkle: Using `Health Check` for reporting the health of app infrastructure components.
|
||||
- :sparkle: Using `Docker-Compose` and `Kubernetes` for our deployment mechanism.
|
||||
- :sparkle: Using `Kibana` on top of `Serilog` for `logging`.
|
||||
- :sparkle: Using `OpenTelemetry` for distributed tracing on top of `Jaeger`.
|
||||
- :sparkle: Using `OpenTelemetry` for monitoring on top of `Prometheus` and `Grafana`.
|
||||
- :sparkle: Using `OpenTelemetry` for distributed tracing.
|
||||
- :sparkle: Using `IdentityServer` for authentication and authorization base on `OpenID-Connect` and `OAuth2`.
|
||||
- :sparkle: Using `Yarp` as a microservices `gateway`.
|
||||
- :sparkle: Using `Kubernetes` to achieve efficient `scaling` and ensure `high availability` for each of our microservices.
|
||||
- :sparkle: Using `Nginx Ingress Controller` for `load balancing` between our microservices top of `Kubernetes`.
|
||||
- :sparkle: Using `cert-manager` to Configure `TLS` in `kubernetes cluster`.
|
||||
- :sparkle: Using `Aspire` for `service discovery`, `observability`, and `local orchestration` of microservices.
|
||||
- :sparkle: Using `Yarp` as a microservices gateway.
|
||||
|
||||
## Plan
|
||||
|
||||
> 🌀This project is a work in progress, new features will be added over time.🌀
|
||||
|
||||
I will try to register future goals and additions in the [Issues](https://github.com/meysamhadeli/booking-microservices/issues) section of this repository.
|
||||
|
||||
High-level plan is represented in the table
|
||||
|
||||
| Feature | Status |
|
||||
| ----------------- | -------------- |
|
||||
| API Gateway | Completed ✔️ |
|
||||
| Identity Service | Completed ✔️ |
|
||||
| Flight Service | Completed ✔️ |
|
||||
| Passenger Service | Completed ✔️ |
|
||||
| Booking Service | Completed ✔️ |
|
||||
| Building Blocks | Completed ✔️ |
|
||||
|
||||
## Technologies - Libraries
|
||||
|
||||
- ✔️ **[`.NET 10`](https://github.com/dotnet/aspnetcore)** - .NET Framework and .NET Core, including ASP.NET and ASP.NET Core.
|
||||
- ✔️ **[`MVC Versioning API`](https://github.com/microsoft/aspnet-api-versioning)** - Set of libraries which add service API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core.
|
||||
- ✔️ **[`EF Core`](https://github.com/dotnet/efcore)** - Modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
|
||||
- ✔️ **[`AspNetCore OpenApi`](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi)** - Provides built-in support for OpenAPI document generation in ASP.NET Core.
|
||||
- ✔️ **[`.NET 7`](https://dotnet.microsoft.com/download)** - .NET Framework and .NET Core, including ASP.NET and ASP.NET Core
|
||||
- ✔️ **[`MVC Versioning API`](https://github.com/microsoft/aspnet-api-versioning)** - Set of libraries which add service API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core
|
||||
- ✔️ **[`EF Core`](https://github.com/dotnet/efcore)** - Modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations
|
||||
- ✔️ **[`Masstransit`](https://github.com/MassTransit/MassTransit)** - Distributed Application Framework for .NET.
|
||||
- ✔️ **[`MediatR`](https://github.com/jbogard/MediatR)** - Simple, unambitious mediator implementation in .NET.
|
||||
- ✔️ **[`FluentValidation`](https://github.com/FluentValidation/FluentValidation)** - Popular .NET validation library for building strongly-typed validation rules.
|
||||
- ✔️ **[`Scalar`](https://github.com/scalar/scalar/tree/main/packages/scalar.aspnetcore)** - Scalar provides an easy way to render beautiful API references based on OpenAPI/Swagger documents.
|
||||
- ✔️ **[`Swagger UI`](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)** - Swagger tools for documenting API's built on ASP.NET Core.
|
||||
- ✔️ **[`FluentValidation`](https://github.com/FluentValidation/FluentValidation)** - Popular .NET validation library for building strongly-typed validation rules
|
||||
- ✔️ **[`Swagger & Swagger UI`](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)** - Swagger tools for documenting API's built on ASP.NET Core
|
||||
- ✔️ **[`Serilog`](https://github.com/serilog/serilog)** - Simple .NET logging with fully-structured events
|
||||
- ✔️ **[`Polly`](https://github.com/App-vNext/Polly)** - Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.
|
||||
- ✔️ **[`Polly`](https://github.com/App-vNext/Polly)** - Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner
|
||||
- ✔️ **[`Scrutor`](https://github.com/khellang/Scrutor)** - Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection
|
||||
- ✔️ **[`Opentelemetry-dotnet`](https://github.com/open-telemetry/opentelemetry-dotnet)** - The OpenTelemetry .NET Client
|
||||
- ✔️ **[`DuendeSoftware IdentityServer`](https://github.com/DuendeSoftware/IdentityServer)** - The most flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core.
|
||||
- ✔️ **[`DuendeSoftware IdentityServer`](https://github.com/DuendeSoftware/IdentityServer)** - The most flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core
|
||||
- ✔️ **[`EasyCaching`](https://github.com/dotnetcore/EasyCaching)** - Open source caching library that contains basic usages and some advanced usages of caching which can help us to handle caching more easier.
|
||||
- ✔️ **[`Mapster`](https://github.com/MapsterMapper/Mapster)** - Convention-based object-object mapper in .NET.
|
||||
- ✔️ **[`Hellang.Middleware.ProblemDetails`](https://github.com/khellang/Middleware/tree/master/src/ProblemDetails)** - A middleware for handling exception in .Net Core.
|
||||
- ✔️ **[`NewId`](https://github.com/phatboyg/NewId)** - NewId can be used as an embedded unique ID generator that produces 128 bit (16 bytes) sequential IDs.
|
||||
- ✔️ **[`Yarp`](https://github.com/microsoft/reverse-proxy)** - Reverse proxy toolkit for building fast proxy servers in .NET.
|
||||
- ✔️ **[`Tye`](https://github.com/dotnet/tye)** - Developer tool that makes developing, testing, and deploying microservices and distributed applications easier.
|
||||
- ✔️ **[`Hellang.Middleware.ProblemDetails`](https://github.com/khellang/Middleware/tree/master/src/ProblemDetails)** - A middleware for handling exception in .Net Core
|
||||
- ✔️ **[`IdGen`](https://github.com/RobThree/IdGen)** - Twitter Snowflake-alike ID generator for .Net
|
||||
- ✔️ **[`Yarp`](https://github.com/microsoft/reverse-proxy)** - Reverse proxy toolkit for building fast proxy servers in .NET
|
||||
- ✔️ **[`Tye`](https://github.com/dotnet/tye)** - Developer tool that makes developing, testing, and deploying microservices and distributed applications easier
|
||||
- ✔️ **[`gRPC-dotnet`](https://github.com/grpc/grpc-dotnet)** - gRPC functionality for .NET.
|
||||
- ✔️ **[`EventStore`](https://github.com/EventStore/EventStore)** - The open-source, functional database with Complex Event Processing.
|
||||
- ✔️ **[`MongoDB.Driver`](https://github.com/mongodb/mongo-csharp-driver)** - .NET Driver for MongoDB.
|
||||
- ✔️ **[`xUnit.net`](https://github.com/xunit/xunit)** - A free, open source, community-focused unit testing tool for the .NET Framework.
|
||||
- ✔️ **[`Respawn`](https://github.com/jbogard/Respawn)** - Respawn is a small utility to help in resetting test databases to a clean state.
|
||||
- ✔️ **[`Testcontainers`](https://github.com/testcontainers/testcontainers-dotnet)** - Testcontainers for .NET is a library to support tests with throwaway instances of Docker containers.
|
||||
- ✔️ **[`K6`](https://github.com/grafana/k6)** - Modern load testing for developers and testers in the DevOps era.
|
||||
- ✔️ **[`Aspire`](https://github.com/dotnet/aspire)** - .NET stack for building and orchestrating observable, distributed cloud-native applications.
|
||||
|
||||
|
||||
## Key Features
|
||||
1. **Independent Services**: Each service is a separate project with its own database and deployment pipeline, enabling independent development and deployment.
|
||||
2. **Decentralized Communication**: Services communicate via APIs (REST, gRPC) or message brokers (RabbitMQ, Kafka), ensuring loose coupling and resilience.
|
||||
3. **Scalability**: Services can be scaled independently based on demand, allowing efficient resource utilization.
|
||||
4. **Fault Tolerance**: Failures are isolated, preventing cascading failures and ensuring high availability.
|
||||
5. **Technology Agnostic**: Services can use different technologies, frameworks, or databases, providing flexibility.
|
||||
|
||||
|
||||
## When to Use
|
||||
1. **Large and Complex Projects**: Ideal for applications with complex business logic that can be broken into smaller, manageable services.
|
||||
2. **High Scalability Needs**: Suitable for applications requiring independent scaling of components.
|
||||
3. **Fault Tolerance and High Availability**: Perfect for systems where failure isolation and uptime are critical.
|
||||
4. **Distributed Teams**: Enables teams to work independently on different services.
|
||||
5. **Frequent Updates**: Supports continuous deployment and A/B testing for individual services.
|
||||
6. **Technology Diversity**: Allows the use of different technologies for different services.
|
||||
|
||||
|
||||
## Challenges
|
||||
- Increased complexity in management, DevOps overhead, data consistency, latency, and higher costs.
|
||||
|
||||
|
||||
## The Domain And Bounded Context - Service Boundary
|
||||
|
||||
@ -137,10 +100,19 @@
|
||||
|
||||

|
||||
|
||||
|
||||
## Structure of Project
|
||||
|
||||
In this project, I used [vertical slice architecture](https://jimmybogard.com/vertical-slice-architecture/) at the architectural level and [feature folder structure](http://www.kamilgrzybek.com/design/feature-folders/) to structure my files.
|
||||
In this project I used a mix of [clean architecture](https://jasontaylor.dev/clean-architecture-getting-started/), [vertical slice architecture](https://jimmybogard.com/vertical-slice-architecture/) and I used [feature folder structure](http://www.kamilgrzybek.com/design/feature-folders/) to structure my files.
|
||||
|
||||
I used [yarp reverse proxy](https://microsoft.github.io/reverse-proxy/articles/index.html) to route synchronous and asynchronous requests to the corresponding microservice. Each microservice has its dependencies such as databases, files etc. Each microservice is decoupled from other microservices and developed and deployed separately. Microservices talk to each other with Rest or gRPC for synchronous calls and use RabbitMq or Kafka for asynchronous calls.
|
||||
|
||||
We have a separate microservice ([IdentityServer](https://github.com/DuendeSoftware/IdentityServer)) for authentication and authorization of each request. Once signed-in users are issued a JWT token. This token is used by other microservices to validate the user, read claims and allow access to authorized/role specific endpoints.
|
||||
|
||||
I used [RabbitMQ](https://github.com/rabbitmq) as my MessageBroker for async communication between microservices using the eventual consistency mechanism. Each microservice uses [MassTransit](https://github.com/MassTransit/MassTransit) to interface with [RabbitMQ](https://github.com/rabbitmq) providing, messaging, availability, reliability, etc.
|
||||
|
||||
Microservices are `event based` which means they can publish and/or subscribe to any events occurring in the setup. By using this approach for communicating between services, each microservice does not need to know about the other services or handle errors occurred in other microservices.
|
||||
|
||||
After saving data in write side, I save a [Internal Command](https://github.com/kgrzybek/modular-monolith-with-ddd#38-internal-processing) record in my Persist Messages storage (like something we do in outbox pattern) and after committing transaction in write side, trigger our command handler in read side and this handler could save their read models in our MongoDB database.
|
||||
|
||||
I treat each request as a distinct use case or slice, encapsulating and grouping all concerns from front-end to back.
|
||||
When adding or changing a feature in an application in n-tire architecture, we are typically touching many "layers" in an application. We are changing the user interface, adding fields to models, modifying validation, and so on. Instead of coupling across a layer, we couple vertically along a slice. We `minimize coupling` `between slices`, and `maximize coupling` `in a slice`.
|
||||
@ -163,111 +135,55 @@ I used CQRS to decompose my features into small parts that makes our application
|
||||
|
||||
Using the CQRS pattern, we cut each business functionality into vertical slices, for each of these slices we group classes (see [technical folders structure](http://www.kamilgrzybek.com/design/feature-folders)) specific to that feature together (command, handlers, infrastructure, repository, controllers, etc). In our CQRS pattern each command/query handler is a separate slice. This is where you can reduce coupling between layers. Each handler can be a separated code unit, even copy/pasted. Thanks to that, we can tune down the specific method to not follow general conventions (e.g. use custom SQL query or even different storage). In a traditional layered architecture, when we change the core generic mechanism in one layer, it can impact all methods.
|
||||
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Dotnet Tools Packages
|
||||
For installing our requirement packages with .NET cli tools, we need to install `dotnet tool manifest`.
|
||||
```bash
|
||||
dotnet new tool-manifest
|
||||
```
|
||||
And after that we can restore our dotnet tools packages with .NET cli tools from `.config` folder and `dotnet-tools.json` file.
|
||||
```
|
||||
dotnet tool restore
|
||||
```
|
||||
|
||||
### Husky
|
||||
Here we use `husky` to handel some pre commit rules and we used `conventional commits` rules and `formatting` as pre commit rules, here in [package.json](.././package.json). of course, we can add more rules for pre commit in future. (find more about husky in the [documentation](https://typicode.github.io/husky/get-started.html))
|
||||
We need to install `husky` package for `manage` `pre commits hooks` and also I add two packages `@commitlint/cli` and `@commitlint/config-conventional` for handling conventional commits rules in [package.json](.././package.json).
|
||||
Run the command bellow in the root of project to install all npm dependencies related to husky:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
> Note: In the root of project we have `.husky` folder and it has `commit-msg` file for handling conventional commits rules with provide user friendly message and `pre-commit` file that we can run our `scripts` as a `pre-commit` hooks. that here we call `format` script from [package.json](./package.json) for formatting purpose.
|
||||
|
||||
### Upgrade Nuget Packages
|
||||
For upgrading our nuget packages to last version, we use the great package [dotnet-outdated](https://github.com/dotnet-outdated/dotnet-outdated).
|
||||
Run the command below in the root of project to upgrade all of packages to last version:
|
||||
```bash
|
||||
dotnet outdated -u
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
> ### Config Certificate
|
||||
Run the following commands to [Config SSL](https://docs.microsoft.com/en-us/aspnet/core/security/docker-compose-https?view=aspnetcore-6.0) in your system:
|
||||
> ### Docker
|
||||
|
||||
#### Config Certificate
|
||||
Run the following commands to [Config SSL](https://docs.microsoft.com/en-us/aspnet/core/security/docker-compose-https?view=aspnetcore-6.0) in your system
|
||||
|
||||
#### Windows using Linux containers
|
||||
```bash
|
||||
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p password
|
||||
dotnet dev-certs https --trust
|
||||
```
|
||||
> Note: for running this command in `powershell` use `$env:USERPROFILE` instead of `%USERPROFILE%`*
|
||||
> Note: for running this command in `powershell` use `$env:USERPROFILE` instead of `%USERPROFILE%`
|
||||
|
||||
#### macOS or Linux
|
||||
```bash
|
||||
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p $CREDENTIAL_PLACEHOLDER$
|
||||
dotnet dev-certs https --trust
|
||||
```
|
||||
#### Docker Compose
|
||||
|
||||
### Aspire
|
||||
|
||||
To run the application using the `Aspire App Host`, execute the following command from the solution root:
|
||||
|
||||
```bash
|
||||
aspire run
|
||||
```
|
||||
|
||||
> Note:The `Aspire dashboard` will be available at `http://localhost:18888`
|
||||
|
||||
> ### Docker Compose
|
||||
|
||||
|
||||
To run this app in `Docker`, use the [docker-compose.yaml](./deployments/docker-compose/docker-compose.yaml) and execute the below command at the `root` of the application:
|
||||
Run this app in docker using the [docker-compose.yaml](./deployments/docker-compose/docker-compose.yaml) file with the below command at the root of the application:
|
||||
|
||||
```bash
|
||||
docker-compose -f ./deployments/docker-compose/docker-compose.yaml up -d
|
||||
```
|
||||
|
||||
> ### Kubernetes
|
||||
To `configure TLS` in the `Kubernetes cluster`, we need to install `cert-manager` based on the [docs](https://cert-manager.io/docs/installation) and run the following commands to apply TLS in our application. Here, we use [Let's Encrypt](https://letsencrypt.org/) to encrypt our certificate.
|
||||
For Configure TLS in kubernetes cluster we need install `cert-manager` base on [docs](https://cert-manager.io/docs/installation) and run the following commands for apply TLS in our application
|
||||
|
||||
```bash
|
||||
kubectl apply -f ./deployments/kubernetes/booking-cert-manager.yml
|
||||
```
|
||||
> Note: Also, we can run this commands for creating new `tls.key` and `tls.crt` and replace them with old one in `booking-cert-manager.yml` section `secret`
|
||||
```bash
|
||||
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout tls.key -out tls.crt -subj "/CN=booking-microservices.com" -days 365
|
||||
|
||||
To apply all necessary `deployments`, `pods`, `services`, `ingress`, and `config maps`, please run the following command:
|
||||
kubectl create secret tls booking-tls --key tls.key --cert tls.crt
|
||||
```
|
||||
|
||||
Run the following command to apply all deployments, pods, services, ingress, configmaps that we need
|
||||
```bash
|
||||
kubectl apply -f ./deployments/kubernetes/booking-microservices.yml
|
||||
```
|
||||
|
||||
> ### Build
|
||||
To `build` all microservices, run this command in the `root` of the project:
|
||||
```bash
|
||||
dotnet build
|
||||
```
|
||||
### Documentation Apis
|
||||
|
||||
> ### Run
|
||||
To `run` each microservice, run this command in the root of the `Api` folder of each microservice where the `csproj` file is located:
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
> ### Test
|
||||
|
||||
To `test` all microservices, run this command in the `root` of the project:
|
||||
```bash
|
||||
dotnet test
|
||||
```
|
||||
|
||||
> ### Documentation Apis
|
||||
|
||||
Each microservice provides `API documentation` and navigate to `/swagger` for `Swagger OpenAPI` or `/scalar/v1` for `Scalar OpenAPI` to visit list of endpoints.
|
||||
|
||||
As part of API testing, I created the [booking.rest](./booking.rest) file which can be run with the [REST Client](https://github.com/Huachao/vscode-restclient) `VSCode plugin`.
|
||||
Each microservice uses swagger open api, navigate to /swagger for a list of every endpoint.
|
||||
For testing apis I used the [REST Client](https://github.com/Huachao/vscode-restclient) plugin for VS Code running this file [booking.rest](./booking.rest).
|
||||
|
||||
# Support
|
||||
|
||||
@ -281,15 +197,15 @@ Thanks a bunch for supporting me!
|
||||
|
||||
Thanks to all [contributors](https://github.com/meysamhadeli/booking-microservices/graphs/contributors), you're awesome and this wouldn't be possible without you! The goal is to build a categorized, community-driven collection of very well-known resources.
|
||||
|
||||
Please follow this [contribution guideline](./CONTRIBUTION.md) to submit a pull request or create the issue.
|
||||
|
||||
## Project References & Credits
|
||||
|
||||
- [https://github.com/jbogard/ContosoUniversityDotNetCore-Pages](https://github.com/jbogard/ContosoUniversityDotNetCore-Pages)
|
||||
- [https://github.com/kgrzybek/modular-monolith-with-ddd](https://github.com/kgrzybek/modular-monolith-with-ddd)
|
||||
- [https://github.com/oskardudycz/EventSourcing.NetCore](https://github.com/oskardudycz/EventSourcing.NetCore)
|
||||
- [https://github.com/thangchung/clean-architecture-dotnet](https://github.com/thangchung/clean-architecture-dotnet)
|
||||
- [https://github.com/jasontaylordev/CleanArchitecture](https://github.com/jasontaylordev/CleanArchitecture)
|
||||
- [https://github.com/pdevito3/MessageBusTestingInMemHarness](https://github.com/pdevito3/MessageBusTestingInMemHarness)
|
||||
- [https://github.com/devmentors/FeedR](https://github.com/devmentors/FeedR)
|
||||
|
||||
## License
|
||||
This project is made available under the MIT license. See [LICENSE](https://github.com/meysamhadeli/booking-microservices/blob/main/LICENSE) for details.
|
||||
|
||||
File diff suppressed because one or more lines are too long
13426
assets/booking-microservices.excalidraw
Normal file
13426
assets/booking-microservices.excalidraw
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 643 KiB After Width: | Height: | Size: 1.4 MiB |
@ -4,66 +4,66 @@
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 242,
|
||||
"versionNonce": 1509780320,
|
||||
"isDeleted": false,
|
||||
"id": "80OGzNPG6Gk8NAvbV3XaF",
|
||||
"type": "rectangle",
|
||||
"x": 648,
|
||||
"y": 187,
|
||||
"width": 538,
|
||||
"height": 62,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#5dade2",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 648,
|
||||
"y": 187,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#a8bffe",
|
||||
"width": 538,
|
||||
"height": 62,
|
||||
"seed": 246982778,
|
||||
"opacity": 70,
|
||||
"groupIds": [],
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 246982778,
|
||||
"version": 236,
|
||||
"versionNonce": 69633510,
|
||||
"isDeleted": false,
|
||||
"boundElements": [
|
||||
{
|
||||
"type": "text",
|
||||
"id": "46GLDhDwmnc8RGy3v8OK8"
|
||||
}
|
||||
],
|
||||
"updated": 1679316672934,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 137,
|
||||
"versionNonce": 703919968,
|
||||
"isDeleted": false,
|
||||
"id": "46GLDhDwmnc8RGy3v8OK8",
|
||||
"type": "text",
|
||||
"x": 897.848014831543,
|
||||
"y": 201.2,
|
||||
"width": 38.30397033691406,
|
||||
"height": 33.6,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 897.848014831543,
|
||||
"y": 201.2,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 38.30397033691406,
|
||||
"height": 33.6,
|
||||
"seed": 2080176422,
|
||||
"opacity": 70,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949309,
|
||||
"seed": 2080176422,
|
||||
"version": 133,
|
||||
"versionNonce": 467252090,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Api",
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Api",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": "80OGzNPG6Gk8NAvbV3XaF",
|
||||
@ -71,20 +71,20 @@
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 358,
|
||||
"versionNonce": 356515488,
|
||||
"version": 339,
|
||||
"versionNonce": 2033133178,
|
||||
"isDeleted": false,
|
||||
"id": "nZuYK7wbLObwRvpRRLHay",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"opacity": 70,
|
||||
"angle": 0,
|
||||
"x": 648,
|
||||
"y": 263,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#fea8d5",
|
||||
"backgroundColor": "#ced4da",
|
||||
"width": 538,
|
||||
"height": 62,
|
||||
"seed": 287502970,
|
||||
@ -98,21 +98,21 @@
|
||||
"id": "OALII-DXtatRPgn_EkHfp"
|
||||
}
|
||||
],
|
||||
"updated": 1679316735759,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 246,
|
||||
"versionNonce": 1126108000,
|
||||
"version": 242,
|
||||
"versionNonce": 1368921638,
|
||||
"isDeleted": false,
|
||||
"id": "OALII-DXtatRPgn_EkHfp",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"opacity": 70,
|
||||
"angle": 0,
|
||||
"x": 845.628044128418,
|
||||
"y": 277.2,
|
||||
@ -123,8 +123,8 @@
|
||||
"seed": 1016531494,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949309,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
@ -137,20 +137,20 @@
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 282,
|
||||
"versionNonce": 787808928,
|
||||
"version": 271,
|
||||
"versionNonce": 1144538938,
|
||||
"isDeleted": false,
|
||||
"id": "za_4vz64MSfPF5TWmD7wj",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"opacity": 70,
|
||||
"angle": 0,
|
||||
"x": 650,
|
||||
"y": 338,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f30358",
|
||||
"backgroundColor": "#fa5252",
|
||||
"width": 538,
|
||||
"height": 62,
|
||||
"seed": 676018342,
|
||||
@ -164,21 +164,21 @@
|
||||
"id": "6CqYCSOKHqhqJ8nf4b-Sv"
|
||||
}
|
||||
],
|
||||
"updated": 1679316783390,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 189,
|
||||
"versionNonce": 1441177440,
|
||||
"version": 185,
|
||||
"versionNonce": 1874747750,
|
||||
"isDeleted": false,
|
||||
"id": "6CqYCSOKHqhqJ8nf4b-Sv",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"opacity": 70,
|
||||
"angle": 0,
|
||||
"x": 816.618049621582,
|
||||
"y": 352.2,
|
||||
@ -189,8 +189,8 @@
|
||||
"seed": 1067355322,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949309,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
@ -203,8 +203,8 @@
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 326,
|
||||
"versionNonce": 1669046112,
|
||||
"version": 323,
|
||||
"versionNonce": 987713530,
|
||||
"isDeleted": false,
|
||||
"id": "t2sZwLLvmq3y2ndIbEomB",
|
||||
"fillStyle": "solid",
|
||||
@ -216,7 +216,7 @@
|
||||
"x": 648,
|
||||
"y": 413,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#9d9ca2",
|
||||
"backgroundColor": "#58ccae",
|
||||
"width": 538,
|
||||
"height": 62,
|
||||
"seed": 1173221990,
|
||||
@ -230,14 +230,14 @@
|
||||
"id": "b3wdaWjaVmgHpzMD26uKD"
|
||||
}
|
||||
],
|
||||
"updated": 1679316844215,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 224,
|
||||
"versionNonce": 1385935712,
|
||||
"version": 223,
|
||||
"versionNonce": 1635337382,
|
||||
"isDeleted": false,
|
||||
"id": "b3wdaWjaVmgHpzMD26uKD",
|
||||
"fillStyle": "hachure",
|
||||
@ -255,8 +255,8 @@
|
||||
"seed": 1307397882,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949310,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
@ -268,37 +268,37 @@
|
||||
"originalText": "Core"
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 202,
|
||||
"versionNonce": 1461187232,
|
||||
"isDeleted": false,
|
||||
"id": "FQZImjU2-VUOATU9Yeyly",
|
||||
"type": "rectangle",
|
||||
"x": 678,
|
||||
"y": 154,
|
||||
"width": 48,
|
||||
"height": 361,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 678,
|
||||
"y": 154,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#fefda8",
|
||||
"width": 48,
|
||||
"height": 361,
|
||||
"seed": 1254939642,
|
||||
"groupIds": [],
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1254939642,
|
||||
"version": 185,
|
||||
"versionNonce": 19349690,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1679316609154,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 249,
|
||||
"versionNonce": 1540775776,
|
||||
"version": 224,
|
||||
"versionNonce": 1119033722,
|
||||
"isDeleted": false,
|
||||
"id": "_Vw9EnXAyzxRDEzXCTfeL",
|
||||
"fillStyle": "solid",
|
||||
@ -307,10 +307,10 @@
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 742,
|
||||
"x": 743,
|
||||
"y": 153.5,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#fefda8",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"width": 48,
|
||||
"height": 361,
|
||||
"seed": 523058342,
|
||||
@ -318,39 +318,39 @@
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"boundElements": [],
|
||||
"updated": 1679316594766,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 249,
|
||||
"versionNonce": 871687840,
|
||||
"isDeleted": false,
|
||||
"id": "hyJiOwPt7LFndn5R0xgfL",
|
||||
"type": "text",
|
||||
"x": 637.1248451774691,
|
||||
"y": 317.9455509364301,
|
||||
"width": 130.73194885253906,
|
||||
"height": 33.6,
|
||||
"angle": 4.707547804955119,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 4.707547804955119,
|
||||
"x": 637.1248451774691,
|
||||
"y": 317.9455509364301,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"width": 130.73194885253906,
|
||||
"height": 33.6,
|
||||
"seed": 678740006,
|
||||
"opacity": 70,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315961675,
|
||||
"seed": 678740006,
|
||||
"version": 245,
|
||||
"versionNonce": 1220596518,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Feature 1",
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Feature 1",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
@ -358,15 +358,15 @@
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 182,
|
||||
"versionNonce": 1494113120,
|
||||
"version": 179,
|
||||
"versionNonce": 1053153850,
|
||||
"isDeleted": false,
|
||||
"id": "7KOHd5JA_wVMmwXPVT1N3",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 80,
|
||||
"opacity": 70,
|
||||
"angle": 4.7123889803846915,
|
||||
"x": 695.6880416870117,
|
||||
"y": 313.20000000000005,
|
||||
@ -377,8 +377,8 @@
|
||||
"seed": 1387191482,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949310,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 28,
|
||||
@ -390,33 +390,33 @@
|
||||
"originalText": "Feature 2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 163,
|
||||
"versionNonce": 1243581088,
|
||||
"isDeleted": false,
|
||||
"id": "SuFNrbzZGowiIybusnadN",
|
||||
"type": "text",
|
||||
"x": 748,
|
||||
"y": 96,
|
||||
"width": 360.47186279296875,
|
||||
"height": 33.6,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 70,
|
||||
"angle": 0,
|
||||
"x": 748,
|
||||
"y": 96,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#f9e79f",
|
||||
"width": 360.47186279296875,
|
||||
"height": 33.6,
|
||||
"seed": 2006173690,
|
||||
"groupIds": [],
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1679315949310,
|
||||
"seed": 2006173690,
|
||||
"version": 162,
|
||||
"versionNonce": 1556577894,
|
||||
"isDeleted": false,
|
||||
"boundElements": null,
|
||||
"updated": 1677440080893,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"text": "Vertical Slice Architecture",
|
||||
"fontSize": 28,
|
||||
"fontFamily": 1,
|
||||
"text": "Vertical Slice Architecture",
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"containerId": null,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 69 KiB |
175
booking-microservices-sample.sln
Normal file
175
booking-microservices-sample.sln
Normal file
@ -0,0 +1,175 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30114.105
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{5B69EDFD-4B09-457A-AAAF-D816D402D595}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{9010E0B5-9C42-4256-ADE4-E290434F2CEF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateway", "ApiGateway", "{3E38DD17-9EEE-4815-9D5B-BEB5549020A0}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{776BDF43-0DEA-44A3-AF72-99408CE544EE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiGateway", "src\ApiGateway\src\ApiGateway.csproj", "{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildingBlocks", "src\BuildingBlocks\BuildingBlocks.csproj", "{E42BB533-4144-4D78-BCCE-50BA00BCADBE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flight", "Flight", "{5F0996AB-F8DB-4240-BD4A-DFDD70638A73}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Passenger", "Passenger", "{1A2ABCD9-493B-4848-9C69-919CDBCA61F3}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Booking", "Booking", "{22447274-717D-4321-87F3-868BAF93CBEC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{55BE6759-95AA-434D-925D-A8D32F274E66}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E2637D6D-04A5-4DE4-8AAF-E015C65DE8E1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{5185D5C5-0EAD-49D5-B405-93B939F3639B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{53D0AA09-F5FA-4721-8C1B-375CBD15B4E8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C6EE337B-91EA-472A-87C7-E9528408CE59}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F39D8F09-6233-4495-ACD0-F98904993B7E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{295284BA-D4E4-40AA-A2C2-BE36343F7DE6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{85DA00E5-CC11-463C-8577-C34967C328F7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C1EBE17D-BFAD-47DA-88EB-BB073B84593E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Booking", "src\Services\Booking\src\Booking\Booking.csproj", "{B2BAA061-C005-409F-9D3E-BDCBE5B1B136}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Booking.Api", "src\Services\Booking\src\Booking.Api\Booking.Api.csproj", "{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flight", "src\Services\Flight\src\Flight\Flight.csproj", "{574222F8-9C26-4015-8F35-C1E5D41A505F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flight.Api", "src\Services\Flight\src\Flight.Api\Flight.Api.csproj", "{B8F734F5-873C-4367-9EBD-38EA420CD868}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity", "src\Services\Identity\src\Identity\Identity.csproj", "{65C1BB58-2A2E-44FF-B15D-2B023CF088D4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.Api", "src\Services\Identity\src\Identity.Api\Identity.Api.csproj", "{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger", "src\Services\Passenger\src\Passenger\Passenger.csproj", "{6D7BCECE-D77D-4C57-A296-CA6E728E94B7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Api", "src\Services\Passenger\src\Passenger.Api\Passenger.Api.csproj", "{4F29C4B6-A7DA-4A92-9CDB-42FE98238837}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Flight\tests\IntegrationTest\Integration.Test.csproj", "{6B6603C8-D8B6-4775-9C7A-FFE6058070C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Identity\tests\IntegrationTest\Integration.Test.csproj", "{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Passenger\tests\IntegrationTest\Integration.Test.csproj", "{539364C8-88B1-48A3-8406-D0B19FF30509}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Booking\tests\IntegrationTest\Integration.Test.csproj", "{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unit.Test", "src\Services\Flight\tests\UnitTest\Unit.Test.csproj", "{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndToEnd.Test", "src\Services\Flight\tests\EndToEndTest\EndToEnd.Test.csproj", "{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{776BDF43-0DEA-44A3-AF72-99408CE544EE} = {3E38DD17-9EEE-4815-9D5B-BEB5549020A0}
|
||||
{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5} = {776BDF43-0DEA-44A3-AF72-99408CE544EE}
|
||||
{E42BB533-4144-4D78-BCCE-50BA00BCADBE} = {5B69EDFD-4B09-457A-AAAF-D816D402D595}
|
||||
{5F0996AB-F8DB-4240-BD4A-DFDD70638A73} = {9010E0B5-9C42-4256-ADE4-E290434F2CEF}
|
||||
{1A2ABCD9-493B-4848-9C69-919CDBCA61F3} = {9010E0B5-9C42-4256-ADE4-E290434F2CEF}
|
||||
{22447274-717D-4321-87F3-868BAF93CBEC} = {9010E0B5-9C42-4256-ADE4-E290434F2CEF}
|
||||
{55BE6759-95AA-434D-925D-A8D32F274E66} = {9010E0B5-9C42-4256-ADE4-E290434F2CEF}
|
||||
{E2637D6D-04A5-4DE4-8AAF-E015C65DE8E1} = {22447274-717D-4321-87F3-868BAF93CBEC}
|
||||
{5185D5C5-0EAD-49D5-B405-93B939F3639B} = {22447274-717D-4321-87F3-868BAF93CBEC}
|
||||
{53D0AA09-F5FA-4721-8C1B-375CBD15B4E8} = {5F0996AB-F8DB-4240-BD4A-DFDD70638A73}
|
||||
{C6EE337B-91EA-472A-87C7-E9528408CE59} = {5F0996AB-F8DB-4240-BD4A-DFDD70638A73}
|
||||
{F39D8F09-6233-4495-ACD0-F98904993B7E} = {55BE6759-95AA-434D-925D-A8D32F274E66}
|
||||
{295284BA-D4E4-40AA-A2C2-BE36343F7DE6} = {55BE6759-95AA-434D-925D-A8D32F274E66}
|
||||
{85DA00E5-CC11-463C-8577-C34967C328F7} = {1A2ABCD9-493B-4848-9C69-919CDBCA61F3}
|
||||
{C1EBE17D-BFAD-47DA-88EB-BB073B84593E} = {1A2ABCD9-493B-4848-9C69-919CDBCA61F3}
|
||||
{B2BAA061-C005-409F-9D3E-BDCBE5B1B136} = {E2637D6D-04A5-4DE4-8AAF-E015C65DE8E1}
|
||||
{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C} = {E2637D6D-04A5-4DE4-8AAF-E015C65DE8E1}
|
||||
{574222F8-9C26-4015-8F35-C1E5D41A505F} = {53D0AA09-F5FA-4721-8C1B-375CBD15B4E8}
|
||||
{B8F734F5-873C-4367-9EBD-38EA420CD868} = {53D0AA09-F5FA-4721-8C1B-375CBD15B4E8}
|
||||
{65C1BB58-2A2E-44FF-B15D-2B023CF088D4} = {F39D8F09-6233-4495-ACD0-F98904993B7E}
|
||||
{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA} = {F39D8F09-6233-4495-ACD0-F98904993B7E}
|
||||
{6D7BCECE-D77D-4C57-A296-CA6E728E94B7} = {85DA00E5-CC11-463C-8577-C34967C328F7}
|
||||
{4F29C4B6-A7DA-4A92-9CDB-42FE98238837} = {85DA00E5-CC11-463C-8577-C34967C328F7}
|
||||
{6B6603C8-D8B6-4775-9C7A-FFE6058070C2} = {C6EE337B-91EA-472A-87C7-E9528408CE59}
|
||||
{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2} = {295284BA-D4E4-40AA-A2C2-BE36343F7DE6}
|
||||
{539364C8-88B1-48A3-8406-D0B19FF30509} = {C1EBE17D-BFAD-47DA-88EB-BB073B84593E}
|
||||
{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC} = {5185D5C5-0EAD-49D5-B405-93B939F3639B}
|
||||
{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8} = {C6EE337B-91EA-472A-87C7-E9528408CE59}
|
||||
{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB} = {C6EE337B-91EA-472A-87C7-E9528408CE59}
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A2D7C5C4-5148-4C3E-BB12-B7A197A290F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E42BB533-4144-4D78-BCCE-50BA00BCADBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E42BB533-4144-4D78-BCCE-50BA00BCADBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E42BB533-4144-4D78-BCCE-50BA00BCADBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E42BB533-4144-4D78-BCCE-50BA00BCADBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B2BAA061-C005-409F-9D3E-BDCBE5B1B136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2BAA061-C005-409F-9D3E-BDCBE5B1B136}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2BAA061-C005-409F-9D3E-BDCBE5B1B136}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2BAA061-C005-409F-9D3E-BDCBE5B1B136}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E8FB852-4317-43D2-8EFC-14E3ECCFDA2C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{574222F8-9C26-4015-8F35-C1E5D41A505F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{574222F8-9C26-4015-8F35-C1E5D41A505F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{574222F8-9C26-4015-8F35-C1E5D41A505F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{574222F8-9C26-4015-8F35-C1E5D41A505F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B8F734F5-873C-4367-9EBD-38EA420CD868}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B8F734F5-873C-4367-9EBD-38EA420CD868}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B8F734F5-873C-4367-9EBD-38EA420CD868}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B8F734F5-873C-4367-9EBD-38EA420CD868}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65C1BB58-2A2E-44FF-B15D-2B023CF088D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65C1BB58-2A2E-44FF-B15D-2B023CF088D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65C1BB58-2A2E-44FF-B15D-2B023CF088D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65C1BB58-2A2E-44FF-B15D-2B023CF088D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BEE7A9D7-1BFC-477E-B070-4BE63C0361AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6D7BCECE-D77D-4C57-A296-CA6E728E94B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6D7BCECE-D77D-4C57-A296-CA6E728E94B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6D7BCECE-D77D-4C57-A296-CA6E728E94B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6D7BCECE-D77D-4C57-A296-CA6E728E94B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4F29C4B6-A7DA-4A92-9CDB-42FE98238837}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4F29C4B6-A7DA-4A92-9CDB-42FE98238837}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4F29C4B6-A7DA-4A92-9CDB-42FE98238837}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4F29C4B6-A7DA-4A92-9CDB-42FE98238837}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B6603C8-D8B6-4775-9C7A-FFE6058070C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B6603C8-D8B6-4775-9C7A-FFE6058070C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B6603C8-D8B6-4775-9C7A-FFE6058070C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B6603C8-D8B6-4775-9C7A-FFE6058070C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC7871B8-BB18-4BCC-96A8-7324C11BF4A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{539364C8-88B1-48A3-8406-D0B19FF30509}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{539364C8-88B1-48A3-8406-D0B19FF30509}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{539364C8-88B1-48A3-8406-D0B19FF30509}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{539364C8-88B1-48A3-8406-D0B19FF30509}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{50C66B53-ACA0-4AFF-8C5C-834D4EDA8FAC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8F78BCE2-C705-4357-A6B9-1B83B55ABBE8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8561089E-9FB9-4ACD-A1F5-EAAF213E1DDB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -1,348 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CD4A4407-C3B0-422D-BB8C-2A810CED9938}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateway", "ApiGateway", "{CDFA86FA-BBBA-4A5B-A833-3BE219E373E5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{B19FD14B-4DFE-26B6-646B-3D5D94CC4D36}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{C734CEF7-A2AC-3076-84D8-694B7490AA9D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flight", "Flight", "{A3579DE0-F7C5-67E8-3CF8-3AC89B64E059}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Booking", "Booking", "{C6034A5C-F49A-5FA4-86A6-65B2CB19613F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Passenger", "Passenger", "{9D4F3958-FE6E-C048-E6F9-6F53D8AF03CA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{B465D535-05D9-3A0A-08BF-35A1C18CEC46}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A2834164-BF04-BF13-ADC5-A97145852861}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1B4FBE3A-43F5-1B1E-2877-3036AC5431EF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DDEDC5E0-5D13-A45C-2393-A774DD4A1A07}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{51D8F471-B8EB-AD1C-0E89-AA84C5D0C759}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{773BFBD8-04CD-79F8-8301-C81308C3ED45}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4B043475-1AFA-C467-FE09-A46D09CD6936}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5CED3889-AECF-A6CD-55DC-F680D3C18861}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{54BCCDE8-25E6-6FCB-4A9E-D5D2AF76D352}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Booking.Api", "src\Services\Booking\src\Booking.Api\Booking.Api.csproj", "{D3BF565A-C413-4185-9528-BE1B4F46993C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Booking", "src\Services\Booking\src\Booking\Booking.csproj", "{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flight", "src\Services\Flight\src\Flight\Flight.csproj", "{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flight.Api", "src\Services\Flight\src\Flight.Api\Flight.Api.csproj", "{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity", "src\Services\Identity\src\Identity\Identity.csproj", "{BCDEAB10-6373-46E7-B408-846A3B0B508B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.Api", "src\Services\Identity\src\Identity.Api\Identity.Api.csproj", "{B0EC74C5-9B2D-492C-ABAE-3E868397B122}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger", "src\Services\Passenger\src\Passenger\Passenger.csproj", "{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Api", "src\Services\Passenger\src\Passenger.Api\Passenger.Api.csproj", "{101FFD12-17A4-4615-9438-F347BBF4CC85}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildingBlocks", "src\BuildingBlocks\BuildingBlocks.csproj", "{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{427BE8BE-DA7B-FC74-412B-547671E05463}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiGateway", "src\ApiGateway\src\ApiGateway.csproj", "{C015BF35-6977-407B-8948-636A9C81C5BE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Booking\tests\IntegrationTest\Integration.Test.csproj", "{19A89F36-FD3A-448D-90D1-04A1B67BB255}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndToEnd.Test", "src\Services\Flight\tests\EndToEndTest\EndToEnd.Test.csproj", "{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Flight\tests\IntegrationTest\Integration.Test.csproj", "{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unit.Test", "src\Services\Flight\tests\UnitTest\Unit.Test.csproj", "{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Identity\tests\IntegrationTest\Integration.Test.csproj", "{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration.Test", "src\Services\Passenger\tests\IntegrationTest\Integration.Test.csproj", "{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Aspire", "Aspire", "{D1B6353A-63F5-4DD9-90E6-42B2CFDF1DEA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C4287034-6833-4505-A6EB-704A86392ECB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppHost", "src\Aspire\src\AppHost\AppHost.csproj", "{490BCB11-314C-473C-9B85-A32164783507}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceDefaults", "src\Aspire\src\ServiceDefaults\ServiceDefaults.csproj", "{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279}.Release|x86.Build.0 = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538}.Release|x86.Build.0 = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|x64.Build.0 = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|x64.Build.0 = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5}.Release|x86.Build.0 = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|x64.Build.0 = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{490BCB11-314C-473C-9B85-A32164783507}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{CDFA86FA-BBBA-4A5B-A833-3BE219E373E5} = {CD4A4407-C3B0-422D-BB8C-2A810CED9938}
|
||||
{B19FD14B-4DFE-26B6-646B-3D5D94CC4D36} = {CD4A4407-C3B0-422D-BB8C-2A810CED9938}
|
||||
{C734CEF7-A2AC-3076-84D8-694B7490AA9D} = {CD4A4407-C3B0-422D-BB8C-2A810CED9938}
|
||||
{A3579DE0-F7C5-67E8-3CF8-3AC89B64E059} = {B19FD14B-4DFE-26B6-646B-3D5D94CC4D36}
|
||||
{C6034A5C-F49A-5FA4-86A6-65B2CB19613F} = {B19FD14B-4DFE-26B6-646B-3D5D94CC4D36}
|
||||
{9D4F3958-FE6E-C048-E6F9-6F53D8AF03CA} = {B19FD14B-4DFE-26B6-646B-3D5D94CC4D36}
|
||||
{B465D535-05D9-3A0A-08BF-35A1C18CEC46} = {B19FD14B-4DFE-26B6-646B-3D5D94CC4D36}
|
||||
{A2834164-BF04-BF13-ADC5-A97145852861} = {C6034A5C-F49A-5FA4-86A6-65B2CB19613F}
|
||||
{1B4FBE3A-43F5-1B1E-2877-3036AC5431EF} = {C6034A5C-F49A-5FA4-86A6-65B2CB19613F}
|
||||
{DDEDC5E0-5D13-A45C-2393-A774DD4A1A07} = {A3579DE0-F7C5-67E8-3CF8-3AC89B64E059}
|
||||
{51D8F471-B8EB-AD1C-0E89-AA84C5D0C759} = {A3579DE0-F7C5-67E8-3CF8-3AC89B64E059}
|
||||
{773BFBD8-04CD-79F8-8301-C81308C3ED45} = {B465D535-05D9-3A0A-08BF-35A1C18CEC46}
|
||||
{4B043475-1AFA-C467-FE09-A46D09CD6936} = {B465D535-05D9-3A0A-08BF-35A1C18CEC46}
|
||||
{5CED3889-AECF-A6CD-55DC-F680D3C18861} = {9D4F3958-FE6E-C048-E6F9-6F53D8AF03CA}
|
||||
{54BCCDE8-25E6-6FCB-4A9E-D5D2AF76D352} = {9D4F3958-FE6E-C048-E6F9-6F53D8AF03CA}
|
||||
{D3BF565A-C413-4185-9528-BE1B4F46993C} = {A2834164-BF04-BF13-ADC5-A97145852861}
|
||||
{3EA375C7-2900-4927-B1E5-C9D31E67F4A8} = {A2834164-BF04-BF13-ADC5-A97145852861}
|
||||
{BCC8A8A6-C2ED-42D2-86BB-A05C790D7279} = {DDEDC5E0-5D13-A45C-2393-A774DD4A1A07}
|
||||
{836D1466-3C20-4D74-B54A-FA09C0EE0FA2} = {DDEDC5E0-5D13-A45C-2393-A774DD4A1A07}
|
||||
{BCDEAB10-6373-46E7-B408-846A3B0B508B} = {773BFBD8-04CD-79F8-8301-C81308C3ED45}
|
||||
{B0EC74C5-9B2D-492C-ABAE-3E868397B122} = {773BFBD8-04CD-79F8-8301-C81308C3ED45}
|
||||
{9B4BDD42-56F3-4DB9-B3E5-74ABB7C19538} = {5CED3889-AECF-A6CD-55DC-F680D3C18861}
|
||||
{101FFD12-17A4-4615-9438-F347BBF4CC85} = {5CED3889-AECF-A6CD-55DC-F680D3C18861}
|
||||
{AEDB3219-5E1D-4716-8DE2-F5F9391913A2} = {C734CEF7-A2AC-3076-84D8-694B7490AA9D}
|
||||
{427BE8BE-DA7B-FC74-412B-547671E05463} = {CDFA86FA-BBBA-4A5B-A833-3BE219E373E5}
|
||||
{C015BF35-6977-407B-8948-636A9C81C5BE} = {427BE8BE-DA7B-FC74-412B-547671E05463}
|
||||
{19A89F36-FD3A-448D-90D1-04A1B67BB255} = {1B4FBE3A-43F5-1B1E-2877-3036AC5431EF}
|
||||
{B27759CD-5A7D-43A4-A55C-FE1154DC4CC4} = {51D8F471-B8EB-AD1C-0E89-AA84C5D0C759}
|
||||
{BD23EEF8-9196-4E0F-BF33-E14E99D34C1B} = {51D8F471-B8EB-AD1C-0E89-AA84C5D0C759}
|
||||
{B52D6341-AAD9-43CB-82AF-2DBE39CBF1DB} = {51D8F471-B8EB-AD1C-0E89-AA84C5D0C759}
|
||||
{0DAACE48-4EA6-4DB7-8A5C-99B86BCB1E01} = {4B043475-1AFA-C467-FE09-A46D09CD6936}
|
||||
{A85AE27D-81ED-485A-BA4B-161B25BEB8A5} = {54BCCDE8-25E6-6FCB-4A9E-D5D2AF76D352}
|
||||
{D1B6353A-63F5-4DD9-90E6-42B2CFDF1DEA} = {CD4A4407-C3B0-422D-BB8C-2A810CED9938}
|
||||
{C4287034-6833-4505-A6EB-704A86392ECB} = {D1B6353A-63F5-4DD9-90E6-42B2CFDF1DEA}
|
||||
{490BCB11-314C-473C-9B85-A32164783507} = {C4287034-6833-4505-A6EB-704A86392ECB}
|
||||
{5B7BF918-E47F-4932-B5C5-E8C2C35890E4} = {C4287034-6833-4505-A6EB-704A86392ECB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
36
booking.rest
36
booking.rest
@ -1,15 +1,15 @@
|
||||
|
||||
## uncommnet this line for use kubernetes ingress controller instead of Yarp
|
||||
//@api-gateway=https://booking-microservices.com
|
||||
@api-gateway=https://localhost:5000
|
||||
//@api-gateway=https://booking-microservices.com
|
||||
@api-gateway=https://localhost:5000
|
||||
@identity-api=http://localhost:6005
|
||||
@flight-api=http://localhost:5004
|
||||
@passenger-api=http://localhost:6012
|
||||
@booking-api=http://localhost:6010
|
||||
|
||||
@contentType = application/json
|
||||
@flightid = "3c5c0000-97c6-fc34-2eb9-08db322230c9"
|
||||
@passengerId = "8c9c0000-97c6-fc34-2eb9-66db322230c9"
|
||||
@flightid = 1
|
||||
@passengerId = 1
|
||||
|
||||
################################# Identity API #################################
|
||||
|
||||
@ -29,9 +29,7 @@ grant_type=password
|
||||
&client_secret=secret
|
||||
&username=samh
|
||||
&password=Admin@123456
|
||||
&scope=flight-api role
|
||||
|
||||
### change scope base on microservices scope (eg. passenger-api, ...)
|
||||
&scope=flight-api
|
||||
###
|
||||
|
||||
|
||||
@ -47,7 +45,7 @@ authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
"firstName": "John",
|
||||
"lastName": "Do",
|
||||
"username": "admin",
|
||||
"passportNumber": "41290000",
|
||||
"passportNumber": "412900000000",
|
||||
"email": "admin@admin.com",
|
||||
"password": "Admin@12345",
|
||||
"confirmPassword": "Admin@12345"
|
||||
@ -72,7 +70,7 @@ authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
"seatNumber": "1255",
|
||||
"type": 1,
|
||||
"class": 1,
|
||||
"flightId": "3c5c0000-97c6-fc34-2eb9-08db322230c9"
|
||||
"flightId": 1
|
||||
}
|
||||
###
|
||||
|
||||
@ -85,7 +83,7 @@ Content-Type: application/json
|
||||
authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
|
||||
{
|
||||
"flightId": "3c5c0000-97c6-fc34-2eb9-08db322230c9",
|
||||
"flightId": 1,
|
||||
"seatNumber": "1255"
|
||||
}
|
||||
###
|
||||
@ -127,11 +125,11 @@ authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
|
||||
{
|
||||
"flightNumber": "12BB",
|
||||
"aircraftId": "3c5c0000-97c6-fc34-fcd3-08db322230c8",
|
||||
"departureAirportId": "3c5c0000-97c6-fc34-a0cb-08db322230c8",
|
||||
"aircraftId": 1,
|
||||
"departureAirportId": 1,
|
||||
"departureDate": "2022-03-01T14:55:41.255Z",
|
||||
"arriveDate": "2022-03-01T14:55:41.255Z",
|
||||
"arriveAirportId": "3c5c0000-97c6-fc34-fc3c-08db322230c8",
|
||||
"arriveAirportId": 2,
|
||||
"durationMinutes": 120,
|
||||
"flightDate": "2022-03-01T14:55:41.255Z",
|
||||
"status": 1,
|
||||
@ -150,11 +148,11 @@ authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
{
|
||||
"id": 1,
|
||||
"flightNumber": "BD467",
|
||||
"aircraftId": "3c5c0000-97c6-fc34-fcd3-08db322230c8",
|
||||
"departureAirportId": "3c5c0000-97c6-fc34-a0cb-08db322230c8",
|
||||
"aircraftId": 1,
|
||||
"departureAirportId": 1,
|
||||
"departureDate": "2022-04-23T12:17:45.140Z",
|
||||
"arriveDate": "2022-04-23T12:17:45.140Z",
|
||||
"arriveAirportId": "3c5c0000-97c6-fc34-fc3c-08db322230c8",
|
||||
"arriveAirportId": 2,
|
||||
"durationMinutes": 120,
|
||||
"flightDate": "2022-04-23T12:17:45.140Z",
|
||||
"status": 4,
|
||||
@ -220,7 +218,7 @@ Content-Type: application/json
|
||||
authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
|
||||
{
|
||||
"passportNumber": "41290000",
|
||||
"passportNumber": "412900000000",
|
||||
"passengerType": 1,
|
||||
"age": 30
|
||||
}
|
||||
@ -252,8 +250,8 @@ Content-Type: application/json
|
||||
authorization: bearer {{Authenticate.response.body.access_token}}
|
||||
|
||||
{
|
||||
"passengerId": "8c9c0000-97c6-fc34-2eb9-66db322230c9",
|
||||
"flightId": "3c5c0000-97c6-fc34-2eb9-08db322230c9",
|
||||
"passengerId": 8765596234940416,
|
||||
"flightId": 1,
|
||||
"description": "I want to fly to iran"
|
||||
}
|
||||
###
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
# Dashboards
|
||||
|
||||
- [Introducing ASP.NET Core metrics and Grafana dashboards in .NET 8](https://devblogs.microsoft.com/dotnet/introducing-aspnetcore-metrics-and-grafana-dashboards-in-dotnet-8/)
|
||||
- [ASP.NET Core](https://grafana.com/grafana/dashboards/19924-asp-net-core/)
|
||||
- [ASP.NET Core Endpoint](https://grafana.com/grafana/dashboards/19925-asp-net-core-endpoint/)
|
||||
- [Node Exporter Quickstart and Dashboard](https://grafana.com/grafana/dashboards/13978-node-exporter-quickstart-and-dashboard/)
|
||||
- [PostgreSQL Exporter Quickstart and Dashboard](https://grafana.com/grafana/dashboards/14114-postgres-overview/)
|
||||
- [RabbitMQ-Overview](https://grafana.com/grafana/dashboards/10991-rabbitmq-overview/)
|
||||
@ -1,908 +0,0 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY",
|
||||
"label": "Managed_Prometheus_jamesnk-telemetry",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "prometheus",
|
||||
"pluginName": "Prometheus"
|
||||
}
|
||||
],
|
||||
"__elements": {},
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "9.4.8"
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "stat",
|
||||
"name": "Stat",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "table",
|
||||
"name": "Table",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "timeseries",
|
||||
"name": "Time series",
|
||||
"version": ""
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [
|
||||
{
|
||||
"asDropdown": false,
|
||||
"icon": "dashboard",
|
||||
"includeVars": false,
|
||||
"keepTime": true,
|
||||
"tags": [],
|
||||
"targetBlank": false,
|
||||
"title": " ASP.NET Core",
|
||||
"tooltip": "",
|
||||
"type": "link",
|
||||
"url": "/d/KdDACDp4z/asp-net-core-metrics"
|
||||
}
|
||||
],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"fixedColor": "dark-green",
|
||||
"mode": "continuous-GrYlRd",
|
||||
"seriesBy": "max"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"axisSoftMin": 0,
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 50,
|
||||
"gradientMode": "opacity",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "smooth",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "s"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"__systemRef": "hideSeriesFrom",
|
||||
"matcher": {
|
||||
"id": "byNames",
|
||||
"options": {
|
||||
"mode": "exclude",
|
||||
"names": [
|
||||
"p50"
|
||||
],
|
||||
"prefix": "All except:",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.hideFrom",
|
||||
"value": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 40,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"min",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.50, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"legendFormat": "p50",
|
||||
"range": true,
|
||||
"refId": "p50"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.75, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p75",
|
||||
"range": true,
|
||||
"refId": "p75"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.90, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p90",
|
||||
"range": true,
|
||||
"refId": "p90"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.95, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p95",
|
||||
"range": true,
|
||||
"refId": "p95"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.98, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p98",
|
||||
"range": true,
|
||||
"refId": "p98"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.99, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p99",
|
||||
"range": true,
|
||||
"refId": "p99"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "histogram_quantile(0.999, sum(rate(http_server_request_duration_s_bucket{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m])) by (le))",
|
||||
"hide": false,
|
||||
"legendFormat": "p99.9",
|
||||
"range": true,
|
||||
"refId": "p99.9"
|
||||
}
|
||||
],
|
||||
"title": "Requests Duration - $method $route",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic",
|
||||
"seriesBy": "max"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 50,
|
||||
"gradientMode": "opacity",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "smooth",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "percentunit"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "All"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "dark-orange",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "4XX"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "yellow",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "5XX"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"fixedColor": "dark-red",
|
||||
"mode": "fixed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 46,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"lastNotNull",
|
||||
"min",
|
||||
"max"
|
||||
],
|
||||
"displayMode": "table",
|
||||
"placement": "right",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\", status_code=~\"4..|5..\"}[5m]) or vector(0)) / sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m]))",
|
||||
"legendFormat": "All",
|
||||
"range": true,
|
||||
"refId": "All"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\", status_code=~\"4..\"}[5m]) or vector(0)) / sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m]))",
|
||||
"hide": false,
|
||||
"legendFormat": "4XX",
|
||||
"range": true,
|
||||
"refId": "4XX"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\", status_code=~\"5..\"}[5m]) or vector(0)) / sum(rate(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[5m]))",
|
||||
"hide": false,
|
||||
"legendFormat": "5XX",
|
||||
"range": true,
|
||||
"refId": "5XX"
|
||||
}
|
||||
],
|
||||
"title": "Errors Rate - $method $route",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"cellOptions": {
|
||||
"type": "auto"
|
||||
},
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Requests"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.width",
|
||||
"value": 300
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"mode": "gradient",
|
||||
"type": "gauge"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "continuous-YlRd"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Route"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "links",
|
||||
"value": [
|
||||
{
|
||||
"title": "",
|
||||
"url": "/d/NagEsjE4z/asp-net-core-endpoint-details?var-route=${__data.fields.Route}&var-method=${__data.fields.Method}&${__url_time_range}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"hideTimeOverride": false,
|
||||
"id": 44,
|
||||
"options": {
|
||||
"footer": {
|
||||
"countRows": false,
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true,
|
||||
"sortBy": [
|
||||
{
|
||||
"desc": true,
|
||||
"displayName": "Value"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pluginVersion": "9.4.8",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"exemplar": false,
|
||||
"expr": "sum by (exception_name) (\r\n max_over_time(http_server_request_duration_s_count{route=\"$route\", method=\"$method\", exception_name!=\"\"}[$__rate_interval])\r\n)",
|
||||
"format": "table",
|
||||
"instant": true,
|
||||
"interval": "",
|
||||
"legendFormat": "{{route}}",
|
||||
"range": false,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Unhandled Exceptions",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {
|
||||
"excludeByName": {
|
||||
"Time": true,
|
||||
"method": false
|
||||
},
|
||||
"indexByName": {
|
||||
"Time": 0,
|
||||
"Value": 2,
|
||||
"exception_name": 1
|
||||
},
|
||||
"renameByName": {
|
||||
"Value": "Requests",
|
||||
"exception_name": "Exception",
|
||||
"method": "Method",
|
||||
"route": "Route"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"fixedColor": "blue",
|
||||
"mode": "fixed"
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 4,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 9
|
||||
},
|
||||
"id": 42,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"max"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"pluginVersion": "9.4.8",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (status_code) (\r\n max_over_time(http_server_request_duration_s_count{route=\"$route\", method=\"$method\"}[$__rate_interval])\r\n )",
|
||||
"legendFormat": "Status {{status_code}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Requests HTTP Status Code",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"fixedColor": "green",
|
||||
"mode": "fixed"
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 4,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 13
|
||||
},
|
||||
"id": 48,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"max"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"pluginVersion": "9.4.8",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (scheme) (\r\n max_over_time(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[$__rate_interval])\r\n )",
|
||||
"legendFormat": "{{scheme}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Requests Secured",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"fixedColor": "purple",
|
||||
"mode": "fixed"
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 4,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 13
|
||||
},
|
||||
"id": 50,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"max"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"pluginVersion": "9.4.8",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"expr": "sum by (protocol) (\r\n max_over_time(http_server_request_duration_s_count{job=\"$job\", instance=\"$instance\", route=\"$route\", method=\"$method\"}[$__rate_interval])\r\n )",
|
||||
"legendFormat": "{{protocol}}",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Requests HTTP Protocol",
|
||||
"type": "stat"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"revision": 1,
|
||||
"schemaVersion": 38,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"dotnet",
|
||||
"prometheus",
|
||||
"aspnetcore"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"definition": "label_values(http_server_current_requests, job)",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Job",
|
||||
"multi": false,
|
||||
"name": "job",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(http_server_current_requests, job)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"current": {},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"definition": "label_values(http_server_current_requests{job=~\"$job\"}, instance)",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Instance",
|
||||
"multi": false,
|
||||
"name": "instance",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(http_server_current_requests{job=~\"$job\"}, instance)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"current": {},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"definition": "label_values(http_server_request_duration_s_count, route)",
|
||||
"description": "Route",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Route",
|
||||
"multi": false,
|
||||
"name": "route",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(http_server_request_duration_s_count, route)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"current": {},
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_MANAGED_PROMETHEUS_JAMESNK-TELEMETRY}"
|
||||
},
|
||||
"definition": "label_values(http_server_request_duration_s_count{route=~\"$route\"}, method)",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Method",
|
||||
"multi": false,
|
||||
"name": "method",
|
||||
"options": [],
|
||||
"query": {
|
||||
"query": "label_values(http_server_request_duration_s_count{route=~\"$route\"}, method)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 1,
|
||||
"type": "query"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-30m",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ASP.NET Core Endpoint",
|
||||
"uid": "NagEsjE4z",
|
||||
"version": 10,
|
||||
"weekStart": ""
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,892 +0,0 @@
|
||||
{
|
||||
"__inputs": [],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "7.4.3"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"id": "graph",
|
||||
"name": "Graph",
|
||||
"version": ""
|
||||
},
|
||||
{
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"name": "Prometheus",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": []
|
||||
},
|
||||
"editable": false,
|
||||
"gnetId": 13978,
|
||||
"graphTooltip": 0,
|
||||
"hideControls": false,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"refresh": "",
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"collapsed": false,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": true,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "(\n (1 - rate(node_cpu_seconds_total{job=\"node\", mode=\"idle\", instance=\"$instance\"}[$__interval]))\n/ ignoring(cpu) group_left\n count without (cpu)( node_cpu_seconds_total{job=\"node\", mode=\"idle\", instance=\"$instance\"})\n)\n",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 5,
|
||||
"legendFormat": "{{cpu}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "CPU Usage",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "percentunit",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "percentunit",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": 1,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 0,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 3,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "node_load1{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "1m load average",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "node_load5{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "5m load average",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "node_load15{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "15m load average",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "count(node_cpu_seconds_total{job=\"node\", instance=\"$instance\", mode=\"idle\"})",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "logical cores",
|
||||
"refId": "D"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Load Average",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": false,
|
||||
"title": "Dashboard Row",
|
||||
"titleSize": "h6",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"collapsed": false,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 9,
|
||||
"stack": true,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "(\n node_memory_MemTotal_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_MemFree_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_Buffers_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_Cached_bytes{job=\"node\", instance=\"$instance\"}\n)\n",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "memory used",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "node_memory_Buffers_bytes{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "memory buffers",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "node_memory_Cached_bytes{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "memory cached",
|
||||
"refId": "C"
|
||||
},
|
||||
{
|
||||
"expr": "node_memory_MemFree_bytes{job=\"node\", instance=\"$instance\"}",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "memory free",
|
||||
"refId": "D"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Memory Usage",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": false,
|
||||
"colors": [
|
||||
"rgba(50, 172, 45, 0.97)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(245, 54, 54, 0.9)"
|
||||
],
|
||||
"datasource": "$datasource",
|
||||
"format": "percent",
|
||||
"gauge": {
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"show": true,
|
||||
"thresholdLabels": false,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"gridPos": {},
|
||||
"id": 5,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"span": 3,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": false
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "100 -\n(\n avg(node_memory_MemAvailable_bytes{job=\"node\", instance=\"$instance\"})\n/\n avg(node_memory_MemTotal_bytes{job=\"node\", instance=\"$instance\"})\n* 100\n)\n",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": "80, 90",
|
||||
"title": "Memory Usage",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "80%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "current"
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": false,
|
||||
"title": "Dashboard Row",
|
||||
"titleSize": "h6",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"collapsed": false,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 0,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 6,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "/ read| written/",
|
||||
"yaxis": 1
|
||||
},
|
||||
{
|
||||
"alias": "/ io time/",
|
||||
"yaxis": 2
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(node_disk_read_bytes_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{device}} read",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "rate(node_disk_written_bytes_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{device}} written",
|
||||
"refId": "B"
|
||||
},
|
||||
{
|
||||
"expr": "rate(node_disk_io_time_seconds_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{device}} io time",
|
||||
"refId": "C"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Disk I/O",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 7,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [
|
||||
{
|
||||
"alias": "used",
|
||||
"color": "#E0B400"
|
||||
},
|
||||
{
|
||||
"alias": "available",
|
||||
"color": "#73BF69"
|
||||
}
|
||||
],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": true,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(\n max by (device) (\n node_filesystem_size_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n -\n node_filesystem_avail_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "used",
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"expr": "sum(\n max by (device) (\n node_filesystem_avail_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "available",
|
||||
"refId": "B"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Disk Space Usage",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": false,
|
||||
"title": "Dashboard Row",
|
||||
"titleSize": "h6",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"collapsed": false,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 0,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 8,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(node_network_receive_bytes_total{job=\"node\", instance=\"$instance\", device!=\"lo\"}[$__interval])",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{device}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Network Received",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "$datasource",
|
||||
"fill": 0,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {},
|
||||
"id": 9,
|
||||
"legend": {
|
||||
"alignAsTable": false,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": false,
|
||||
"show": true,
|
||||
"sideWidth": null,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"repeat": null,
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 6,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(node_network_transmit_bytes_total{job=\"node\", instance=\"$instance\", device!=\"lo\"}[$__interval])",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{device}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Network Transmitted",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "bytes",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": false,
|
||||
"title": "Dashboard Row",
|
||||
"titleSize": "h6",
|
||||
"type": "row"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 14,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"text": "Prometheus",
|
||||
"value": "Prometheus"
|
||||
},
|
||||
"hide": 0,
|
||||
"label": null,
|
||||
"name": "datasource",
|
||||
"options": [],
|
||||
"query": "prometheus",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"type": "datasource"
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": {},
|
||||
"datasource": "$datasource",
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": null,
|
||||
"multi": false,
|
||||
"name": "instance",
|
||||
"options": [],
|
||||
"query": "label_values(node_exporter_build_info{job=\"node\"}, instance)",
|
||||
"refresh": 2,
|
||||
"regex": "",
|
||||
"sort": 0,
|
||||
"tagValuesQuery": "",
|
||||
"tags": [],
|
||||
"tagsQuery": "",
|
||||
"type": "query",
|
||||
"useTags": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Node Exporter Quickstart and Dashboard",
|
||||
"version": 0,
|
||||
"description": "A quickstart to setup Prometheus Node Exporter with preconfigured dashboards, alerting rules, and recording rules."
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,14 +0,0 @@
|
||||
# https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: "default"
|
||||
orgId: 1
|
||||
folder: ""
|
||||
type: file
|
||||
disableDeletion: false
|
||||
editable: true
|
||||
allowUiUpdates: true
|
||||
updateIntervalSeconds: 5 # how often Grafana will scan for changed dashboards
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards # path to dashboards on disk
|
||||
@ -1,88 +0,0 @@
|
||||
# https://grafana.com/docs/grafana/latest/administration/provisioning/
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml
|
||||
# https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml
|
||||
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml
|
||||
- name: Prometheus
|
||||
type: prometheus
|
||||
typeName: Prometheus
|
||||
uid: prometheus-uid
|
||||
access: proxy
|
||||
orgId: 1
|
||||
url: http://prometheus:9090
|
||||
basicAuth: false
|
||||
isDefault: true
|
||||
readOnly: false
|
||||
user: ''
|
||||
database: ''
|
||||
version: 1
|
||||
editable: false
|
||||
jsonData:
|
||||
httpMethod: GET
|
||||
|
||||
- name: Jaeger
|
||||
type: jaeger
|
||||
access: proxy
|
||||
url: http://jaeger-all-in-one:16686
|
||||
editable: false
|
||||
uid: jaeger-uid
|
||||
|
||||
- name: Zipkin
|
||||
type: zipkin
|
||||
access: proxy
|
||||
url: http://zipkin-all-in-one:9411
|
||||
editable: false
|
||||
uid: zipkin-uid
|
||||
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml
|
||||
- name: Tempo
|
||||
type: tempo
|
||||
access: proxy
|
||||
orgId: 1
|
||||
url: http://tempo:3200
|
||||
basicAuth: false
|
||||
isDefault: false
|
||||
version: 1
|
||||
editable: false
|
||||
apiVersion: 1
|
||||
uid: tempo-uid
|
||||
jsonData:
|
||||
httpMethod: GET
|
||||
serviceMap:
|
||||
datasourceUid: prometheus-uid
|
||||
streamingEnabled:
|
||||
search: true
|
||||
|
||||
#https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml
|
||||
- name: Loki
|
||||
type: loki
|
||||
access: proxy
|
||||
uid: loki-uid
|
||||
url: http://loki:3100
|
||||
user: ''
|
||||
database: ''
|
||||
readOnly: false
|
||||
jsonData:
|
||||
derivedFields:
|
||||
- datasourceUid: tempo-uid
|
||||
matcherRegex: "^.*?traceI[d|D]=(\\w+).*$"
|
||||
name: traceId
|
||||
url: '$${__value.raw}'
|
||||
|
||||
- name: Kibana
|
||||
type: elasticsearch
|
||||
url: http://elasticsearch:9200
|
||||
access: proxy
|
||||
isDefault: false
|
||||
uid: kibana-uid
|
||||
jsonData:
|
||||
esVersion: 7
|
||||
timeField: "@timestamp"
|
||||
maxConcurrentShardRequests: 256
|
||||
interval: Daily
|
||||
logMessageField: "message" # Optional: Field for log messages
|
||||
logLevelField: "level" # Optional: Field for log levels
|
||||
editable: true
|
||||
@ -1,44 +0,0 @@
|
||||
# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/
|
||||
# https://github.com/grafana/loki/issues/2018#issuecomment-970789233
|
||||
# https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/
|
||||
# https://github.com/grafana/loki/blob/main/examples/getting-started/loki-config.yaml
|
||||
# https://github.com/grafana/loki/blob/main/cmd/loki/loki-local-config.yaml
|
||||
# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/#1-local-configuration-exampleyaml
|
||||
|
||||
---
|
||||
# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/#1-local-configuration-exampleyaml
|
||||
auth_enabled: false
|
||||
|
||||
# This is a complete configuration to deploy Loki backed by the filesystem.
|
||||
# The index will be shipped to the storage via tsdb-shipper.
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
|
||||
common:
|
||||
ring:
|
||||
instance_addr: 127.0.0.1
|
||||
kvstore:
|
||||
store: inmemory
|
||||
replication_factor: 1
|
||||
path_prefix: /tmp/loki
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2020-05-15
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
storage_config:
|
||||
filesystem:
|
||||
directory: /tmp/loki/chunks
|
||||
|
||||
# https://grafana.com/docs/loki/latest/send-data/otel/
|
||||
# https://grafana.com/docs/loki/latest/send-data/otel/#changing-the-default-mapping-of-otlp-to-loki-format
|
||||
limits_config:
|
||||
# this attribute should be `true` when we use `otlphttp/loki`, but if we want to use `loki component` from `opentelemetry-collector-contrib` it should be false.
|
||||
allow_structured_metadata: true
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/otel-collector-config.yaml
|
||||
# https://opentelemetry.io/docs/collector/configuration/
|
||||
# https://opentelemetry.io/docs/collector/architecture/
|
||||
# https://betterstack.com/community/guides/observability/opentelemetry-collector/
|
||||
# https://signoz.io/blog/opentelemetry-collector-complete-guide/
|
||||
|
||||
# This configuration sets up an OpenTelemetry Collector that receives trace data via the OTLP protocol over HTTP on port 4318, applies batch processing, and then exports the processed traces
|
||||
# to exporter components like `Jaeger` endpoint located at `jaeger-all-in-one:4317`. It also includes a health_check extension for monitoring the collector's status.
|
||||
|
||||
# Receivers in the OpenTelemetry Collector are components that collect telemetry data (traces, metrics, and logs) from various sources, such as instrumented applications or agents.
|
||||
# They act as entry points, converting incoming data into OpenTelemetry's internal format for processing and export.
|
||||
# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components
|
||||
# https://opentelemetry.io/docs/collector/architecture/#receivers
|
||||
# https://github.com/open-telemetry/opentelemetry-collector/blob/main/receiver/README.md
|
||||
# https://opentelemetry.io/docs/collector/configuration/#receivers
|
||||
receivers:
|
||||
# supported receivers
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver
|
||||
# instead of specifying details explicitly we can just use `otlp` and it uses both grpc and http
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
# prometheus:
|
||||
# config:
|
||||
# scrape_configs:
|
||||
# - job_name: 'node-exporter'
|
||||
# scrape_interval: 10s
|
||||
# static_configs:
|
||||
# - targets: [ 'node-exporter:9100' ]
|
||||
|
||||
|
||||
# Processors in the OpenTelemetry Collector modify and enhance telemetry data by filtering, transforming, enriching, or batching it to prepare it for export.
|
||||
# https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor
|
||||
processors:
|
||||
batch: # Batches logs for better performance
|
||||
|
||||
# - Exporters in the OpenTelemetry Collector send processed telemetry data to backend systems like observability platforms, databases, or cloud services for storage, visualization, and analysis.
|
||||
# - The `key` follows the `type/name` format, where `type` specifies the exporter `type` (e.g., otlp, kafka, prometheus), and `name` (optional) can be appended to provide a unique name for multiple instance of the same type
|
||||
# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components
|
||||
# https://opentelemetry.io/docs/collector/architecture/#exporters
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter
|
||||
# https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter
|
||||
# https://opentelemetry.io/docs/collector/configuration/#exporters
|
||||
exporters:
|
||||
|
||||
# valid values: [prometheusremotewrite zipkin otlphttp file kafka prometheus debug nop otlp opencensus]
|
||||
|
||||
# Prometheus exporter metrics
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
|
||||
prometheusremotewrite:
|
||||
endpoint: "http://prometheus:9090/api/v1/write"
|
||||
|
||||
# https://grafana.com/docs/loki/latest/send-data/otel/
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/lokiexporter/README.md
|
||||
otlphttp/loki:
|
||||
endpoint: "http://loki:3100/otlp"
|
||||
tls:
|
||||
insecure: true
|
||||
|
||||
# # we can also use `loki component` from `opentelemetry-collector-contrib` if we don't want to use builtin `otlphttp` exporter type and `http://loki:3100/otlp` loki endpoint
|
||||
# loki:
|
||||
# endpoint: "http://loki:3100/loki/api/v1/push"
|
||||
# tls:
|
||||
# insecure: true
|
||||
|
||||
debug:
|
||||
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/elasticsearchexporter
|
||||
# using `elasticsearch` from `opentelemetry-collector-contrib` components because it doesn't exist in `opentelemetry-collector`
|
||||
elasticsearch:
|
||||
endpoint: "http://elasticsearch:9200"
|
||||
|
||||
zipkin:
|
||||
endpoint: "http://zipkin-all-in-one:9411/api/v2/spans"
|
||||
format: proto
|
||||
|
||||
# export collected telemetry traces to jaeger OTLP grpc port, we can send data to other available endpoints and ports on jaeger as well
|
||||
otlp/jaeger:
|
||||
endpoint: "http://jaeger-all-in-one:4317"
|
||||
tls:
|
||||
insecure: true
|
||||
|
||||
otlp/tempo:
|
||||
endpoint: "http://tempo:4317"
|
||||
tls:
|
||||
insecure: true
|
||||
|
||||
# seq-otlp:
|
||||
# endpoint: "http://seq:5341/ingest/otlp"
|
||||
|
||||
# https://opentelemetry.io/docs/collector/configuration/#extensions
|
||||
# https://github.com/open-telemetry/opentelemetry-collector/blob/main/extension/README.md
|
||||
extensions:
|
||||
pprof:
|
||||
endpoint: 0.0.0.0:1888
|
||||
zpages:
|
||||
endpoint: 0.0.0.0:55679
|
||||
health_check:
|
||||
endpoint: 0.0.0.0:13133
|
||||
|
||||
# - The service section is used to configure what components are enabled in the Collector based on the configuration found in the receivers, processors, exporters, and extensions sections.
|
||||
# - If a component is configured, but not defined within the service section, then it’s not enabled.
|
||||
# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components
|
||||
# https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/README.md
|
||||
# https://opentelemetry.io/docs/collector/architecture/
|
||||
# https://opentelemetry.io/docs/collector/configuration/#service
|
||||
service:
|
||||
# The `service.extensions` subsection determines which of the configured extensions will be enabled
|
||||
extensions: [pprof, zpages, health_check]
|
||||
# The `service.pipeline` Each pipeline starts with one or more receivers collecting data, which is then processed sequentially by processors (applying transformations, filtering, or sampling).
|
||||
# The processed data is finally sent to all configured exporters, ensuring each receives a copy. Components must be pre-configured in their respective sections before being used in a pipeline.
|
||||
# pipeline activate predefined components, defined components are disabled by default
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
# https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection
|
||||
exporters: [debug, zipkin, otlp/jaeger, otlp/tempo]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [debug, prometheusremotewrite, prometheus]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [otlphttp/loki, elasticsearch]
|
||||
@ -1,48 +0,0 @@
|
||||
# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/prometheus.yaml
|
||||
# https://prometheus.io/docs/introduction/first_steps/
|
||||
# https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
|
||||
global:
|
||||
scrape_interval: 5s
|
||||
|
||||
scrape_configs:
|
||||
# when we use otel-collector we should comment other jobs in prometheus config, and we read configs from `otel-collector-config`
|
||||
- job_name: "otel-collector"
|
||||
scrape_interval: 10s
|
||||
static_configs:
|
||||
# otel-collector Prometheus exporter metrics
|
||||
- targets: [ 'otel-collector:8889' ]
|
||||
- targets: [ 'otel-collector:8888' ]
|
||||
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["prometheus:9090"]
|
||||
|
||||
# # https://prometheus.io/docs/guides/node-exporter/
|
||||
# # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
# - job_name: "node-exporter"
|
||||
# static_configs:
|
||||
# - targets: [ 'node-exporter:9100' ]
|
||||
|
||||
# # if we don't use otel collector we should uncomment this
|
||||
# # scrap application metrics
|
||||
# # http://localhost:4000/metrics by AddPrometheusExporter()
|
||||
# - job_name: vertical-slice-template-api
|
||||
# scrape_interval: 10s
|
||||
# metrics_path: /metrics
|
||||
# static_configs:
|
||||
# - targets: ['host.docker.internal:4000']
|
||||
#
|
||||
# # if we don't use otel collector we should uncomment this
|
||||
# # scrap application health metrics
|
||||
# # http://localhost:4000/health/metrics by AddPrometheusExporter()
|
||||
# - job_name: vertical-slice-template-api-healthchecks
|
||||
# scrape_interval: 10s
|
||||
# metrics_path: /health/metrics
|
||||
# static_configs:
|
||||
# - targets: ['host.docker.internal:4000']
|
||||
|
||||
## https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/prometheus.yaml
|
||||
# - job_name: 'tempo'
|
||||
# static_configs:
|
||||
# - targets: [ 'tempo:3200' ]
|
||||
@ -1,49 +0,0 @@
|
||||
# https://grafana.com/docs/tempo/latest/configuration/
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/local/tempo.yaml
|
||||
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/tempo.yaml
|
||||
stream_over_http_enabled: true
|
||||
server:
|
||||
http_listen_port: 3200
|
||||
log_level: info
|
||||
|
||||
distributor:
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: "tempo:4317"
|
||||
|
||||
ingester:
|
||||
max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
|
||||
|
||||
compactor:
|
||||
compaction:
|
||||
block_retention: 1h # overall Tempo trace retention. set for demo purposes
|
||||
|
||||
metrics_generator:
|
||||
registry:
|
||||
external_labels:
|
||||
source: tempo
|
||||
cluster: docker-compose
|
||||
storage:
|
||||
path: /var/tempo/generator/wal
|
||||
remote_write:
|
||||
- url: http://prometheus:9090/api/v1/write
|
||||
send_exemplars: true
|
||||
traces_storage:
|
||||
path: /var/tempo/generator/traces
|
||||
|
||||
storage:
|
||||
trace:
|
||||
backend: local # backend configuration to use
|
||||
wal:
|
||||
path: /var/tempo/wal # where to store the wal locally
|
||||
local:
|
||||
path: /var/tempo/blocks
|
||||
|
||||
overrides:
|
||||
defaults:
|
||||
metrics_generator:
|
||||
processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator
|
||||
generate_native_histograms: both
|
||||
@ -1,362 +0,0 @@
|
||||
# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml
|
||||
# ref: https://github.com/joaofbantunes/DotNetMicroservicesObservabilitySample/blob/main/docker-compose.yml
|
||||
# ref: https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/docker-compose.yml
|
||||
# https://github.com/grafana/intro-to-mltp
|
||||
# https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to
|
||||
|
||||
|
||||
name: booking-microservices-infrastructure
|
||||
|
||||
services:
|
||||
#######################################################
|
||||
# rabbitmq
|
||||
#######################################################
|
||||
rabbitmq:
|
||||
image: rabbitmq:management
|
||||
container_name: rabbitmq
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5672:5672"
|
||||
- "15672:15672"
|
||||
# volumes:
|
||||
# - rabbitmq:/var/lib/rabbitmq
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
#######################################################
|
||||
# postgres
|
||||
#######################################################
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
container_name: postgres
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '5432:5432'
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
command:
|
||||
- "postgres"
|
||||
- "-c"
|
||||
- "wal_level=logical"
|
||||
- "-c"
|
||||
- "max_prepared_transactions=10"
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
#######################################################
|
||||
# EventStoreDB
|
||||
#######################################################
|
||||
eventstore:
|
||||
container_name: eventstore
|
||||
image: eventstore/eventstore:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- EVENTSTORE_CLUSTER_SIZE=1
|
||||
- EVENTSTORE_RUN_PROJECTIONS=All
|
||||
- EVENTSTORE_START_STANDARD_PROJECTIONS=True
|
||||
- EVENTSTORE_HTTP_PORT=2113
|
||||
- EVENTSTORE_INSECURE=True
|
||||
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=True
|
||||
ports:
|
||||
- "2113:2113"
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # Mongo
|
||||
# #######################################################
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
container_name: mongo
|
||||
restart: unless-stopped
|
||||
# environment:
|
||||
# - MONGO_INITDB_ROOT_USERNAME=root
|
||||
# - MONGO_INITDB_ROOT_PASSWORD=secret
|
||||
ports:
|
||||
- 27017:27017
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # Redis
|
||||
# #######################################################
|
||||
redis:
|
||||
image: redis
|
||||
container_name: redis
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 6379:6379
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # jaeger
|
||||
# # https://www.jaegertracing.io/docs/1.64/deployment/
|
||||
# # https://www.jaegertracing.io/docs/1.6/deployment/
|
||||
# #######################################################
|
||||
jaeger-all-in-one:
|
||||
image: jaegertracing/all-in-one:latest
|
||||
container_name: jaeger-all-in-one
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "6831:6831/udp" # UDP port for Jaeger agent
|
||||
- "16686:16686" # endpoints and Jaeger UI
|
||||
- "14268:14268" # HTTP port for accept trace spans directly from clients
|
||||
- "14317:4317" # OTLP gRPC receiver for jaeger
|
||||
- "14318:4318" # OTLP http receiver for jaeger
|
||||
# - "9411" # Accepts Zipkin spans - /api/v2/spans
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # zipkin
|
||||
# # https://zipkin.io/pages/quickstart
|
||||
# #######################################################
|
||||
zipkin-all-in-one:
|
||||
image: openzipkin/zipkin:latest
|
||||
container_name: zipkin-all-in-one
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9411:9411"
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # otel-collector
|
||||
# # https://opentelemetry.io/docs/collector/installation/
|
||||
# # https://github.com/open-telemetry/opentelemetry-collector
|
||||
# # https://github.com/open-telemetry/opentelemetry-collector-contrib
|
||||
# # we can use none contrib docker `otel/opentelemetry-collector` version from `https://github.com/open-telemetry/opentelemetry-collector` repository but,
|
||||
# # if we need more components like `elasticsearch` we should use `otel/opentelemetry-collector-contrib` image of `https://github.com/open-telemetry/opentelemetry-collector-contrib` repository.
|
||||
# #######################################################
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector-contrib:latest
|
||||
container_name: otel-collector
|
||||
restart: unless-stopped
|
||||
command: ["--config=/etc/otelcol-contrib/config.yaml"]
|
||||
volumes:
|
||||
- ./../configs/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
|
||||
ports:
|
||||
- "11888:1888" # pprof extension
|
||||
- "8888:8888" # Prometheus metrics exposed by the Collector
|
||||
- "8889:8889" # Prometheus exporter metrics
|
||||
- "13133:13133" # health_check extension
|
||||
- "4317:4317" # OTLP gRPC receiver
|
||||
- "4318:4318" # OTLP http receiver
|
||||
- "55679:55679" # zpages extension
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # prometheus
|
||||
# # https://prometheus.io/docs/introduction/first_steps/
|
||||
# # https://prometheus.io/docs/prometheus/3.1/installation/
|
||||
# # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
# #######################################################
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./../configs/prometheus.yaml:/etc/prometheus/prometheus.yml
|
||||
# to passe one flag, such as "--log.level=debug" or "--web.enable-remote-write-receiver", we need to override the whole command, as we can't just pass one extra argument
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
- "--storage.tsdb.path=/prometheus"
|
||||
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
|
||||
- "--web.console.templates=/usr/share/prometheus/consoles"
|
||||
# need this for the OpenTelemetry collector to be able to put metrics into Prometheus
|
||||
- "--web.enable-remote-write-receiver"
|
||||
# - "--log.level=debug"
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # node-exporter
|
||||
# # https://prometheus.io/docs/guides/node-exporter/
|
||||
# # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
# #######################################################
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--path.sysfs=/host/sys'
|
||||
ports:
|
||||
- "9101:9100"
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # grafana
|
||||
# # https://grafana.com/docs/grafana/latest/administration/provisioning/
|
||||
# # https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/
|
||||
# # https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/
|
||||
# # https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml
|
||||
# #######################################################
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||
- GF_FEATURE_TOGGLES_ENABLE=traceqlEditor
|
||||
# - GF_AUTH_ANONYMOUS_ENABLED=true
|
||||
# - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||
# - GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||
depends_on:
|
||||
- prometheus
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./../configs/grafana/provisioning:/etc/grafana/provisioning
|
||||
- ./../configs/grafana/dashboards:/var/lib/grafana/dashboards
|
||||
## https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/
|
||||
# - ./../configs/grafana/grafana.ini:/etc/grafana/grafana.ini
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # tempo
|
||||
# # https://github.com/grafana/tempo/blob/main/example/docker-compose/otel-collector/docker-compose.yaml
|
||||
# # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared
|
||||
# # https://github.com/grafana/tempo/blob/main/example/docker-compose/local
|
||||
# # https://github.com/grafana/tempo/tree/main/example/docker-compose
|
||||
# #######################################################
|
||||
tempo:
|
||||
image: grafana/tempo:latest
|
||||
container_name: tempo
|
||||
restart: unless-stopped
|
||||
command: [ "-config.file=/etc/tempo.yaml" ]
|
||||
volumes:
|
||||
- ./../configs/tempo.yaml:/etc/tempo.yaml
|
||||
ports:
|
||||
- "3200" # tempo
|
||||
- "24317:4317" # otlp grpc
|
||||
- "24318:4318" # otlp http
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # loki
|
||||
# # https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/
|
||||
# # https://github.com/grafana/loki/blob/main/production/docker-compose.yaml
|
||||
# # https://github.com/grafana/loki/blob/main/examples/getting-started/docker-compose.yaml
|
||||
# #######################################################
|
||||
loki:
|
||||
image: grafana/loki:latest
|
||||
hostname: loki
|
||||
container_name: loki
|
||||
ports:
|
||||
- "3100:3100"
|
||||
command: -config.file=/etc/loki/local-config.yaml
|
||||
volumes:
|
||||
- ./../configs/loki-config.yaml:/etc/loki/local-config.yaml
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # elasticsearch
|
||||
# # https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html#docker-compose-file
|
||||
# #######################################################
|
||||
elasticsearch:
|
||||
container_name: elasticsearch
|
||||
restart: unless-stopped
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- cluster.name=docker-cluster
|
||||
- node.name=docker-node
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- xpack.security.enabled=false
|
||||
- xpack.security.http.ssl.enabled=false
|
||||
- xpack.security.transport.ssl.enabled=false
|
||||
- network.host=0.0.0.0
|
||||
- http.port=9200
|
||||
- transport.host=localhost
|
||||
- bootstrap.memory_lock=true
|
||||
- cluster.routing.allocation.disk.threshold_enabled=false
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- elastic-data:/usr/share/elasticsearch/data
|
||||
ports:
|
||||
- ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200}
|
||||
- 9300:9300
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # kibana
|
||||
# # https://www.elastic.co/guide/en/kibana/current/docker.html
|
||||
# #######################################################
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:8.17.0
|
||||
container_name: kibana
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
|
||||
ports:
|
||||
- ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601}
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # cadvisor
|
||||
# #######################################################
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:latest
|
||||
container_name: cadvisor
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
devices:
|
||||
- /dev/kmsg
|
||||
networks:
|
||||
- infrastructure
|
||||
|
||||
|
||||
networks:
|
||||
infrastructure:
|
||||
name: infrastructure
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
elastic-data:
|
||||
postgres-data:
|
||||
@ -1,362 +1,140 @@
|
||||
name: booking-microservices
|
||||
|
||||
version: "3.3"
|
||||
services:
|
||||
|
||||
#######################################################
|
||||
# rabbitmq
|
||||
#######################################################
|
||||
rabbitmq:
|
||||
image: rabbitmq:management
|
||||
container_name: rabbitmq
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5672:5672"
|
||||
- "15672:15672"
|
||||
# volumes:
|
||||
# - rabbitmq:/var/lib/rabbitmq
|
||||
networks:
|
||||
- booking
|
||||
|
||||
#######################################################
|
||||
# postgres
|
||||
#######################################################
|
||||
######################################################
|
||||
# Postgres
|
||||
######################################################
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
container_name: postgres
|
||||
restart: unless-stopped
|
||||
restart: on-failure
|
||||
ports:
|
||||
- '5432:5432'
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
command:
|
||||
- "postgres"
|
||||
- "-c"
|
||||
- "wal_level=logical"
|
||||
- "-c"
|
||||
- "max_prepared_transactions=10"
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# EventStoreDB
|
||||
#######################################################
|
||||
#######################################################
|
||||
# Rabbitmq
|
||||
#######################################################
|
||||
rabbitmq:
|
||||
container_name: rabbitmq
|
||||
image: rabbitmq:3-management
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5672:5672
|
||||
- 15672:15672
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# Jaeger
|
||||
#######################################################
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one
|
||||
container_name: jaeger
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- booking
|
||||
ports:
|
||||
- 5775:5775/udp
|
||||
- 5778:5778
|
||||
- 6831:6831/udp
|
||||
- 6832:6832/udp
|
||||
- 9411:9411
|
||||
- 14268:14268
|
||||
- 16686:16686
|
||||
|
||||
|
||||
#######################################################
|
||||
# EventStoreDB
|
||||
#######################################################
|
||||
eventstore:
|
||||
container_name: eventstore
|
||||
image: eventstore/eventstore:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- EVENTSTORE_CLUSTER_SIZE=1
|
||||
- EVENTSTORE_RUN_PROJECTIONS=All
|
||||
- EVENTSTORE_START_STANDARD_PROJECTIONS=True
|
||||
- EVENTSTORE_HTTP_PORT=2113
|
||||
- EVENTSTORE_INSECURE=True
|
||||
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=True
|
||||
ports:
|
||||
- "2113:2113"
|
||||
networks:
|
||||
- booking
|
||||
container_name: eventstore
|
||||
image: eventstore/eventstore:21.2.0-buster-slim
|
||||
restart: on-failure
|
||||
environment:
|
||||
- EVENTSTORE_CLUSTER_SIZE=1
|
||||
- EVENTSTORE_RUN_PROJECTIONS=All
|
||||
- EVENTSTORE_START_STANDARD_PROJECTIONS=true
|
||||
- EVENTSTORE_EXT_TCP_PORT=1113
|
||||
- EVENTSTORE_EXT_HTTP_PORT=2113
|
||||
- EVENTSTORE_INSECURE=true
|
||||
- EVENTSTORE_ENABLE_EXTERNAL_TCP=true
|
||||
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true
|
||||
ports:
|
||||
- '1113:1113'
|
||||
- '2113:2113'
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# Mongo
|
||||
#######################################################
|
||||
#######################################################
|
||||
# Mongo
|
||||
#######################################################
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
image: mongo:5
|
||||
container_name: mongo
|
||||
restart: unless-stopped
|
||||
# environment:
|
||||
# - MONGO_INITDB_ROOT_USERNAME=root
|
||||
# - MONGO_INITDB_ROOT_PASSWORD=secret
|
||||
networks:
|
||||
- booking
|
||||
ports:
|
||||
- 27017:27017
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# Redis
|
||||
#######################################################
|
||||
redis:
|
||||
image: redis
|
||||
container_name: redis
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 6379:6379
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# jaeger
|
||||
# https://www.jaegertracing.io/docs/1.64/deployment/
|
||||
# https://www.jaegertracing.io/docs/1.6/deployment/
|
||||
#######################################################
|
||||
jaeger-all-in-one:
|
||||
image: jaegertracing/all-in-one:latest
|
||||
container_name: jaeger-all-in-one
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "6831:6831/udp" # UDP port for Jaeger agent
|
||||
- "16686:16686" # endpoints and Jaeger UI
|
||||
- "14268:14268" # HTTP port for accept trace spans directly from clients
|
||||
- "14317:4317" # OTLP gRPC receiver for jaeger
|
||||
- "14318:4318" # OTLP http receiver for jaeger
|
||||
# - "9411" # Accepts Zipkin spans - /api/v2/spans
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# zipkin
|
||||
# https://zipkin.io/pages/quickstart
|
||||
#######################################################
|
||||
zipkin-all-in-one:
|
||||
image: openzipkin/zipkin:latest
|
||||
container_name: zipkin-all-in-one
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9411:9411"
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# otel-collector
|
||||
# https://opentelemetry.io/docs/collector/installation/
|
||||
# https://github.com/open-telemetry/opentelemetry-collector
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib
|
||||
# we can use none contrib docker `otel/opentelemetry-collector` version from `https://github.com/open-telemetry/opentelemetry-collector` repository but,
|
||||
# if we need more components like `elasticsearch` we should use `otel/opentelemetry-collector-contrib` image of `https://github.com/open-telemetry/opentelemetry-collector-contrib` repository.
|
||||
#######################################################
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector-contrib:latest
|
||||
container_name: otel-collector
|
||||
restart: unless-stopped
|
||||
command: ["--config=/etc/otelcol-contrib/config.yaml"]
|
||||
volumes:
|
||||
- ./../configs/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
|
||||
ports:
|
||||
- "11888:1888" # pprof extension
|
||||
- "8888:8888" # Prometheus metrics exposed by the Collector
|
||||
- "8889:8889" # Prometheus exporter metrics
|
||||
- "13133:13133" # health_check extension
|
||||
- "4317:4317" # OTLP gRPC receiver
|
||||
- "4318:4318" # OTLP http receiver
|
||||
- "55679:55679" # zpages extension
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# prometheus
|
||||
# https://prometheus.io/docs/introduction/first_steps/
|
||||
# https://prometheus.io/docs/prometheus/3.1/installation/
|
||||
# https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
#######################################################
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./../configs/prometheus.yaml:/etc/prometheus/prometheus.yml
|
||||
# to passe one flag, such as "--log.level=debug" or "--web.enable-remote-write-receiver", we need to override the whole command, as we can't just pass one extra argument
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
- "--storage.tsdb.path=/prometheus"
|
||||
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
|
||||
- "--web.console.templates=/usr/share/prometheus/consoles"
|
||||
# need this for the OpenTelemetry collector to be able to put metrics into Prometheus
|
||||
- "--web.enable-remote-write-receiver"
|
||||
# - "--log.level=debug"
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# node-exporter
|
||||
# https://prometheus.io/docs/guides/node-exporter/
|
||||
# https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/
|
||||
#######################################################
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--path.sysfs=/host/sys'
|
||||
ports:
|
||||
- "9101:9100"
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# grafana
|
||||
# https://grafana.com/docs/grafana/latest/administration/provisioning/
|
||||
# https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/
|
||||
# https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/
|
||||
# https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml
|
||||
#######################################################
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||
- GF_FEATURE_TOGGLES_ENABLE=traceqlEditor
|
||||
# - GF_AUTH_ANONYMOUS_ENABLED=true
|
||||
# - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
||||
# - GF_AUTH_DISABLE_LOGIN_FORM=true
|
||||
depends_on:
|
||||
- prometheus
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./../configs/grafana/provisioning:/etc/grafana/provisioning
|
||||
- ./../configs/grafana/dashboards:/var/lib/grafana/dashboards
|
||||
## https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/
|
||||
# - ./../configs/grafana/grafana.ini:/etc/grafana/grafana.ini
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# tempo
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/otel-collector/docker-compose.yaml
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared
|
||||
# https://github.com/grafana/tempo/blob/main/example/docker-compose/local
|
||||
# https://github.com/grafana/tempo/tree/main/example/docker-compose
|
||||
#######################################################
|
||||
tempo:
|
||||
image: grafana/tempo:latest
|
||||
container_name: tempo
|
||||
restart: unless-stopped
|
||||
command: [ "-config.file=/etc/tempo.yaml" ]
|
||||
volumes:
|
||||
- ./../configs/tempo.yaml:/etc/tempo.yaml
|
||||
ports:
|
||||
- "3200" # tempo
|
||||
- "24317:4317" # otlp grpc
|
||||
- "24318:4318" # otlp http
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# loki
|
||||
# https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/
|
||||
# https://github.com/grafana/loki/blob/main/production/docker-compose.yaml
|
||||
# https://github.com/grafana/loki/blob/main/examples/getting-started/docker-compose.yaml
|
||||
#######################################################
|
||||
loki:
|
||||
image: grafana/loki:latest
|
||||
hostname: loki
|
||||
container_name: loki
|
||||
ports:
|
||||
- "3100:3100"
|
||||
command: -config.file=/etc/loki/local-config.yaml
|
||||
volumes:
|
||||
- ./../configs/loki-config.yaml:/etc/loki/local-config.yaml
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# elasticsearch
|
||||
# https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html#docker-compose-file
|
||||
#######################################################
|
||||
#######################################################
|
||||
# Elastic Search
|
||||
#######################################################
|
||||
elasticsearch:
|
||||
container_name: elasticsearch
|
||||
restart: unless-stopped
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- cluster.name=docker-cluster
|
||||
- node.name=docker-node
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- xpack.security.enabled=false
|
||||
- xpack.security.http.ssl.enabled=false
|
||||
- xpack.security.transport.ssl.enabled=false
|
||||
- network.host=0.0.0.0
|
||||
- http.port=9200
|
||||
- transport.host=localhost
|
||||
- bootstrap.memory_lock=true
|
||||
- cluster.routing.allocation.disk.threshold_enabled=false
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- elastic-data:/usr/share/elasticsearch/data
|
||||
ports:
|
||||
- ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200}
|
||||
- 9300:9300
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# kibana
|
||||
# https://www.elastic.co/guide/en/kibana/current/docker.html
|
||||
#######################################################
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:8.17.0
|
||||
container_name: kibana
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
|
||||
ports:
|
||||
- ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601}
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# cadvisor
|
||||
#######################################################
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:latest
|
||||
container_name: cadvisor
|
||||
container_name: elasticsearch
|
||||
image: elasticsearch:7.17.9
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- 9200:9200
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
devices:
|
||||
- /dev/kmsg
|
||||
- elasticsearch-data:/usr/share/elasticsearch/data
|
||||
environment:
|
||||
- xpack.monitoring.enabled=true
|
||||
- xpack.watcher.enabled=false
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- discovery.type=single-node
|
||||
networks:
|
||||
- booking
|
||||
|
||||
#######################################################
|
||||
# Kibana
|
||||
#######################################################
|
||||
kibana:
|
||||
container_name: kibana
|
||||
image: kibana:7.17.9
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5601:5601
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
environment:
|
||||
- ELASTICSEARCH_URL=elasticsearch:9200
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
######################################################
|
||||
# Api-Gateway
|
||||
# Gateway
|
||||
######################################################
|
||||
api-gateway:
|
||||
image: api-gateway
|
||||
gateway:
|
||||
image: gateway
|
||||
build:
|
||||
args:
|
||||
Version: "1"
|
||||
context: ../../
|
||||
dockerfile: src/ApiGateway/Dockerfile
|
||||
container_name: api-gateway
|
||||
dockerfile: src/ApiGateway/dev.Dockerfile
|
||||
container_name: gateway
|
||||
ports:
|
||||
- "5001:80"
|
||||
- "5000:443"
|
||||
@ -382,7 +160,7 @@ services:
|
||||
args:
|
||||
Version: "1"
|
||||
context: ../../
|
||||
dockerfile: src/Services/Flight/Dockerfile
|
||||
dockerfile: src/Services/Flight/dev.Dockerfile
|
||||
container_name: flight
|
||||
ports:
|
||||
- 5004:80
|
||||
@ -408,7 +186,7 @@ services:
|
||||
args:
|
||||
Version: "1"
|
||||
context: ../../
|
||||
dockerfile: src/Services/Identity/Dockerfile
|
||||
dockerfile: src/Services/Identity/dev.Dockerfile
|
||||
container_name: identity
|
||||
ports:
|
||||
- 6005:80
|
||||
@ -435,7 +213,7 @@ services:
|
||||
args:
|
||||
Version: "1"
|
||||
context: ../../
|
||||
dockerfile: src/Services/Passenger/Dockerfile
|
||||
dockerfile: src/Services/Passenger/dev.Dockerfile
|
||||
container_name: passenger
|
||||
ports:
|
||||
- 6012:80
|
||||
@ -462,7 +240,7 @@ services:
|
||||
args:
|
||||
Version: "1"
|
||||
context: ../../
|
||||
dockerfile: src/Services/Booking/Dockerfile
|
||||
dockerfile: src/Services/Booking/dev.Dockerfile
|
||||
container_name: booking
|
||||
ports:
|
||||
- 6010:80
|
||||
@ -482,11 +260,9 @@ services:
|
||||
|
||||
networks:
|
||||
booking:
|
||||
name: booking
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
elastic-data:
|
||||
postgres-data:
|
||||
elasticsearch-data:
|
||||
|
||||
|
||||
|
||||
|
||||
150
deployments/docker-compose/infrastracture.yaml
Normal file
150
deployments/docker-compose/infrastracture.yaml
Normal file
@ -0,0 +1,150 @@
|
||||
version: "3.3"
|
||||
services:
|
||||
|
||||
#######################################################
|
||||
# Rabbitmq
|
||||
#######################################################
|
||||
rabbitmq:
|
||||
container_name: rabbitmq
|
||||
image: rabbitmq:3-management
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5672:5672
|
||||
- 15672:15672
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# Postgres
|
||||
######################################################
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
container_name: postgres
|
||||
restart: on-failure
|
||||
ports:
|
||||
- '5432:5432'
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
networks:
|
||||
- booking
|
||||
|
||||
#######################################################
|
||||
# Jaeger
|
||||
#######################################################
|
||||
jaeger:
|
||||
container_name: jaeger
|
||||
image: jaegertracing/all-in-one
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- booking
|
||||
ports:
|
||||
- 5775:5775/udp
|
||||
- 5778:5778
|
||||
- 6831:6831/udp
|
||||
- 6832:6832/udp
|
||||
- 9411:9411
|
||||
- 14268:14268
|
||||
- 16686:16686
|
||||
|
||||
|
||||
# #######################################################
|
||||
# # EventStoreDB
|
||||
# #######################################################
|
||||
# #https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to
|
||||
|
||||
eventstore:
|
||||
container_name: eventstore
|
||||
image: eventstore/eventstore:21.2.0-buster-slim
|
||||
restart: on-failure
|
||||
environment:
|
||||
- EVENTSTORE_CLUSTER_SIZE=1
|
||||
- EVENTSTORE_RUN_PROJECTIONS=All
|
||||
- EVENTSTORE_START_STANDARD_PROJECTIONS=true
|
||||
- EVENTSTORE_EXT_TCP_PORT=1113
|
||||
- EVENTSTORE_EXT_HTTP_PORT=2113
|
||||
- EVENTSTORE_INSECURE=true
|
||||
- EVENTSTORE_ENABLE_EXTERNAL_TCP=true
|
||||
- EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true
|
||||
ports:
|
||||
- '1113:1113'
|
||||
- '2113:2113'
|
||||
networks:
|
||||
- booking
|
||||
|
||||
|
||||
#######################################################
|
||||
# Mongo
|
||||
#######################################################
|
||||
mongo:
|
||||
image: mongo:5
|
||||
container_name: mongo
|
||||
restart: unless-stopped
|
||||
# environment:
|
||||
# - MONGO_INITDB_ROOT_USERNAME=root
|
||||
# - MONGO_INITDB_ROOT_PASSWORD=secret
|
||||
networks:
|
||||
- booking
|
||||
ports:
|
||||
- 27017:27017
|
||||
|
||||
|
||||
#######################################################
|
||||
# Elastic Search
|
||||
#######################################################
|
||||
elasticsearch:
|
||||
container_name: elasticsearch
|
||||
image: elasticsearch:7.17.9
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 9200:9200
|
||||
volumes:
|
||||
- elasticsearch-data:/usr/share/elasticsearch/data
|
||||
environment:
|
||||
- xpack.monitoring.enabled=true
|
||||
- xpack.watcher.enabled=false
|
||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- discovery.type=single-node
|
||||
networks:
|
||||
- booking
|
||||
|
||||
#######################################################
|
||||
# Kibana
|
||||
#######################################################
|
||||
kibana:
|
||||
container_name: kibana
|
||||
image: kibana:7.17.9
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5601:5601
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
environment:
|
||||
- ELASTICSEARCH_URL=http://localhost:9200
|
||||
networks:
|
||||
- booking
|
||||
|
||||
#######################################################
|
||||
# Redis
|
||||
#######################################################
|
||||
redis:
|
||||
image: redis
|
||||
container_name: redis
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- booking
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
|
||||
|
||||
networks:
|
||||
booking:
|
||||
|
||||
volumes:
|
||||
elasticsearch-data:
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,16 +1,40 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
# #######################################################
|
||||
# Secret
|
||||
# #######################################################
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: letsencrypt-staging
|
||||
name: booking-tls
|
||||
namespace: default
|
||||
type: kubernetes.io/tls
|
||||
data:
|
||||
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGS1RDQ0F4R2dBd0lCQWdJVUZhOWxoMTc2enQxK3pSb013TEpoVWI5YUVHc3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3SkRFaU1DQUdBMVVFQXd3WlltOXZhMmx1WnkxdGFXTnliM05sY25acFkyVnpMbU52YlRBZUZ3MHlNekF5DQpNakV4TVRRM01UQmFGdzB5TkRBeU1qRXhNVFEzTVRCYU1DUXhJakFnQmdOVkJBTU1HV0p2YjJ0cGJtY3RiV2xqDQpjbTl6WlhKMmFXTmxjeTVqYjIwd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUURVDQpqZ01vWHh0YXZzTVhVb0h2YTBXVWZSeWJKTVVnR1NQbml3ZWF3eW41RmlnVVR4Nmd2NlZ2T3pxU21HWjE4NVA0DQpVSWJXQ3VkOVdqRUNFU0pVSkI0cVpiUmlEWUlNQWQyMzM2Y2k1d0RzbkRGVXpuWHRNOWc1VUZmS3dPd2VPVmN2DQpqc1N0WWY2Szl3ZC8xaXRMb3JIeDV0eEVQblBkVGRGR0ZqOVlVT2t1MmM1VllIMk9LaUk3ampDaDAwc3RaZHo4DQp0NWkvL0t2MjdQRHQ2REc3L3VuMHlnVEcxa21NVU1QcnBSQmVIbFFNWWZ0N09xTTNHSHJEZml1SDdjNVpGNWM2DQphRGdQeWt5dzJSM2dMYkJqeUhiamE5VkZKcytkTUViUE1sa0RLeklWK2dndWdWR3d1UWRvRDUvSnZrem8zcVhUDQpjWkp3R0U3Mk9FRmlKbi9Wd1dPSDBXamxYS2pIQkFqaFNuOW42M05GamhzM1NHS3RkaW9xSEJPaVpDeEI2NjZyDQpNSEdaeTE1a0R5emdEVVNGNU9JK0svbWIza3dHRDhTNXV6ZW1PNmRXeFdRd0w3ek5ScHhNaUg0YjhEOENGQlV1DQpyQ0lDSWt1NWhTRC9MTnZ0K05PVnRDUllUalNMT01kWmFjdEg3MFAxRXdxckpHUzJzSms4RERpMmg1bzJDaG5JDQpXL2t4TU95WnIzYk9EQUJaTGlhTndIWXZFSEJISHdndWVYR0hiaVlVRGg3czlzTWZKUVpyR1pEbmQ3R0h5STdIDQplbWRzYkIwMnN2ekRQckFFOUxRZjRXQi9kcWFOUmxJMmZ0SnIzSEo1YTlnWUJvSkRLWnU2OVI0N0c2MGozbXJrDQp4SHVYR1JDYzh4QW1PcUk0VWNla3RXb0RaR1prTEUxVXdIeFlQRVJ4WndJREFRQUJvMU13VVRBZEJnTlZIUTRFDQpGZ1FVR3lxY1p6U2NSWWJtcDNOZkhGc1k1NHJaUU5Jd0h3WURWUjBqQkJnd0ZvQVVHeXFjWnpTY1JZYm1wM05mDQpIRnNZNTRyWlFOSXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FnRUFiaU9xDQpYUFowcW9yZmZZOW5YUWtpY2RaQjdmTXFEZjV6WjIybFdCRTRmbER6ZDhmZk82TmVIL0Z0N1UzWXdwS3N0dXpoDQozbkhWYlIrVDM1YnVmVXBMeVBibStKL2dJRzlTSHk1TlRrMmVuKzdseHJvYmVzTlZuNjY5Uy9UQW1yd2ZwbEN5DQpWZXB0WVQ0MkpsMy9TZDY0RHdINExIQVVyUGpzZFVoeVl5V2FXbnRUZ3JxeEF5K3RVb1B4anZyWDE0ZVdDNndIDQpjOHQxb3ZNU2ZTczVlYXBzd1JPUUsyVkFyKzE5cDJwRllQVEVMNzVlcENoeG4yZjI4Z1ZubEVWZ21rQW9rNFBSDQpJV2s0aldkei9IU0duT1BJNU5DbW1vZW9nUkFjdTNUOWp4cE9vRkFHWFlFMU9FdEdxV2kxeUpBRUo0NU9WVHNZDQprQk9pRnhsOC8xZUIySmRWWFBDRVRVaFZ6Uy93bGZIOG5vd1pzenk1OHNRNVF3RzllMXduVXcvMFI3M3NTMUVHDQpxY0hraUJFRDB5Z05DTndNT1ZYTW5hbEREbmlYS0JKd3FaMFk1SytMOVlYek9HaU8raEJNMUxFVFRxeXVHdzdJDQpVM1NwcUR3SVZJU2gzRDhNVzc3WFFXZmdQZXk1TE1Fa0x1SHQ4akt5aTVCMDZKOUE3Rm1XWGdzdmlqZnJjbGFBDQp3ZHBDakJWN2pjY216Qkl4WVV3cEtOUHljY1Q5Mk43UDg2VlEzV2NPQ1BqSGJnUDNtMXRTUlQ2UG9nakRibjdNDQp3VmhUeUNvMGN1cTJRV2I0cUtYN3NIUHZDSmJyS3pJY1Y2ZE9iZm1zUjUzMEt0cTZaU0xNbVQ5RzJkSnFzT0FtDQpsNXlMU1ByU2E5Tjl0UU03Q1lSMzB4N3ZnaTNHZ29GVGxrQ1hGV0E9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo=
|
||||
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlKUkFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0NTNHdnZ2txQWdFQUFvSUNBUURVamdNb1h4dGF2c01YDQpVb0h2YTBXVWZSeWJKTVVnR1NQbml3ZWF3eW41RmlnVVR4Nmd2NlZ2T3pxU21HWjE4NVA0VUliV0N1ZDlXakVDDQpFU0pVSkI0cVpiUmlEWUlNQWQyMzM2Y2k1d0RzbkRGVXpuWHRNOWc1VUZmS3dPd2VPVmN2anNTdFlmNks5d2QvDQoxaXRMb3JIeDV0eEVQblBkVGRGR0ZqOVlVT2t1MmM1VllIMk9LaUk3ampDaDAwc3RaZHo4dDVpLy9LdjI3UER0DQo2REc3L3VuMHlnVEcxa21NVU1QcnBSQmVIbFFNWWZ0N09xTTNHSHJEZml1SDdjNVpGNWM2YURnUHlreXcyUjNnDQpMYkJqeUhiamE5VkZKcytkTUViUE1sa0RLeklWK2dndWdWR3d1UWRvRDUvSnZrem8zcVhUY1pKd0dFNzJPRUZpDQpKbi9Wd1dPSDBXamxYS2pIQkFqaFNuOW42M05GamhzM1NHS3RkaW9xSEJPaVpDeEI2NjZyTUhHWnkxNWtEeXpnDQpEVVNGNU9JK0svbWIza3dHRDhTNXV6ZW1PNmRXeFdRd0w3ek5ScHhNaUg0YjhEOENGQlV1ckNJQ0lrdTVoU0QvDQpMTnZ0K05PVnRDUllUalNMT01kWmFjdEg3MFAxRXdxckpHUzJzSms4RERpMmg1bzJDaG5JVy9reE1PeVpyM2JPDQpEQUJaTGlhTndIWXZFSEJISHdndWVYR0hiaVlVRGg3czlzTWZKUVpyR1pEbmQ3R0h5STdIZW1kc2JCMDJzdnpEDQpQckFFOUxRZjRXQi9kcWFOUmxJMmZ0SnIzSEo1YTlnWUJvSkRLWnU2OVI0N0c2MGozbXJreEh1WEdSQ2M4eEFtDQpPcUk0VWNla3RXb0RaR1prTEUxVXdIeFlQRVJ4WndJREFRQUJBb0lDQVFDUEQ1NVVkOTdqYnUzRUxzWkJyTVBDDQpNNHNqYU5ZOHltNytFdmRsVk9KVlFuSnJhTzFHYUhjaXJJeTV5bFY4SWh0LzBFTlFvVG81aHBEaHdVS0h1MStLDQpUYlhoSVJKY25venFpMS9rLy9JQlR3ZHMreUVvSy9MbWNJc0dibDc5NEw0cnhqM2VMTXkwSDV3dWtLbkhXSlBJDQpLd2dwN3BieFpzVHFGV05CUUFRU2dvcDdzRndSYVk1czQwRWNTaWlaUDZ4RGRCY2RjU1VWSjFqcDU1UkI0a3I1DQpkVmROdFVEL2JnVFAvK05LVmNOZ0tqcW5NRXBXZE9WNzJ0blZ2VnRiWDZOcnJtVzlTdjNmTWVNSDFmaVkwSDRrDQpoNW1kMTRkNVZ0cng3Z00zUE1XVFFSeHNvS0dvL29CYnE5aHlZdUZGQTBZOVVIMnRjTThFcmN4a0VXR05MNEthDQoxcjdvOTR5QWlHemRYd2xLbjdoSFBMWHlhc0lyYmF1T3FrSUE1ZUNnRkplQm9McUkrU1UyakJEZ3NPZlVOaHpWDQpNTmIxQzNoNGl3OUp2TER6MXMzaDJPbGxCY080WnBSamF0ODBQY1E4Sm5SK2l4VWUvYWdiS3ZRR056cEVobkovDQpOdWt2V2NWdXJrZUNRY1lQc01rWlMvUGlHK0U1NElSUVlvRHBoakZIUHd1cW12bWZKMTNUMjN2NXAvelVBNXVUDQoxQVFkMWRWL1JrQmtBcG9RWm51c1g3Q1ZCcWpUaGRWREVVem91OVRrK09nR016WkZRd0NjYVNWQllWVlg5OXkwDQpUTVpReFN6MlllUS9hZmZ2M2FDZ3dkZHhyZERFQzNDYm9BUks1bW91ZEhxaUVhSExROEswR3pValdzTDhTVnhGDQpOZ2JHNnFLcW5XWUJyeFIrWkFsOUlRS0NBUUVBK1puaE8zOWNNUnJhdk1EYzdNYjlkdFFoSFBYeFpnR2xaVGZTDQpWMHhrV3RPZEFqZjNHVlJ2RERqRE1oMk9hQUZiakFDSVBYdGoyaWxWV2MxSWIwQmxTbTVnVEdHeERrMVIvVTg3DQo2QUVGa3ZxME8rTWtSZjhQS21LQWpCa1RYY1VhbVo1NjFwQWRaaldSeDVBNi9IbW5lWGxxbzM3VDBhaTg5alRUDQpGMXpKeWZ4SXNwVGZ2YVJDUFQrSndMNWx6TmRFUmpUd0MzZDZRSWhRM2Q2MWhYMFFvVFhjeFpXRmNvMjNCemFwDQpMei9uYjNqOG81TFNnQ2JCNUdDQzd6SGtUYlN2SHNjdnVOOWFySDkwNE5CZ3g4aWJ6b3B6WHdaaFhzK3pxZWp1DQpkSVgxWHhONUFUSVEwak1hK0I3WnI1Tmp3TnU0T1JtdjQwZUpzNlhFOHgza0FXNjdMd0tDQVFFQTJnRC93RHRmDQpsU2l6c0g0cnExK1pFZE96K3AvQ2Fjdk1CK2lxdTczdEJROG8xR1ViVlJ3Q0h0TjkzeHQ0RUEyMGk2NjFobU5LDQoxL2kxNWljeERiVG44akg4SStOd0F2clRVSzJ3eGVkRXNxK3ZWZWtUaWoya0NLOVVJMGh1eFBFSTlkMVdKNnk4DQp1eDhibFFyNTMyUEpYT2FLMlpUOEE0eERBMk8wOThNOFQydUdlTEtlM1phc0ppRjJLTXJuMyt6TlRmWW91ODJVDQpacDdwN2MrbDh0bmRIUC80MUxjQno2dklPQUhDb3lKYTZmeEY0YWhMRThiU3VUaFBGVS8rRGpIZm1nb0xiMTgrDQpyZDJSR09ZU0R5dWZPT1lKN3NBY1hKVGFRK2hjVVpuRHFOcktLZkdBTlhGYzVUSGVEYTlkamRHMkNLaURhVXNHDQpFWEE4SGxvMWRFZS9TUUtDQVFFQXJoYkQzNG12Tlppelk5OW90OFQ2MkR5UWMvQ2VWRFZsdExsQWZoOE1COFY4DQp4eVZkdFU4TXZRdUNLWnd2elI3VlNVcTl1NVFxU3VsMVhGTXY2RmlUelZ3NjBrdDVBSzZ4TnVwaXNDaTJTSk9QDQp6ZzFaS1hFQ2xOOXJKVXdBRS9ENzRwV0V1ODU4a3VOZU1FREt3M25lYzMxYUFYcmVKbWQ0bElpM2lwM3ZLSEJNDQpEREtGODNGenVlQnRKZ0FtWkw3b0ljZWVmWUR4eGJ6T0dsSFJiYStUUDcyZnBEZnJnY0NTSGZmai9NNm5qenBsDQppM2xHVkplenVLUVA3dUZ2aVRzeXdWYlFWRE9FdkxlUlA1UlhURUVCV3dkNS9KY29wc1piVzNEWmtIQTJlZi9NDQo4Q2FKVVBMUUpxcnR6ZVlSTjF5SW0xcnRNS3Fld3F3bU9DTnErZ3pQaFFLQ0FRRUFySUJ4M3hpY0w1ai9acjdQDQpxMUYvKzkwNjR5d2JXRC9NK00wZ25HSlM5TmZrQlB6a1BkcGx5eUtxelNvZFBRYTdRSFJFYTB5U1lvY0kyRTlXDQp2M1BRdlpMVDQwb0t6akRQbVYxM0xZSXNsLy93aTloY2Y5ejZ1V3lTOVVCUmRrRU1TQkNXSmRySGxJR3UvNmFwDQp4aHhkcjhjMVE2cGlLQ1NLdWxuaFR0UU1Hd1FJYWVWZFZCWHZybFIzL1J0aGs0ejdmNTh5NkRocUh6SE1CVU4wDQpHdEJONks2YnBTWVNwdE5WSVF3emlZYWJ6ZDZ6SlRaWUFoUW5saXg2VjNEdXBTak51RVFPZkZndmJzQ09HZGVqDQpucUZ6NGtBVXgvajMrRUpJMjhjM2xkSklRb3F0d2JhNUxwQy9ZeFNza3NPYkVhZEpsVnhTYjdUUDNtaWpDWmwwDQpCc2puRVFLQ0FRQTZDSG5LZTNWNEF5WkRJV1N5UE0xZ2Q4VWVyQWY3V2paLzJ1RU0yWC9Nc1JvN2pHeHh4U0JMDQpUOE5vemtuZ05GbXV2SENnOURpdXRxZ0N0eHV5TXZ6MmJ2MnhXdWxPMm9ZL0NVdUQvVzV6aU44NzlnenBPSStPDQo5T0d4NklUV2xqZ0FKQmt4U1RaYXpYd0NVK05qNDlkY2ZicWhEZGtTQWZ6RW1COGpCRzEzaXprcVZEQTdYU0lBDQoxWDNUdEpkSGwzUmYwNFpoUUN1aCthWEdlRjdHOHQ0QTFhZW1iWWIyUStjM1BPK0s2ZlZZU3doTC9PeEdFdmUzDQpEc2x1aUZ2ZnM1cFIwb3B0ZWR6Y1RQdHhQM29tK0JiSThvUnVHVUdMdkNKbS9GYlNOL0c1TGFZS1U4YlkydHlhDQo1L05QTjR1OTZCcStRYUFsS0hKc24xL01XRWRaTS9ocg0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ0K
|
||||
---
|
||||
# #######################################################
|
||||
# Issuer Cert-Manager
|
||||
# #######################################################
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: booking-microservices-issuer
|
||||
namespace: default
|
||||
spec:
|
||||
acme:
|
||||
# Staging API
|
||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
# server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: test@email.com
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-staging
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
ca:
|
||||
secretName: booking-tls
|
||||
---
|
||||
# #######################################################
|
||||
# Certificate Cert-Manager
|
||||
# #######################################################
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: booking-microservices-cert
|
||||
namespace: default
|
||||
spec:
|
||||
secretName: booking-tls-cert
|
||||
issuerRef:
|
||||
name: booking-microservices-issuer
|
||||
kind: Issuer
|
||||
dnsNames:
|
||||
- booking-microservices.com
|
||||
File diff suppressed because it is too large
Load Diff
45
deployments/tye/tye.yml
Normal file
45
deployments/tye/tye.yml
Normal file
@ -0,0 +1,45 @@
|
||||
name: Booking
|
||||
services:
|
||||
- name: booking-gateway
|
||||
project: ./../../src/ApiGateway/src/ApiGateway.csproj
|
||||
bindings:
|
||||
- port: 5001
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: development
|
||||
|
||||
|
||||
- name: flight
|
||||
project: ./../../src/Services/Flight/src/Flight.Api/Flight.Api.csproj
|
||||
bindings:
|
||||
- port: 5003
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: development
|
||||
|
||||
|
||||
- name: identity
|
||||
project: ./../../src/Services/Identity/src/Identity.Api/Identity.Api.csproj
|
||||
bindings:
|
||||
- port: 5005
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: development
|
||||
|
||||
|
||||
- name: passenger
|
||||
project: ./../../src/Services/Passenger/src/Passenger.Api/Passenger.Api.csproj
|
||||
bindings:
|
||||
- port: 5012
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: development
|
||||
|
||||
|
||||
- name: booking
|
||||
project: ./../../src/Services/Booking/src/Booking.Api/Booking.Api.csproj
|
||||
bindings:
|
||||
- port: 5010
|
||||
env:
|
||||
- name: ASPNETCORE_ENVIRONMENT
|
||||
value: development
|
||||
@ -1,6 +0,0 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "10.0.103",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
1346
package-lock.json
generated
1346
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@ -1,19 +1,3 @@
|
||||
{
|
||||
"name": "booking-microservices",
|
||||
"version": "1.0.0",
|
||||
"description": "booking-microservices",
|
||||
"author": "Meysam Hadeli",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"prepare": "husky && dotnet tool restore",
|
||||
"format": "dotnet tool run dotnet-csharpier booking-microservices.sln",
|
||||
"ci-format": "dotnet tool run dotnet-csharpier booking-microservices.sln --check",
|
||||
"upgrade-packages": "dotnet outdated --upgrade"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.5.0",
|
||||
"@commitlint/config-conventional": "^19.5.0",
|
||||
"husky": "^9.1.6"
|
||||
}
|
||||
{
|
||||
"version": "0.0.0"
|
||||
}
|
||||
|
||||
@ -1,38 +1,42 @@
|
||||
# ---------- Build Stage ----------
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS builder
|
||||
WORKDIR /src
|
||||
|
||||
# Copy solution-level files
|
||||
COPY .editorconfig .
|
||||
COPY global.json .
|
||||
COPY Directory.Build.props .
|
||||
# Setup working directory for the project
|
||||
WORKDIR /src
|
||||
COPY ./src/BuildingBlocks/BuildingBlocks.csproj ./BuildingBlocks/
|
||||
COPY ./src/ApiGateway/src/ApiGateway.csproj ./ApiGateway/src/
|
||||
|
||||
# Copy project files first (better Docker caching)
|
||||
COPY src/BuildingBlocks/BuildingBlocks.csproj src/BuildingBlocks/
|
||||
COPY src/ApiGateway/src/ApiGateway.csproj src/ApiGateway/src/
|
||||
COPY src/Aspire/src/ServiceDefaults/ServiceDefaults.csproj src/Aspire/src/ServiceDefaults/
|
||||
|
||||
# Restore dependencies
|
||||
RUN dotnet restore src/ApiGateway/src/ApiGateway.csproj
|
||||
# Restore nuget packages
|
||||
RUN dotnet restore ./ApiGateway/src/ApiGateway.csproj
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY src ./src
|
||||
# Copy project files
|
||||
COPY ./src/BuildingBlocks ./BuildingBlocks/
|
||||
COPY ./src/ApiGateway/src ./ApiGateway/src/
|
||||
|
||||
# Publish (build included)
|
||||
RUN dotnet publish src/ApiGateway/src/ApiGateway.csproj \
|
||||
-c Release \
|
||||
-o /app/publish \
|
||||
--no-restore
|
||||
# Build project with Release configuration
|
||||
# and no restore, as we did it already
|
||||
|
||||
# ---------- Runtime Stage ----------
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
||||
RUN ls
|
||||
RUN dotnet build -c Release --no-restore ./ApiGateway/src/ApiGateway.csproj
|
||||
|
||||
WORKDIR /src/ApiGateway/src
|
||||
|
||||
# Publish project to output folder
|
||||
# and no build, as we did it already
|
||||
RUN dotnet publish -c Release --no-build -o out
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0
|
||||
|
||||
# Setup working directory for the project
|
||||
WORKDIR /app
|
||||
COPY --from=builder /src/ApiGateway/src/out .
|
||||
|
||||
COPY --from=build /app/publish .
|
||||
|
||||
ENV ASPNETCORE_URLS=http://+:80
|
||||
ENV ASPNETCORE_ENVIRONMENT=docker
|
||||
ENV ASPNETCORE_URLS https://*:443, http://*:80
|
||||
ENV ASPNETCORE_ENVIRONMENT docker
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
ENTRYPOINT ["dotnet", "ApiGateway.dll"]
|
||||
|
||||
ENTRYPOINT ["dotnet", "ApiGateway.dll"]
|
||||
45
src/ApiGateway/dev.Dockerfile
Normal file
45
src/ApiGateway/dev.Dockerfile
Normal file
@ -0,0 +1,45 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS builder
|
||||
WORKDIR /src
|
||||
|
||||
# Setup working directory for the project
|
||||
WORKDIR /src
|
||||
COPY ./src/BuildingBlocks/BuildingBlocks.csproj ./BuildingBlocks/
|
||||
COPY ./src/ApiGateway/src/ApiGateway.csproj ./ApiGateway/src/
|
||||
|
||||
|
||||
# Restore nuget packages
|
||||
RUN --mount=type=cache,id=gateway_nuget,target=/root/.nuget/packages \
|
||||
dotnet restore ./ApiGateway/src/ApiGateway.csproj
|
||||
|
||||
# Copy project files
|
||||
COPY ./src/BuildingBlocks ./BuildingBlocks/
|
||||
COPY ./src/ApiGateway/src ./ApiGateway/src/
|
||||
|
||||
# Build project with Release configuration
|
||||
# and no restore, as we did it already
|
||||
|
||||
RUN ls
|
||||
RUN --mount=type=cache,id=gateway_nuget,target=/root/.nuget/packages \
|
||||
dotnet build -c Release --no-restore ./ApiGateway/src/ApiGateway.csproj
|
||||
|
||||
WORKDIR /src/ApiGateway/src
|
||||
|
||||
# Publish project to output folder
|
||||
# and no build, as we did it already
|
||||
RUN --mount=type=cache,id=gateway_nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -c Release --no-build -o out
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0
|
||||
|
||||
# Setup working directory for the project
|
||||
WORKDIR /app
|
||||
COPY --from=builder /src/ApiGateway/src/out .
|
||||
|
||||
ENV ASPNETCORE_URLS https://*:443, http://*:80
|
||||
ENV ASPNETCORE_ENVIRONMENT docker
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
ENTRYPOINT ["dotnet", "ApiGateway.dll"]
|
||||
|
||||
@ -1,5 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\BuildingBlocks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="AsyncFixer" Version="1.6.0" />
|
||||
<PackageReference Update="Meziantou.Analyzer" Version="1.0.747" />
|
||||
<PackageReference Update="Microsoft.VisualStudio.Threading.Analyzers" Version="17.4.27" />
|
||||
<PackageReference Update="Roslynator.Analyzers" Version="4.1.2" />
|
||||
<PackageReference Update="Roslynator.Formatting.Analyzers" Version="4.2.0" />
|
||||
<PackageReference Update="Roslynator.CodeAnalysis.Analyzers" Version="4.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using BuildingBlocks.Logging;
|
||||
using BuildingBlocks.Web;
|
||||
using Figgle;
|
||||
using Figgle.Fonts;
|
||||
using Serilog;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var env = builder.Environment;
|
||||
@ -8,6 +9,8 @@ var appOptions = builder.Services.GetOptions<AppOptions>("AppOptions");
|
||||
Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name));
|
||||
|
||||
|
||||
|
||||
builder.AddCustomSerilog(env);
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
|
||||
@ -15,6 +18,7 @@ builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSecti
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseSerilogRequestLogging();
|
||||
app.UseCorrelationId();
|
||||
app.UseRouting();
|
||||
app.UseHttpsRedirection();
|
||||
@ -29,4 +33,4 @@ app.UseEndpoints(endpoints =>
|
||||
|
||||
app.MapGet("/", x => x.Response.WriteAsync(appOptions.Name));
|
||||
|
||||
app.Run();
|
||||
app.Run();
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
{
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:17191",
|
||||
"sslPort": 44352
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"ApiGateway": {
|
||||
"commandName": "Project",
|
||||
@ -9,6 +17,14 @@
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
"match": {
|
||||
"path": "identity/{**catch-all}"
|
||||
},
|
||||
"Transforms": [
|
||||
"Transforms": [
|
||||
{
|
||||
"PathRemovePrefix": "identity"
|
||||
}
|
||||
@ -28,7 +28,7 @@
|
||||
"match": {
|
||||
"path": "flight/{**catch-all}"
|
||||
},
|
||||
"Transforms": [
|
||||
"Transforms": [
|
||||
{
|
||||
"PathRemovePrefix": "flight"
|
||||
}
|
||||
@ -39,7 +39,7 @@
|
||||
"match": {
|
||||
"path": "passenger/{**catch-all}"
|
||||
},
|
||||
"Transforms": [
|
||||
"Transforms": [
|
||||
{
|
||||
"PathRemovePrefix": "passenger"
|
||||
}
|
||||
@ -50,7 +50,7 @@
|
||||
"match": {
|
||||
"path": "booking/{**catch-all}"
|
||||
},
|
||||
"Transforms": [
|
||||
"Transforms": [
|
||||
{
|
||||
"PathRemovePrefix": "booking"
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.SDK" Version="13.1.1"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>bde28db3-85ba-4201-b889-0f3faba24169</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.Docker" Version="13.1.1-preview.1.26105.8" />
|
||||
<PackageReference Include="Aspire.Hosting.MongoDB" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.PostgreSQL" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.RabbitMQ" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.Redis" Version="13.1.1" />
|
||||
<PackageReference Include="CommunityToolkit.Aspire.Hosting.EventStore" Version="9.9.0" />
|
||||
<PackageReference Include="Elastic.Aspire.Hosting.Elasticsearch" Version="9.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\ApiGateway\src\ApiGateway.csproj" />
|
||||
<ProjectReference Include="..\..\..\Services\Booking\src\Booking.Api\Booking.Api.csproj" />
|
||||
<ProjectReference Include="..\..\..\Services\Flight\src\Flight.Api\Flight.Api.csproj" />
|
||||
<ProjectReference Include="..\..\..\Services\Identity\src\Identity.Api\Identity.Api.csproj" />
|
||||
<ProjectReference Include="..\..\..\Services\Passenger\src\Passenger.Api\Passenger.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -1,366 +0,0 @@
|
||||
using System.Net.Sockets;
|
||||
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
builder.AddDockerComposeEnvironment("docker-compose");
|
||||
|
||||
// 1. Database Services
|
||||
var pgUsername = builder.AddParameter("pg-username", "postgres", secret: true);
|
||||
var pgPassword = builder.AddParameter("pg-password", "postgres", secret: true);
|
||||
|
||||
var postgres = builder.AddPostgres("postgres", pgUsername, pgPassword)
|
||||
.WithImage("postgres:latest")
|
||||
.WithEndpoint(
|
||||
"tcp",
|
||||
e =>
|
||||
{
|
||||
e.Port = 5432;
|
||||
e.TargetPort = 5432;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
})
|
||||
.WithArgs(
|
||||
"-c",
|
||||
"wal_level=logical",
|
||||
"-c",
|
||||
"max_prepared_transactions=10");
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
postgres.WithDataVolume("postgres-data")
|
||||
.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
|
||||
var flightDb = postgres.AddDatabase("flight");
|
||||
var passengerDb = postgres.AddDatabase("passenger");
|
||||
var identityDb = postgres.AddDatabase("identity");
|
||||
var persistMessageDb = postgres.AddDatabase("persist-message");
|
||||
|
||||
var mongoUsername = builder.AddParameter("mongo-username", "root", secret: true);
|
||||
var mongoPassword = builder.AddParameter("mongo-password", "secret", secret: true);
|
||||
|
||||
var mongo = builder.AddMongoDB("mongo", userName: mongoUsername, password: mongoPassword)
|
||||
.WithImage("mongo")
|
||||
.WithImageTag("latest")
|
||||
.WithEndpoint(
|
||||
"tcp",
|
||||
e =>
|
||||
{
|
||||
e.Port = 27017;
|
||||
e.TargetPort = 27017;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
});
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
mongo.WithDataVolume("mongo-data")
|
||||
.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
|
||||
var redis = builder.AddRedis("redis")
|
||||
.WithImage("redis:latest")
|
||||
.WithEndpoint(
|
||||
"tcp",
|
||||
e =>
|
||||
{
|
||||
e.Port = 6379;
|
||||
e.TargetPort = 6379;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
});
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
redis.WithDataVolume("redis-data")
|
||||
.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
|
||||
var eventstore = builder.AddEventStore("eventstore")
|
||||
.WithImage("eventstore/eventstore")
|
||||
.WithEnvironment("EVENTSTORE_CLUSTER_SIZE", "1")
|
||||
.WithEnvironment("EVENTSTORE_RUN_PROJECTIONS", "All")
|
||||
.WithEnvironment("EVENTSTORE_START_STANDARD_PROJECTIONS", "True")
|
||||
.WithEnvironment("EVENTSTORE_INSECURE", "True")
|
||||
.WithEnvironment("EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "True")
|
||||
.WithEndpoint(
|
||||
"http",
|
||||
e =>
|
||||
{
|
||||
e.TargetPort = 2113;
|
||||
e.Port = 2113;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = true;
|
||||
})
|
||||
.WithEndpoint(
|
||||
port: 1113,
|
||||
targetPort: 1113,
|
||||
name: "tcp",
|
||||
isProxied: true,
|
||||
isExternal: false);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
eventstore.WithDataVolume("eventstore-data")
|
||||
.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
// 2. Messaging Services
|
||||
var rabbitmqUsername = builder.AddParameter("rabbitmq-username", "guest", secret: true);
|
||||
var rabbitmqPassword = builder.AddParameter("rabbitmq-password", "guest", secret: true);
|
||||
|
||||
var rabbitmq = builder.AddRabbitMQ("rabbitmq", rabbitmqUsername, rabbitmqPassword)
|
||||
.WithManagementPlugin()
|
||||
.WithEndpoint(
|
||||
"tcp",
|
||||
e =>
|
||||
{
|
||||
e.TargetPort = 5672;
|
||||
e.Port = 5672;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
})
|
||||
.WithEndpoint(
|
||||
"management",
|
||||
e =>
|
||||
{
|
||||
e.TargetPort = 15672;
|
||||
e.Port = 15672;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = true;
|
||||
});
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
rabbitmq.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
// // 3. Observability Services
|
||||
var jaeger = builder.AddContainer("jaeger-all-in-one", "jaegertracing/all-in-one")
|
||||
.WithEndpoint(
|
||||
port: 6831,
|
||||
targetPort: 6831,
|
||||
name: "agent",
|
||||
protocol: ProtocolType.Udp,
|
||||
isProxied: true,
|
||||
isExternal: false)
|
||||
.WithEndpoint(port: 16686, targetPort: 16686, name: "http", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 14268, targetPort: 14268, name: "collector", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 14317, targetPort: 4317, name: "otlp-grpc", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 14318, targetPort: 4318, name: "otlp-http", isProxied: true, isExternal: false);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
jaeger.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var zipkin = builder.AddContainer("zipkin-all-in-one", "openzipkin/zipkin")
|
||||
.WithEndpoint(port: 9411, targetPort: 9411, name: "http", isProxied: true, isExternal: true);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
zipkin.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var otelCollector = builder.AddContainer("otel-collector", "otel/opentelemetry-collector-contrib")
|
||||
.WithBindMount(
|
||||
"../../../../deployments/configs/otel-collector-config.yaml",
|
||||
"/etc/otelcol-contrib/config.yaml",
|
||||
isReadOnly: true)
|
||||
.WithArgs("--config=/etc/otelcol-contrib/config.yaml")
|
||||
.WithEndpoint(port: 11888, targetPort: 1888, name: "otel-pprof", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 8888, targetPort: 8888, name: "otel-metrics", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 8889, targetPort: 8889, name: "otel-exporter-metrics", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 13133, targetPort: 13133, name: "otel-health", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 4317, targetPort: 4317, name: "otel-grpc", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 4318, targetPort: 4318, name: "otel-http", isProxied: true, isExternal: true)
|
||||
.WithEndpoint(port: 55679, targetPort: 55679, name: "otel-zpages", isProxied: true, isExternal: true);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
otelCollector.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var prometheus = builder.AddContainer("prometheus", "prom/prometheus")
|
||||
.WithBindMount("../../../../deployments/configs/prometheus.yaml", "/etc/prometheus/prometheus.yml")
|
||||
.WithArgs(
|
||||
"--config.file=/etc/prometheus/prometheus.yml",
|
||||
"--storage.tsdb.path=/prometheus",
|
||||
"--web.console.libraries=/usr/share/prometheus/console_libraries",
|
||||
"--web.console.templates=/usr/share/prometheus/consoles",
|
||||
"--web.enable-remote-write-receiver")
|
||||
.WithEndpoint(port: 9090, targetPort: 9090, name: "http", isProxied: true, isExternal: true);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
prometheus.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var grafana = builder.AddContainer("grafana", "grafana/grafana")
|
||||
.WithEnvironment("GF_INSTALL_PLUGINS", "grafana-clock-panel,grafana-simple-json-datasource")
|
||||
.WithEnvironment("GF_SECURITY_ADMIN_USER", "admin")
|
||||
.WithEnvironment("GF_SECURITY_ADMIN_PASSWORD", "admin")
|
||||
.WithEnvironment("GF_FEATURE_TOGGLES_ENABLE", "traceqlEditor")
|
||||
.WithBindMount("../../../../deployments/configs/grafana/provisioning", "/etc/grafana/provisioning")
|
||||
.WithBindMount("../../../../deployments/configs/grafana/dashboards", "/var/lib/grafana/dashboards")
|
||||
.WithEndpoint(port: 3000, targetPort: 3000, name: "http", isProxied: true, isExternal: true);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
grafana.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var nodeExporter = builder.AddContainer("node-exporter", "prom/node-exporter")
|
||||
.WithBindMount("/proc", "/host/proc", isReadOnly: true)
|
||||
.WithBindMount("/sys", "/host/sys", isReadOnly: true)
|
||||
.WithBindMount("/", "/rootfs", isReadOnly: true)
|
||||
.WithArgs(
|
||||
"--path.procfs=/host/proc",
|
||||
"--path.rootfs=/rootfs",
|
||||
"--path.sysfs=/host/sys")
|
||||
.WithEndpoint(port: 9101, targetPort: 9100, name: "http", isProxied: true, isExternal: true);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
nodeExporter.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var tempo = builder.AddContainer("tempo", "grafana/tempo")
|
||||
.WithBindMount("../../../../deployments/configs/tempo.yaml", "/etc/tempo.yaml", isReadOnly: true)
|
||||
.WithArgs("--config.file=/etc/tempo.yaml")
|
||||
.WithEndpoint(port: 3200, targetPort: 3200, name: "http", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 9095, targetPort: 9095, name: "grpc", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 4317, targetPort: 4317, name: "otlp-grpc", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 4318, targetPort: 4318, name: "otlp-http", isProxied: true, isExternal: false);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
tempo.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var loki = builder.AddContainer("loki", "grafana/loki")
|
||||
.WithBindMount("../../../../deployments/configs/loki-config.yaml", "/etc/loki/local-config.yaml", isReadOnly: true)
|
||||
.WithArgs("-config.file=/etc/loki/local-config.yaml")
|
||||
.WithEndpoint(port: 3100, targetPort: 3100, name: "http", isProxied: true, isExternal: false)
|
||||
.WithEndpoint(port: 9096, targetPort: 9096, name: "grpc", isProxied: true, isExternal: false);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
loki.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var elasticsearch = builder.AddElasticsearch("elasticsearch")
|
||||
.WithImage("docker.elastic.co/elasticsearch/elasticsearch:8.17.0")
|
||||
.WithEnvironment("discovery.type", "single-node")
|
||||
.WithEnvironment("cluster.name", "docker-cluster")
|
||||
.WithEnvironment("node.name", "docker-node")
|
||||
.WithEnvironment("ES_JAVA_OPTS", "-Xms512m -Xmx512m")
|
||||
.WithEnvironment("xpack.security.enabled", "false")
|
||||
.WithEnvironment("xpack.security.http.ssl.enabled", "false")
|
||||
.WithEnvironment("xpack.security.transport.ssl.enabled", "false")
|
||||
.WithEnvironment("network.host", "0.0.0.0")
|
||||
.WithEnvironment("http.port", "9200")
|
||||
.WithEnvironment("transport.host", "localhost")
|
||||
.WithEnvironment("bootstrap.memory_lock", "true")
|
||||
.WithEnvironment("cluster.routing.allocation.disk.threshold_enabled", "false")
|
||||
.WithEndpoint(
|
||||
"http",
|
||||
e =>
|
||||
{
|
||||
e.TargetPort = 9200;
|
||||
e.Port = 9200;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
})
|
||||
.WithEndpoint(
|
||||
"internal",
|
||||
e =>
|
||||
{
|
||||
e.TargetPort = 9300;
|
||||
e.Port = 9300;
|
||||
e.IsProxied = true;
|
||||
e.IsExternal = false;
|
||||
})
|
||||
.WithDataVolume("elastic-data");
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
elasticsearch.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
var kibana = builder.AddContainer("kibana", "docker.elastic.co/kibana/kibana:8.17.0")
|
||||
.WithEnvironment("ELASTICSEARCH_HOSTS", "http://elasticsearch:9200")
|
||||
.WithEndpoint(port: 5601, targetPort: 5601, name: "http", isProxied: true, isExternal: true)
|
||||
.WithReference(elasticsearch)
|
||||
.WaitFor(elasticsearch);
|
||||
|
||||
if (builder.ExecutionContext.IsPublishMode)
|
||||
{
|
||||
kibana.WithLifetime(ContainerLifetime.Persistent);
|
||||
}
|
||||
|
||||
// 5. Application Services
|
||||
var identity = builder.AddProject<Projects.Identity_Api>("identity-service")
|
||||
.WithReference(persistMessageDb)
|
||||
.WaitFor(persistMessageDb)
|
||||
.WithReference(identityDb)
|
||||
.WaitFor(identityDb)
|
||||
.WithReference(mongo)
|
||||
.WaitFor(mongo)
|
||||
.WithReference(rabbitmq)
|
||||
.WaitFor(rabbitmq)
|
||||
.WithHttpEndpoint(port: 6005, name: "identity-http")
|
||||
.WithHttpsEndpoint(port: 5005, name: "identity-https");
|
||||
|
||||
var passenger = builder.AddProject<Projects.Passenger_Api>("passenger-service")
|
||||
.WithReference(persistMessageDb)
|
||||
.WaitFor(persistMessageDb)
|
||||
.WithReference(passengerDb)
|
||||
.WaitFor(passengerDb)
|
||||
.WithReference(mongo)
|
||||
.WaitFor(mongo)
|
||||
.WithReference(rabbitmq)
|
||||
.WaitFor(rabbitmq)
|
||||
.WithHttpEndpoint(port: 6012, name: "passenger-http")
|
||||
.WithHttpsEndpoint(port: 5012, name: "passenger-https");
|
||||
|
||||
var flight = builder.AddProject<Projects.Flight_Api>("flight-service")
|
||||
.WithReference(persistMessageDb)
|
||||
.WaitFor(persistMessageDb)
|
||||
.WithReference(flightDb)
|
||||
.WaitFor(flightDb)
|
||||
.WithReference(mongo)
|
||||
.WaitFor(mongo)
|
||||
.WithReference(rabbitmq)
|
||||
.WaitFor(rabbitmq)
|
||||
.WithHttpEndpoint(port: 5004, name: "flight-http")
|
||||
.WithHttpsEndpoint(port: 5003, name: "flight-https");
|
||||
|
||||
var booking = builder.AddProject<Projects.Booking_Api>("booking-service")
|
||||
.WithReference(persistMessageDb)
|
||||
.WaitFor(persistMessageDb)
|
||||
.WithReference(eventstore)
|
||||
.WaitFor(eventstore)
|
||||
.WithReference(mongo)
|
||||
.WaitFor(mongo)
|
||||
.WithReference(rabbitmq)
|
||||
.WaitFor(rabbitmq)
|
||||
.WithHttpEndpoint(port: 6010, name: "booking-http")
|
||||
.WithHttpsEndpoint(port: 5010, name: "booking-https");
|
||||
|
||||
var gateway = builder.AddProject<Projects.ApiGateway>("api-gateway")
|
||||
.WithReference(flight)
|
||||
.WaitFor(flight)
|
||||
.WithReference(passenger)
|
||||
.WaitFor(passenger)
|
||||
.WithReference(identity)
|
||||
.WaitFor(identity)
|
||||
.WithReference(booking)
|
||||
.WaitFor(booking)
|
||||
.WithHttpEndpoint(port: 5001, name: "gateway-http")
|
||||
.WithHttpsEndpoint(port: 5000, name: "gateway-https");
|
||||
|
||||
builder.Build().Run();
|
||||
@ -1,18 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"AppHost": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:18888",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"DOTNET_ENVIRONMENT": "Development",
|
||||
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true",
|
||||
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://otel-collector:4317",
|
||||
"ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://otel-collector:4318"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
using BuildingBlocks.HealthCheck;
|
||||
using BuildingBlocks.OpenTelemetryCollector;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace ServiceDefaults;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IHostApplicationBuilder AddServiceDefaults(this WebApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddCustomHealthCheck();
|
||||
builder.AddCustomObservability();
|
||||
builder.Services.AddServiceDiscovery();
|
||||
|
||||
builder.Services.ConfigureHttpClientDefaults(http =>
|
||||
{
|
||||
http.AddStandardResilienceHandler(options =>
|
||||
{
|
||||
var timeSpan = TimeSpan.FromMinutes(1);
|
||||
options.CircuitBreaker.SamplingDuration = timeSpan * 2;
|
||||
options.TotalRequestTimeout.Timeout = timeSpan * 3;
|
||||
options.Retry.MaxRetryAttempts = 3;
|
||||
});
|
||||
|
||||
// Turn on service discovery by default
|
||||
http.AddServiceDiscovery();
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static WebApplication UseServiceDefaults(this WebApplication app)
|
||||
{
|
||||
app.UseCustomHealthCheck();
|
||||
app.UseCustomObservability();
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\BuildingBlocks.csproj" IsAspireProjectResource="false" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -1,110 +1,160 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Ardalis.GuardClauses" Version="5.0.0" />
|
||||
<PackageReference Include="Asp.Versioning.Abstractions" Version="8.1.0" />
|
||||
<PackageReference Include="Asp.Versioning.Http" Version="8.1.1" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.1" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.1" />
|
||||
<PackageReference Include="Figgle.Fonts" Version="0.6.5" />
|
||||
<PackageReference Include="Ardalis.GuardClauses" Version="4.0.1" />
|
||||
<PackageReference Include="Asp.Versioning.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Asp.Versioning.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc" Version="7.0.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="7.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Elasticsearch" Version="6.0.2" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.EventStore" Version="6.0.3" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="6.0.2" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="6.0.2" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.SQLite.Storage" Version="6.0.5" />
|
||||
<PackageReference Include="Ben.BlockingDetector" Version="0.0.4" />
|
||||
<PackageReference Include="EasyCaching.Core" Version="1.8.0" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.8.0" />
|
||||
<PackageReference Include="EasyNetQ.Management.Client" Version="1.4.2" />
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2" />
|
||||
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" />
|
||||
<PackageReference Include="Figgle" Version="0.5.1" />
|
||||
<PackageReference Include="FluentValidation" Version="11.4.0" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
|
||||
<PackageReference Include="Grpc.Core.Testing" Version="2.46.6" />
|
||||
<PackageReference Include="EasyCaching.Core" Version="1.9.2" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
||||
<PackageReference Include="EasyNetQ.Management.Client" Version="3.0.1" />
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="10.0.1" />
|
||||
<PackageReference Include="Figgle" Version="0.6.5" />
|
||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="10.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="10.3.0" />
|
||||
<PackageReference Include="Npgsql" Version="10.0.1" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="Polly" Version="8.6.5" />
|
||||
<PackageReference Include="Humanizer.Core" Version="3.0.1" />
|
||||
<PackageReference Include="IdGen" Version="3.0.7" />
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.1" />
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.3" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.6.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Scalar.AspNetCore" Version="2.12.38" />
|
||||
<PackageReference Include="Scrutor" Version="7.0.0" />
|
||||
<PackageReference Include="Sieve" Version="2.5.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="10.1.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.2" />
|
||||
<PackageReference Include="MassTransit" Version="8.5.8" />
|
||||
<PackageReference Include="MassTransit.RabbitMQ" Version="8.5.8" />
|
||||
<PackageReference Include="Duende.IdentityServer" Version="7.4.5" />
|
||||
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="7.4.5" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" Version="7.4.5" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework.Storage" Version="7.4.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="System.Linq.Async" Version="7.0.0" />
|
||||
<PackageReference Include="System.Linq.Async.Queryable" Version="7.0.0" />
|
||||
<PackageReference Include="Testcontainers" Version="4.9.0" />
|
||||
<PackageReference Include="Testcontainers.EventStoreDb" Version="4.9.0" />
|
||||
<PackageReference Include="Testcontainers.MongoDb" Version="4.9.0" />
|
||||
<PackageReference Include="Testcontainers.PostgreSql" Version="4.9.0" />
|
||||
<PackageReference Include="Testcontainers.RabbitMq" Version="4.9.0" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
|
||||
<PackageReference Include="Xunit.Extensions.Logging" Version="1.1.0" />
|
||||
<PackageReference Include="Yarp.ReverseProxy" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.3" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.EventStore" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="9.0.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.MongoDb" Version="9.0.0" />
|
||||
|
||||
<PackageReference Include="Npgsql.OpenTelemetry" Version="10.0.1" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.15.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.15.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.15.0-beta.1" />
|
||||
<PackageReference Include="Grafana.OpenTelemetry" Version="1.5.2" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.15.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Zipkin" Version="1.15.0" />
|
||||
|
||||
<PackageReference Include="EventStore.Client.Grpc.Streams" Version="23.3.9" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
|
||||
<PackageReference Include="AutoBogus" Version="2.13.1" />
|
||||
<PackageReference Include="Bogus" Version="35.6.5" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.8.0" />
|
||||
<PackageReference Include="Respawn" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.3" />
|
||||
<PackageReference Include="WebMotions.Fake.Authentication.JwtBearer" Version="10.0.0" />
|
||||
|
||||
<PackageReference Include="Google.Protobuf" Version="3.33.5" />
|
||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.76.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.3">
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
||||
<PackageReference Include="Mongo2Go" Version="3.1.3" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.1" />
|
||||
<PackageReference Include="NSubstitute" Version="4.4.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.0.0-rc9.7" />
|
||||
<PackageReference Include="Polly" Version="7.2.3" />
|
||||
<PackageReference Include="protobuf-net.BuildTools" Version="3.1.25">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Hellang.Middleware.ProblemDetails" Version="6.5.1" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="IdGen" Version="3.0.3" />
|
||||
<PackageReference Include="Mapster" Version="7.3.0" />
|
||||
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.0" />
|
||||
<PackageReference Include="MediatR" Version="11.1.0" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="OpenTelemetry.Contrib.Instrumentation.MassTransit" Version="1.0.0-beta2" />
|
||||
<PackageReference Include="Scrutor" Version="4.2.0" />
|
||||
<PackageReference Include="Scrutor.AspNetCore" Version="3.3.0" />
|
||||
<PackageReference Include="Sentry.Serilog" Version="3.25.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
|
||||
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
|
||||
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
|
||||
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="8.4.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2" />
|
||||
<PackageReference Include="Serilog.Sinks.SpectreConsole" Version="0.3.3" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit" Version="3.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="6.0.5" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="6.0.5" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="6.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="7.0.2" />
|
||||
<PackageReference Include="AspNetCore.HealthChecks.MongoDb" Version="6.0.2" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="6.0.1" />
|
||||
<PackageReference Include="MassTransit" Version="8.0.12" />
|
||||
<PackageReference Include="MassTransit.RabbitMQ" Version="8.0.12" />
|
||||
<PackageReference Include="DotNetCore.CAP" Version="7.0.2" />
|
||||
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="7.0.2" />
|
||||
<PackageReference Include="DotNetCore.CAP.MongoDB" Version="7.0.2" />
|
||||
<PackageReference Include="DotNetCore.CAP.OpenTelemetry" Version="7.0.2" />
|
||||
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="7.0.2" />
|
||||
<PackageReference Include="DotNetCore.CAP.SqlServer" Version="7.0.2" />
|
||||
<PackageReference Include="Duende.IdentityServer" Version="6.2.2" />
|
||||
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="6.2.2" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" Version="6.2.2" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework.Storage" Version="6.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.2" />
|
||||
<PackageReference Include="Testcontainers" Version="2.3.0" />
|
||||
<PackageReference Include="Unchase.Swashbuckle.AspNetCore.Extensions" Version="2.7.1" />
|
||||
<PackageReference Include="WebMotions.Fake.Authentication.JwtBearer" Version="7.0.0" />
|
||||
<PackageReference Include="Yarp.ReverseProxy" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.Identity.Web" Version="2.0.5-preview" />
|
||||
|
||||
<PackageReference Include="Jaeger" Version="1.0.3" />
|
||||
<PackageReference Include="OpenTracing" Version="0.12.1" />
|
||||
<PackageReference Include="prometheus-net" Version="7.0.0" />
|
||||
<PackageReference Include="prometheus-net.AspNetCore" Version="7.0.0" />
|
||||
|
||||
<PackageReference Include="OpenTelemetry" Version="1.4.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Jaeger" Version="1.4.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc9.7" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.7" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.7" />
|
||||
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.0.64">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<PackageReference Include="EventStore.Client.Grpc.Streams" Version="22.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.1" />
|
||||
|
||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
||||
<PackageReference Include="AutoBogus" Version="2.13.1" />
|
||||
<PackageReference Include="Bogus" Version="34.0.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.9.0" />
|
||||
<PackageReference Include="Respawn" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.12" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.51.0" />
|
||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.51.0" />
|
||||
<PackageReference Update="AsyncFixer" Version="1.6.0" />
|
||||
<PackageReference Update="Meziantou.Analyzer" Version="1.0.758" />
|
||||
<PackageReference Remove="Microsoft.VisualStudio.Threading.Analyzers" />
|
||||
<PackageReference Update="Microsoft.VisualStudio.Threading.Analyzers" Version="17.4.27" />
|
||||
<PackageReference Update="Roslynator.Analyzers" Version="4.2.0" />
|
||||
<PackageReference Update="Roslynator.CodeAnalysis.Analyzers" Version="4.2.0" />
|
||||
<PackageReference Update="Roslynator.Formatting.Analyzers" Version="4.2.0" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Contracts" />
|
||||
<Folder Include="EventStoreDB\BackgroundWorkers" />
|
||||
<Folder Include="PersistMessageProcessor\Data\Configurations" />
|
||||
<Folder Include="PersistMessageProcessor\Data\Migrations" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
55
src/BuildingBlocks/CAP/Extensions.cs
Normal file
55
src/BuildingBlocks/CAP/Extensions.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Unicode;
|
||||
using BuildingBlocks.Utils;
|
||||
using BuildingBlocks.Web;
|
||||
using DotNetCore.CAP;
|
||||
using DotNetCore.CAP.Messages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BuildingBlocks.CAP;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IServiceCollection AddCustomCap<TDbContext>(this IServiceCollection services)
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
var rabbitMqOptions = services.GetOptions<RabbitMQOptions>("RabbitMq");
|
||||
|
||||
services.AddCap(x =>
|
||||
{
|
||||
x.UseEntityFramework<TDbContext>();
|
||||
x.UseRabbitMQ(o =>
|
||||
{
|
||||
o.HostName = rabbitMqOptions.HostName;
|
||||
o.UserName = rabbitMqOptions.UserName;
|
||||
o.Password = rabbitMqOptions.Password;
|
||||
});
|
||||
x.UseDashboard();
|
||||
x.FailedRetryCount = 5;
|
||||
x.FailedThresholdCallback = failed =>
|
||||
{
|
||||
var logger = failed.ServiceProvider.GetService<ILogger>();
|
||||
logger?.LogError(
|
||||
$@"A message of type {failed.MessageType} failed after executing {x.FailedRetryCount} several times,
|
||||
requiring manual troubleshooting. Message name: {failed.Message.GetName()}");
|
||||
};
|
||||
x.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
|
||||
});
|
||||
|
||||
// services.AddOpenTelemetryTracing((builder) => builder
|
||||
// .AddAspNetCoreInstrumentation()
|
||||
// .AddCapInstrumentation()
|
||||
// .AddZipkinExporter()
|
||||
// );
|
||||
|
||||
services.Scan(s =>
|
||||
s.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies())
|
||||
.AddClasses(c => c.AssignableTo(typeof(ICapSubscribe)))
|
||||
.AsImplementedInterfaces()
|
||||
.WithScopedLifetime());
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
using EasyCaching.Core;
|
||||
using EasyCaching.Core;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@ -47,4 +47,4 @@ public class CachingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest,
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,4 +4,4 @@ public interface ICacheRequest
|
||||
{
|
||||
string CacheKey { get; }
|
||||
DateTime? AbsoluteExpirationRelativeToNow { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,4 +4,4 @@ namespace BuildingBlocks.Caching
|
||||
{
|
||||
string CacheKey { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,4 +36,4 @@ namespace BuildingBlocks.Caching
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
namespace BuildingBlocks.Constants;
|
||||
|
||||
public static class IdentityConstant
|
||||
{
|
||||
public static class Role
|
||||
{
|
||||
public const string Admin = "admin";
|
||||
public const string User = "user";
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,10 @@ using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Contracts.EventBus.Messages;
|
||||
|
||||
public record FlightCreated(Guid Id) : IIntegrationEvent;
|
||||
public record FlightUpdated(Guid Id) : IIntegrationEvent;
|
||||
public record FlightDeleted(Guid Id) : IIntegrationEvent;
|
||||
public record AircraftCreated(Guid Id) : IIntegrationEvent;
|
||||
public record AirportCreated(Guid Id) : IIntegrationEvent;
|
||||
public record SeatCreated(Guid Id) : IIntegrationEvent;
|
||||
public record SeatReserved(Guid Id) : IIntegrationEvent;
|
||||
public record FlightCreated(long Id) : IIntegrationEvent;
|
||||
public record FlightUpdated(long Id) : IIntegrationEvent;
|
||||
public record FlightDeleted(long Id) : IIntegrationEvent;
|
||||
public record AircraftCreated(long Id) : IIntegrationEvent;
|
||||
public record AirportCreated(long Id) : IIntegrationEvent;
|
||||
public record SeatCreated(long Id) : IIntegrationEvent;
|
||||
public record SeatReserved(long Id) : IIntegrationEvent;
|
||||
|
||||
@ -2,4 +2,4 @@ using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Contracts.EventBus.Messages;
|
||||
|
||||
public record UserCreated(Guid Id, string Name, string PassportNumber) : IIntegrationEvent;
|
||||
public record UserCreated(long Id, string Name, string PassportNumber) : IIntegrationEvent;
|
||||
|
||||
@ -2,5 +2,5 @@ using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Contracts.EventBus.Messages;
|
||||
|
||||
public record PassengerRegistrationCompleted(Guid Id) : IIntegrationEvent;
|
||||
public record PassengerCreated(Guid Id) : IIntegrationEvent;
|
||||
public record PassengerRegistrationCompleted(long Id) : IIntegrationEvent;
|
||||
public record PassengerCreated(long Id) : IIntegrationEvent;
|
||||
|
||||
@ -2,4 +2,4 @@ using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Contracts.EventBus.Messages;
|
||||
|
||||
public record BookingCreated(Guid Id) : IIntegrationEvent;
|
||||
public record BookingCreated(long Id) : IIntegrationEvent;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
|
||||
namespace BuildingBlocks.Core.CQRS;
|
||||
|
||||
@ -9,4 +9,4 @@ public interface ICommand : ICommand<Unit>
|
||||
public interface ICommand<out T> : IRequest<T>
|
||||
where T : notnull
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
|
||||
namespace BuildingBlocks.Core.CQRS;
|
||||
|
||||
@ -11,4 +11,4 @@ public interface ICommandHandler<in TCommand, TResponse> : IRequestHandler<TComm
|
||||
where TCommand : ICommand<TResponse>
|
||||
where TResponse : notnull
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
|
||||
namespace BuildingBlocks.Core.CQRS;
|
||||
|
||||
public interface IQuery<out T> : IRequest<T>
|
||||
where T : notnull
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
|
||||
namespace BuildingBlocks.Core.CQRS;
|
||||
|
||||
@ -6,4 +6,4 @@ public interface IQueryHandler<in TQuery, TResponse> : IRequestHandler<TQuery, T
|
||||
where TQuery : IQuery<TResponse>
|
||||
where TResponse : notnull
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Core;
|
||||
|
||||
public class CompositeEventMapper : IEventMapper
|
||||
{
|
||||
private readonly IEnumerable<IEventMapper> _mappers;
|
||||
|
||||
public CompositeEventMapper(IEnumerable<IEventMapper> mappers)
|
||||
{
|
||||
_mappers = mappers;
|
||||
}
|
||||
|
||||
public IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event)
|
||||
{
|
||||
foreach (var mapper in _mappers)
|
||||
{
|
||||
var integrationEvent = mapper.MapToIntegrationEvent(@event);
|
||||
if (integrationEvent is not null)
|
||||
return integrationEvent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IInternalCommand? MapToInternalCommand(IDomainEvent @event)
|
||||
{
|
||||
foreach (var mapper in _mappers)
|
||||
{
|
||||
var internalCommand = mapper.MapToInternalCommand(@event);
|
||||
if (internalCommand is not null)
|
||||
return internalCommand;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -6,4 +6,4 @@ public enum EventType
|
||||
DomainEvent = 1,
|
||||
IntegrationEvent = 2,
|
||||
InternalCommand = 4
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,4 +2,4 @@ namespace BuildingBlocks.Core.Event;
|
||||
|
||||
public interface IDomainEvent : IEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
using BuildingBlocks.IdsGenerator;
|
||||
using MediatR;
|
||||
|
||||
namespace BuildingBlocks.Core.Event;
|
||||
|
||||
using global::MassTransit;
|
||||
|
||||
public interface IEvent : INotification
|
||||
{
|
||||
Guid EventId => NewId.NextGuid();
|
||||
long EventId => SnowFlakIdGenerator.NewId();
|
||||
public DateTime OccurredOn => DateTime.Now;
|
||||
public string EventType => GetType().AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,4 +5,4 @@ namespace BuildingBlocks.Core.Event;
|
||||
[ExcludeFromTopology]
|
||||
public interface IIntegrationEvent : IEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
namespace BuildingBlocks.Core.Event;
|
||||
namespace BuildingBlocks.Core.Event;
|
||||
|
||||
public interface IInternalCommand : IEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using BuildingBlocks.Core.CQRS;
|
||||
using BuildingBlocks.Core.CQRS;
|
||||
using BuildingBlocks.IdsGenerator;
|
||||
|
||||
namespace BuildingBlocks.Core.Event;
|
||||
|
||||
public record InternalCommand : IInternalCommand, ICommand;
|
||||
public record InternalCommand : IInternalCommand, ICommand;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace BuildingBlocks.Core.Event;
|
||||
|
||||
@ -23,4 +23,4 @@ public class MessageEnvelope<TMessage> : MessageEnvelope
|
||||
}
|
||||
|
||||
public new TMessage? Message { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,17 +9,30 @@ using MessageEnvelope = BuildingBlocks.Core.Event.MessageEnvelope;
|
||||
|
||||
namespace BuildingBlocks.Core;
|
||||
|
||||
public sealed class EventDispatcher(
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
IEventMapper eventMapper,
|
||||
ILogger<EventDispatcher> logger,
|
||||
IPersistMessageProcessor persistMessageProcessor,
|
||||
IHttpContextAccessor httpContextAccessor
|
||||
)
|
||||
: IEventDispatcher
|
||||
public sealed class EventDispatcher : IEventDispatcher
|
||||
{
|
||||
private readonly IEventMapper _eventMapper;
|
||||
private readonly ILogger<EventDispatcher> _logger;
|
||||
private readonly IPersistMessageProcessor _persistMessageProcessor;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
public EventDispatcher(IServiceScopeFactory serviceScopeFactory,
|
||||
IEventMapper eventMapper,
|
||||
ILogger<EventDispatcher> logger,
|
||||
IPersistMessageProcessor persistMessageProcessor,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_eventMapper = eventMapper;
|
||||
_logger = logger;
|
||||
_persistMessageProcessor = persistMessageProcessor;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
|
||||
public async Task SendAsync<T>(IReadOnlyList<T> events, Type type = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
CancellationToken cancellationToken = default)
|
||||
where T : IEvent
|
||||
{
|
||||
if (events.Count > 0)
|
||||
@ -32,7 +45,7 @@ public sealed class EventDispatcher(
|
||||
{
|
||||
foreach (var integrationEvent in integrationEvents)
|
||||
{
|
||||
await persistMessageProcessor.PublishMessageAsync(
|
||||
await _persistMessageProcessor.PublishMessageAsync(
|
||||
new MessageEnvelope(integrationEvent, SetHeaders()),
|
||||
cancellationToken);
|
||||
}
|
||||
@ -41,13 +54,13 @@ public sealed class EventDispatcher(
|
||||
switch (events)
|
||||
{
|
||||
case IReadOnlyList<IDomainEvent> domainEvents:
|
||||
{
|
||||
var integrationEvents = await MapDomainEventToIntegrationEventAsync(domainEvents)
|
||||
{
|
||||
var integrationEvents = await MapDomainEventToIntegrationEventAsync(domainEvents)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await PublishIntegrationEvent(integrationEvents);
|
||||
break;
|
||||
}
|
||||
await PublishIntegrationEvent(integrationEvents);
|
||||
break;
|
||||
}
|
||||
|
||||
case IReadOnlyList<IIntegrationEvent> integrationEvents:
|
||||
await PublishIntegrationEvent(integrationEvents);
|
||||
@ -61,7 +74,7 @@ public sealed class EventDispatcher(
|
||||
|
||||
foreach (var internalMessage in internalMessages)
|
||||
{
|
||||
await persistMessageProcessor.AddInternalMessageAsync(internalMessage, cancellationToken);
|
||||
await _persistMessageProcessor.AddInternalMessageAsync(internalMessage, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,34 +83,33 @@ public sealed class EventDispatcher(
|
||||
public async Task SendAsync<T>(T @event, Type type = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
where T : IEvent =>
|
||||
await SendAsync(new[] { @event }, type, cancellationToken);
|
||||
await SendAsync(new[] {@event}, type, cancellationToken);
|
||||
|
||||
|
||||
private Task<IReadOnlyList<IIntegrationEvent>> MapDomainEventToIntegrationEventAsync(
|
||||
IReadOnlyList<IDomainEvent> events)
|
||||
{
|
||||
logger.LogTrace("Processing integration events start...");
|
||||
_logger.LogTrace("Processing integration events start...");
|
||||
|
||||
var wrappedIntegrationEvents = GetWrappedIntegrationEvents(events.ToList())?.ToList();
|
||||
if (wrappedIntegrationEvents?.Count > 0)
|
||||
return Task.FromResult<IReadOnlyList<IIntegrationEvent>>(wrappedIntegrationEvents);
|
||||
|
||||
var integrationEvents = new List<IIntegrationEvent>();
|
||||
using var scope = serviceScopeFactory.CreateScope();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
foreach (var @event in events)
|
||||
{
|
||||
var eventType = @event.GetType();
|
||||
logger.LogTrace($"Handling domain event: {eventType.Name}");
|
||||
_logger.LogTrace($"Handling domain event: {eventType.Name}");
|
||||
|
||||
var integrationEvent = eventMapper.MapToIntegrationEvent(@event);
|
||||
var integrationEvent = _eventMapper.MapToIntegrationEvent(@event);
|
||||
|
||||
if (integrationEvent is null)
|
||||
continue;
|
||||
if (integrationEvent is null) continue;
|
||||
|
||||
integrationEvents.Add(integrationEvent);
|
||||
}
|
||||
|
||||
logger.LogTrace("Processing integration events done...");
|
||||
_logger.LogTrace("Processing integration events done...");
|
||||
|
||||
return Task.FromResult<IReadOnlyList<IIntegrationEvent>>(integrationEvents);
|
||||
}
|
||||
@ -106,24 +118,23 @@ public sealed class EventDispatcher(
|
||||
private Task<IReadOnlyList<IInternalCommand>> MapDomainEventToInternalCommandAsync(
|
||||
IReadOnlyList<IDomainEvent> events)
|
||||
{
|
||||
logger.LogTrace("Processing internal message start...");
|
||||
_logger.LogTrace("Processing internal message start...");
|
||||
|
||||
var internalCommands = new List<IInternalCommand>();
|
||||
using var scope = serviceScopeFactory.CreateScope();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
foreach (var @event in events)
|
||||
{
|
||||
var eventType = @event.GetType();
|
||||
logger.LogTrace($"Handling domain event: {eventType.Name}");
|
||||
_logger.LogTrace($"Handling domain event: {eventType.Name}");
|
||||
|
||||
var integrationEvent = eventMapper.MapToInternalCommand(@event);
|
||||
var integrationEvent = _eventMapper.MapToInternalCommand(@event);
|
||||
|
||||
if (integrationEvent is null)
|
||||
continue;
|
||||
if (integrationEvent is null) continue;
|
||||
|
||||
internalCommands.Add(integrationEvent);
|
||||
}
|
||||
|
||||
logger.LogTrace("Processing internal message done...");
|
||||
_logger.LogTrace("Processing internal message done...");
|
||||
|
||||
return Task.FromResult<IReadOnlyList<IInternalCommand>>(internalCommands);
|
||||
}
|
||||
@ -146,10 +157,10 @@ public sealed class EventDispatcher(
|
||||
private IDictionary<string, object> SetHeaders()
|
||||
{
|
||||
var headers = new Dictionary<string, object>();
|
||||
headers.Add("CorrelationId", httpContextAccessor?.HttpContext?.GetCorrelationId());
|
||||
headers.Add("UserId", httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier));
|
||||
headers.Add("UserName", httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.Name));
|
||||
headers.Add("CorrelationId", _httpContextAccessor?.HttpContext?.GetCorrelationId());
|
||||
headers.Add("UserId", _httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier));
|
||||
headers.Add("UserName", _httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.Name));
|
||||
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,4 +8,4 @@ public interface IEventDispatcher
|
||||
where T : IEvent;
|
||||
public Task SendAsync<T>(T @event, Type type = null, CancellationToken cancellationToken = default)
|
||||
where T : IEvent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,6 @@ namespace BuildingBlocks.Core;
|
||||
|
||||
public interface IEventMapper
|
||||
{
|
||||
IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event);
|
||||
IInternalCommand? MapToInternalCommand(IDomainEvent @event);
|
||||
}
|
||||
IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event);
|
||||
IInternalCommand MapToInternalCommand(IDomainEvent @event);
|
||||
}
|
||||
|
||||
@ -3,4 +3,4 @@ using BuildingBlocks.Core.Event;
|
||||
namespace BuildingBlocks.Core;
|
||||
|
||||
public record IntegrationEventWrapper<TDomainEventType>(TDomainEventType DomainEvent) : IIntegrationEvent
|
||||
where TDomainEventType : IDomainEvent;
|
||||
where TDomainEventType : IDomainEvent;
|
||||
|
||||
@ -1,23 +1,32 @@
|
||||
using BuildingBlocks.Core.Event;
|
||||
using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Core.Model;
|
||||
|
||||
public abstract record Aggregate<TId> : Entity<TId>, IAggregate<TId>
|
||||
namespace BuildingBlocks.Core.Model
|
||||
{
|
||||
private readonly List<IDomainEvent> _domainEvents = new();
|
||||
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
|
||||
|
||||
public void AddDomainEvent(IDomainEvent domainEvent)
|
||||
public abstract record Aggregate : Aggregate<long>
|
||||
{
|
||||
_domainEvents.Add(domainEvent);
|
||||
}
|
||||
|
||||
public IEvent[] ClearDomainEvents()
|
||||
public abstract record Aggregate<TId> : Audit, IAggregate<TId>
|
||||
{
|
||||
IEvent[] dequeuedEvents = _domainEvents.ToArray();
|
||||
private readonly List<IDomainEvent> _domainEvents = new();
|
||||
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
|
||||
|
||||
_domainEvents.Clear();
|
||||
public void AddDomainEvent(IDomainEvent domainEvent)
|
||||
{
|
||||
_domainEvents.Add(domainEvent);
|
||||
}
|
||||
|
||||
return dequeuedEvents;
|
||||
public IEvent[] ClearDomainEvents()
|
||||
{
|
||||
IEvent[] dequeuedEvents = _domainEvents.ToArray();
|
||||
|
||||
_domainEvents.Clear();
|
||||
|
||||
return dequeuedEvents;
|
||||
}
|
||||
|
||||
public long Version { get; set; }
|
||||
|
||||
public TId Id { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
namespace BuildingBlocks.Core.Model;
|
||||
|
||||
public interface IEntity<T> : IEntity
|
||||
{
|
||||
public T Id { get; set; }
|
||||
}
|
||||
|
||||
public interface IEntity : IVersion
|
||||
public abstract record Audit : IAudit
|
||||
{
|
||||
public DateTime? CreatedAt { get; set; }
|
||||
public long? CreatedBy { get; set; }
|
||||
public DateTime? LastModified { get; set; }
|
||||
public long? LastModifiedBy { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,19 @@
|
||||
using BuildingBlocks.Core.Event;
|
||||
using BuildingBlocks.Core.Event;
|
||||
|
||||
namespace BuildingBlocks.Core.Model;
|
||||
|
||||
public interface IAggregate<T> : IAggregate, IEntity<T>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IAggregate : IEntity
|
||||
public interface IAggregate : IAudit, IVersion
|
||||
{
|
||||
IReadOnlyList<IDomainEvent> DomainEvents { get; }
|
||||
IEvent[] ClearDomainEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAggregate<out T> : IAggregate
|
||||
{
|
||||
T Id { get; }
|
||||
}
|
||||
|
||||
public interface IVersion
|
||||
{
|
||||
long Version { get; set; }
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
namespace BuildingBlocks.Core.Model;
|
||||
|
||||
public abstract record Entity<T> : IEntity<T>
|
||||
public interface IAudit
|
||||
{
|
||||
public T Id { get; set; }
|
||||
public DateTime? CreatedAt { get; set; }
|
||||
public long? CreatedBy { get; set; }
|
||||
public DateTime? LastModified { get; set; }
|
||||
public long? LastModifiedBy { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
public long Version { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Model;
|
||||
|
||||
// For handling optimistic concurrency
|
||||
public interface IVersion
|
||||
{
|
||||
long Version { get; set; }
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Pagination;
|
||||
|
||||
using Sieve.Models;
|
||||
using Sieve.Services;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static async Task<IPageList<TEntity>> ApplyPagingAsync<TEntity>(
|
||||
this IQueryable<TEntity> queryable,
|
||||
IPageRequest pageRequest,
|
||||
ISieveProcessor sieveProcessor,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
where TEntity : class
|
||||
{
|
||||
var sieveModel = new SieveModel
|
||||
{
|
||||
PageSize = pageRequest.PageSize,
|
||||
Page = pageRequest.PageNumber,
|
||||
Sorts = pageRequest.SortOrder,
|
||||
Filters = pageRequest.Filters
|
||||
};
|
||||
|
||||
// https://github.com/Biarity/Sieve/issues/34#issuecomment-403817573
|
||||
var result = sieveProcessor.Apply(sieveModel, queryable, applyPagination: false);
|
||||
var total = result.Count();
|
||||
result = sieveProcessor.Apply(sieveModel, queryable, applyFiltering: false,
|
||||
applySorting: false); // Only applies pagination
|
||||
|
||||
var items = await result
|
||||
.ToAsyncEnumerable()
|
||||
.ToListAsync(cancellationToken: cancellationToken);
|
||||
|
||||
return PageList<TEntity>.Create(items.AsReadOnly(), pageRequest.PageNumber, pageRequest.PageSize, total);
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Pagination;
|
||||
|
||||
public interface IPageList<T>
|
||||
where T : class
|
||||
{
|
||||
int CurrentPageSize { get; }
|
||||
int CurrentStartIndex { get; }
|
||||
int CurrentEndIndex { get; }
|
||||
int TotalPages { get; }
|
||||
bool HasPrevious { get; }
|
||||
bool HasNext { get; }
|
||||
IReadOnlyList<T> Items { get; init; }
|
||||
int TotalCount { get; init; }
|
||||
int PageNumber { get; init; }
|
||||
int PageSize { get; init; }
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Pagination;
|
||||
|
||||
using MediatR;
|
||||
|
||||
public interface IPageQuery<out TResponse> : IPageRequest, IRequest<TResponse>
|
||||
where TResponse : class
|
||||
{ }
|
||||
@ -1,9 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Pagination;
|
||||
|
||||
public interface IPageRequest
|
||||
{
|
||||
int PageNumber { get; init; }
|
||||
int PageSize { get; init; }
|
||||
string? Filters { get; init; }
|
||||
string? SortOrder { get; init; }
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
namespace BuildingBlocks.Core.Pagination;
|
||||
|
||||
public record PageList<T>(IReadOnlyList<T> Items, int PageNumber, int PageSize, int TotalCount) : IPageList<T>
|
||||
where T : class
|
||||
{
|
||||
public int CurrentPageSize => Items.Count;
|
||||
public int CurrentStartIndex => TotalCount == 0 ? 0 : ((PageNumber - 1) * PageSize) + 1;
|
||||
public int CurrentEndIndex => TotalCount == 0 ? 0 : CurrentStartIndex + CurrentPageSize - 1;
|
||||
public int TotalPages => (int)Math.Ceiling(TotalCount / (double)PageSize);
|
||||
public bool HasPrevious => PageNumber > 1;
|
||||
public bool HasNext => PageNumber < TotalPages;
|
||||
|
||||
public static PageList<T> Empty => new(Enumerable.Empty<T>().ToList(), 0, 0, 0);
|
||||
|
||||
public static PageList<T> Create(IReadOnlyList<T> items, int pageNumber, int pageSize, int totalItems)
|
||||
{
|
||||
return new PageList<T>(items, pageNumber, pageSize, totalItems);
|
||||
}
|
||||
}
|
||||
@ -1,83 +1,34 @@
|
||||
namespace BuildingBlocks.EFCore;
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using BuildingBlocks.Core.Event;
|
||||
using BuildingBlocks.Core.Model;
|
||||
using BuildingBlocks.Web;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using IsolationLevel = System.Data.IsolationLevel;
|
||||
|
||||
namespace BuildingBlocks.EFCore;
|
||||
using System.Data;
|
||||
using Web;
|
||||
using Exception = System.Exception;
|
||||
|
||||
public abstract class AppDbContextBase : DbContext, IDbContext
|
||||
{
|
||||
private readonly ICurrentUserProvider? _currentUserProvider;
|
||||
private readonly ILogger<AppDbContextBase>? _logger;
|
||||
private IDbContextTransaction _currentTransaction;
|
||||
private readonly ICurrentUserProvider _currentUserProvider;
|
||||
|
||||
protected AppDbContextBase(DbContextOptions options, ICurrentUserProvider? currentUserProvider = null, ILogger<AppDbContextBase>? logger = null) :
|
||||
protected AppDbContextBase(DbContextOptions options, ICurrentUserProvider currentUserProvider) :
|
||||
base(options)
|
||||
{
|
||||
_currentUserProvider = currentUserProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
}
|
||||
|
||||
public IExecutionStrategy CreateExecutionStrategy() => Database.CreateExecutionStrategy();
|
||||
|
||||
public async Task BeginTransactionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_currentTransaction != null)
|
||||
return;
|
||||
|
||||
_currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task CommitTransactionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
await _currentTransaction?.CommitAsync(cancellationToken)!;
|
||||
}
|
||||
catch
|
||||
{
|
||||
await RollbackTransactionAsync(cancellationToken);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_currentTransaction?.Dispose();
|
||||
_currentTransaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RollbackTransactionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _currentTransaction?.RollbackAsync(cancellationToken)!;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_currentTransaction?.Dispose();
|
||||
_currentTransaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//ref: https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency#execution-strategies-and-transactions
|
||||
public Task ExecuteTransactionalAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var strategy = CreateExecutionStrategy();
|
||||
var strategy = Database.CreateExecutionStrategy();
|
||||
return strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
await using var transaction =
|
||||
await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
|
||||
await using var transaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
|
||||
try
|
||||
{
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
@ -94,29 +45,7 @@ public abstract class AppDbContextBase : DbContext, IDbContext
|
||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
OnBeforeSaving();
|
||||
try
|
||||
{
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
//ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations#resolving-concurrency-conflicts
|
||||
catch (DbUpdateConcurrencyException ex)
|
||||
{
|
||||
foreach (var entry in ex.Entries)
|
||||
{
|
||||
var databaseValues = await entry.GetDatabaseValuesAsync(cancellationToken);
|
||||
|
||||
if (databaseValues == null)
|
||||
{
|
||||
_logger.LogError("The record no longer exists in the database, The record has been deleted by another user.");
|
||||
throw;
|
||||
}
|
||||
|
||||
// Refresh the original values to bypass next concurrency check
|
||||
entry.OriginalValues.SetValues(databaseValues);
|
||||
}
|
||||
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public IReadOnlyList<IDomainEvent> GetDomainEvents()
|
||||
@ -173,9 +102,9 @@ public abstract class AppDbContextBase : DbContext, IDbContext
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new System.Exception("try for find IAggregate", ex);
|
||||
throw new Exception("try for find IAggregate", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BuildingBlocks.EFCore
|
||||
{
|
||||
public abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDbContextFactory<TContext> where TContext : DbContext
|
||||
public abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDbContextFactory<TContext> where TContext : DbContext
|
||||
{
|
||||
public TContext CreateDbContext(string[] args)
|
||||
{
|
||||
|
||||
@ -1,81 +1,61 @@
|
||||
using System.Text.Json;
|
||||
using System.Transactions;
|
||||
using BuildingBlocks.Core;
|
||||
using BuildingBlocks.PersistMessageProcessor;
|
||||
using BuildingBlocks.Polly;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BuildingBlocks.EFCore;
|
||||
|
||||
|
||||
public class EfTxBehavior<TRequest, TResponse>(
|
||||
ILogger<EfTxBehavior<TRequest, TResponse>> logger,
|
||||
IDbContext dbContextBase,
|
||||
IPersistMessageDbContext persistMessageDbContext,
|
||||
IEventDispatcher eventDispatcher
|
||||
)
|
||||
: IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull, IRequest<TResponse>
|
||||
where TResponse : notnull
|
||||
public class EfTxBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : notnull, IRequest<TResponse>
|
||||
where TResponse : notnull
|
||||
{
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
private readonly ILogger<EfTxBehavior<TRequest, TResponse>> _logger;
|
||||
private readonly IDbContext _dbContextBase;
|
||||
private readonly IEventDispatcher _eventDispatcher;
|
||||
|
||||
public EfTxBehavior(
|
||||
ILogger<EfTxBehavior<TRequest, TResponse>> logger,
|
||||
IDbContext dbContextBase,
|
||||
IEventDispatcher eventDispatcher)
|
||||
{
|
||||
logger.LogInformation(
|
||||
_logger = logger;
|
||||
_dbContextBase = dbContextBase;
|
||||
_eventDispatcher = eventDispatcher;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"{Prefix} Handled command {MediatrRequest}",
|
||||
nameof(EfTxBehavior<TRequest, TResponse>),
|
||||
typeof(TRequest).FullName);
|
||||
|
||||
logger.LogDebug(
|
||||
_logger.LogDebug(
|
||||
"{Prefix} Handled command {MediatrRequest} with content {RequestContent}",
|
||||
nameof(EfTxBehavior<TRequest, TResponse>),
|
||||
typeof(TRequest).FullName,
|
||||
JsonSerializer.Serialize(request));
|
||||
|
||||
logger.LogInformation(
|
||||
_logger.LogInformation(
|
||||
"{Prefix} Open the transaction for {MediatrRequest}",
|
||||
nameof(EfTxBehavior<TRequest, TResponse>),
|
||||
typeof(TRequest).FullName);
|
||||
|
||||
//ref: https://learn.microsoft.com/en-us/ef/core/saving/transactions#using-systemtransactions
|
||||
using var scope = new TransactionScope(TransactionScopeOption.Required,
|
||||
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
|
||||
TransactionScopeAsyncFlowOption.Enabled);
|
||||
|
||||
var response = await next();
|
||||
|
||||
logger.LogInformation(
|
||||
_logger.LogInformation(
|
||||
"{Prefix} Executed the {MediatrRequest} request",
|
||||
nameof(EfTxBehavior<TRequest, TResponse>),
|
||||
typeof(TRequest).FullName);
|
||||
|
||||
while (true)
|
||||
{
|
||||
var domainEvents = dbContextBase.GetDomainEvents();
|
||||
var domainEvents = _dbContextBase.GetDomainEvents();
|
||||
|
||||
if (domainEvents is null || !domainEvents.Any())
|
||||
{
|
||||
return response;
|
||||
}
|
||||
await _eventDispatcher.SendAsync(domainEvents.ToArray(), typeof(TRequest), cancellationToken);
|
||||
|
||||
await eventDispatcher.SendAsync(domainEvents.ToArray(), typeof(TRequest), cancellationToken);
|
||||
await _dbContextBase.ExecuteTransactionalAsync(cancellationToken);
|
||||
|
||||
// Save data to database with some retry policy in distributed transaction
|
||||
await dbContextBase.RetryOnFailure(async () =>
|
||||
{
|
||||
await dbContextBase.SaveChangesAsync(cancellationToken);
|
||||
});
|
||||
|
||||
// Save data to database with some retry policy in distributed transaction
|
||||
await persistMessageDbContext.RetryOnFailure(async () =>
|
||||
{
|
||||
await persistMessageDbContext.SaveChangesAsync(cancellationToken);
|
||||
});
|
||||
|
||||
scope.Complete();
|
||||
|
||||
return response;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,79 +1,77 @@
|
||||
using System.Linq.Expressions;
|
||||
using BuildingBlocks.Core.Model;
|
||||
using BuildingBlocks.PersistMessageProcessor.Data;
|
||||
using BuildingBlocks.Web;
|
||||
using Humanizer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace BuildingBlocks.EFCore;
|
||||
|
||||
using Ardalis.GuardClauses;
|
||||
using Humanizer;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IServiceCollection AddCustomDbContext<TContext>(this WebApplicationBuilder builder, string? connectionName = "")
|
||||
where TContext : DbContext, IDbContext
|
||||
public static IServiceCollection AddCustomDbContext<TContext>(
|
||||
this IServiceCollection services)
|
||||
where TContext : DbContext, IDbContext
|
||||
{
|
||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||
|
||||
builder.Services.AddValidateOptions<PostgresOptions>();
|
||||
services.AddValidateOptions<PostgresOptions>();
|
||||
|
||||
builder.Services.AddDbContext<TContext>(
|
||||
(sp, options) =>
|
||||
{
|
||||
var aspireConnectionString = builder.Configuration.GetConnectionString(connectionName.Kebaberize());
|
||||
var connectionString = aspireConnectionString ?? sp.GetRequiredService<PostgresOptions>().ConnectionString;
|
||||
services.AddDbContext<TContext>((sp, options) =>
|
||||
{
|
||||
var postgresOptions = sp.GetRequiredService<PostgresOptions>();
|
||||
|
||||
ArgumentException.ThrowIfNullOrEmpty(connectionString);
|
||||
Guard.Against.Null(options, nameof(postgresOptions));
|
||||
|
||||
options.UseNpgsql(
|
||||
connectionString,
|
||||
dbOptions =>
|
||||
{
|
||||
dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
|
||||
})
|
||||
.UseSnakeCaseNamingConvention();
|
||||
options.UseNpgsql(postgresOptions?.ConnectionString,
|
||||
dbOptions =>
|
||||
{
|
||||
dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
|
||||
//ref: https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||
dbOptions.EnableRetryOnFailure(3, TimeSpan.FromSeconds(1), null);
|
||||
})
|
||||
// https://github.com/efcore/EFCore.NamingConventions
|
||||
.UseSnakeCaseNamingConvention();
|
||||
});
|
||||
|
||||
// Suppress warnings for pending model changes
|
||||
options.ConfigureWarnings(
|
||||
w => w.Ignore(RelationalEventId.PendingModelChangesWarning));
|
||||
});
|
||||
services.AddScoped<IDbContext>(provider => provider.GetService<TContext>());
|
||||
|
||||
builder.Services.AddScoped<ISeedManager, SeedManager>();
|
||||
builder.Services.AddScoped<IDbContext>(sp => sp.GetRequiredService<TContext>());
|
||||
|
||||
return builder.Services;
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
public static IApplicationBuilder UseMigration<TContext>(this IApplicationBuilder app)
|
||||
where TContext : DbContext, IDbContext
|
||||
public static IApplicationBuilder UseMigration<TContext>(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
where TContext : DbContext, IDbContext
|
||||
{
|
||||
MigrateAsync<TContext>(app.ApplicationServices).GetAwaiter().GetResult();
|
||||
MigrateDatabaseAsync<TContext>(app.ApplicationServices).GetAwaiter().GetResult();
|
||||
|
||||
SeedAsync(app.ApplicationServices).GetAwaiter().GetResult();
|
||||
if (!env.IsEnvironment("test"))
|
||||
{
|
||||
SeedDataAsync(app.ApplicationServices).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
// ref: https://github.com/pdevito3/MessageBusTestingInMemHarness/blob/main/RecipeManagement/src/RecipeManagement/Databases/RecipesDbContext.cs
|
||||
public static void FilterSoftDeletedProperties(this ModelBuilder modelBuilder)
|
||||
{
|
||||
Expression<Func<IAggregate, bool>> filterExpr = e => !e.IsDeleted;
|
||||
|
||||
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes()
|
||||
.Where(m => m.ClrType.IsAssignableTo(typeof(IEntity))))
|
||||
.Where(m => m.ClrType.IsAssignableTo(typeof(IAudit))))
|
||||
{
|
||||
// modify expression to handle correct child type
|
||||
var parameter = Expression.Parameter(mutableEntityType.ClrType);
|
||||
|
||||
var body = ReplacingExpressionVisitor
|
||||
.Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body);
|
||||
|
||||
var lambdaExpression = Expression.Lambda(body, parameter);
|
||||
|
||||
// set filter
|
||||
@ -81,7 +79,8 @@ public static class Extensions
|
||||
}
|
||||
}
|
||||
|
||||
// ref: https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/
|
||||
|
||||
//ref: https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/
|
||||
public static void ToSnakeCaseTables(this ModelBuilder modelBuilder)
|
||||
{
|
||||
foreach (var entity in modelBuilder.Model.GetEntityTypes())
|
||||
@ -90,9 +89,7 @@ public static class Extensions
|
||||
entity.SetTableName(entity.GetTableName()?.Underscore());
|
||||
|
||||
var tableObjectIdentifier =
|
||||
StoreObjectIdentifier.Table(
|
||||
entity.GetTableName()?.Underscore()!,
|
||||
entity.GetSchema());
|
||||
StoreObjectIdentifier.Table(entity.GetTableName()?.Underscore()!, entity.GetSchema());
|
||||
|
||||
// Replace column names
|
||||
foreach (var property in entity.GetProperties())
|
||||
@ -112,30 +109,25 @@ public static class Extensions
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task MigrateAsync<TContext>(IServiceProvider serviceProvider)
|
||||
where TContext : DbContext, IDbContext
|
||||
private static async Task MigrateDatabaseAsync<TContext>(IServiceProvider serviceProvider)
|
||||
where TContext : DbContext, IDbContext
|
||||
{
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
|
||||
var persistMessageContext = scope.ServiceProvider.GetRequiredService<PersistMessageDbContext>();
|
||||
await persistMessageContext.Database.MigrateAsync();
|
||||
|
||||
var context = scope.ServiceProvider.GetRequiredService<TContext>();
|
||||
var logger = scope.ServiceProvider.GetRequiredService<ILogger<TContext>>();
|
||||
await context.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
|
||||
|
||||
if (pendingMigrations.Any())
|
||||
private static async Task SeedDataAsync(IServiceProvider serviceProvider)
|
||||
{
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
|
||||
foreach (var seeder in seeders)
|
||||
{
|
||||
logger.LogInformation("Applying {Count} pending migrations...", pendingMigrations.Count());
|
||||
|
||||
await context.Database.MigrateAsync();
|
||||
logger.LogInformation("Migrations applied successfully.");
|
||||
await seeder.SeedAllAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task SeedAsync(IServiceProvider serviceProvider)
|
||||
{
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
|
||||
var seedersManager = scope.ServiceProvider.GetRequiredService<ISeedManager>();
|
||||
|
||||
await seedersManager.ExecuteSeedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user