Skip to content

Commit 42da57b

Browse files
cuichenlipuckpuck
andauthored
store order to postgresql from accounting service (open-telemetry#2175)
* store order to postgresql from accounting service * update on comment * fix trace not closed * Revert "fix trace not closed" This reverts commit e191c3e. * disable entity framework instrumentation * clean * group spans * fix for linter --------- Co-authored-by: Pierre Tessier <pierre@pierretessier.com>
1 parent 21fe6e7 commit 42da57b

File tree

10 files changed

+183
-3
lines changed

10 files changed

+183
-3
lines changed

.licenserc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
],
3939
"ignore": [
4040
"node_modules/",
41+
"src/accounting/bin/",
42+
"src/accounting/obj/",
4143
"/src/accounting/src/protos/",
4244
"src/cart/src/obj/",
4345
"src/cart/tests/obj/",

docker-compose.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ services:
3737
- OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
3838
- OTEL_RESOURCE_ATTRIBUTES
3939
- OTEL_SERVICE_NAME=accounting
40+
- DB_CONNECTION_STRING=Host=postgresql;Username=otelu;Password=otelp;Database=otel
41+
- OTEL_DOTNET_AUTO_TRACES_ENTITYFRAMEWORKCORE_INSTRUMENTATION_ENABLED=false
4042
depends_on:
4143
otel-collector:
4244
condition: service_started
@@ -686,6 +688,18 @@ services:
686688
retries: 10
687689
logging: *logging
688690

691+
# Postgresql used by Accounting service
692+
postgresql:
693+
image: ${POSTGRES_IMAGE}
694+
ports:
695+
- "5432"
696+
environment:
697+
POSTGRES_USER: root
698+
POSTGRES_PASSWORD: otel
699+
POSTGRES_DB: otel
700+
volumes:
701+
- ${PWD}/src/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
702+
689703
# Valkey used by Cart service
690704
valkey-cart:
691705
image: ${VALKEY_IMAGE}

src/accounting/.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bin
2+
obj
3+
build

src/accounting/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
proto

src/accounting/Accounting.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010

1111
<ItemGroup>
1212
<PackageReference Include="Confluent.Kafka" Version="2.8.0" />
13+
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
1314
<PackageReference Include="Google.Protobuf" Version="3.30.0" />
1415
<PackageReference Include="Grpc.Tools" Version="2.68.1">
1516
<PrivateAssets>all</PrivateAssets>
1617
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1718
</PackageReference>
1819
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
1920
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.2" />
21+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
2022
<PackageReference Include="OpenTelemetry.AutoInstrumentation" Version="1.11.0" />
2123
</ItemGroup>
2224

src/accounting/Consumer.cs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,35 @@
44
using Confluent.Kafka;
55
using Microsoft.Extensions.Logging;
66
using Oteldemo;
7+
using Microsoft.EntityFrameworkCore;
8+
using System.Diagnostics;
79

810
namespace Accounting;
911

12+
internal class DBContext : DbContext
13+
{
14+
public DbSet<OrderEntity> Orders { get; set; }
15+
public DbSet<OrderItemEntity> CartItems { get; set; }
16+
public DbSet<ShippingEntity> Shipping { get; set; }
17+
18+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
19+
{
20+
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
21+
22+
optionsBuilder.UseNpgsql(connectionString).UseSnakeCaseNamingConvention();
23+
}
24+
}
25+
26+
1027
internal class Consumer : IDisposable
1128
{
1229
private const string TopicName = "orders";
1330

1431
private ILogger _logger;
1532
private IConsumer<string, byte[]> _consumer;
1633
private bool _isListening;
34+
private DBContext? _dbContext;
35+
private static readonly ActivitySource MyActivitySource = new("Accounting.Consumer");
1736

1837
public Consumer(ILogger<Consumer> logger)
1938
{
@@ -26,6 +45,7 @@ public Consumer(ILogger<Consumer> logger)
2645
_consumer.Subscribe(TopicName);
2746

2847
_logger.LogInformation($"Connecting to Kafka: {servers}");
48+
_dbContext = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING") == null ? null : new DBContext();
2949
}
3050

3151
public void StartListening()
@@ -38,8 +58,8 @@ public void StartListening()
3858
{
3959
try
4060
{
61+
using var activity = MyActivitySource.StartActivity("order-consumed", ActivityKind.Internal);
4162
var consumeResult = _consumer.Consume();
42-
4363
ProcessMessage(consumeResult.Message);
4464
}
4565
catch (ConsumeException e)
@@ -61,8 +81,48 @@ private void ProcessMessage(Message<string, byte[]> message)
6181
try
6282
{
6383
var order = OrderResult.Parser.ParseFrom(message.Value);
64-
6584
Log.OrderReceivedMessage(_logger, order);
85+
86+
if (_dbContext == null)
87+
{
88+
return;
89+
}
90+
91+
var orderEntity = new OrderEntity
92+
{
93+
Id = order.OrderId
94+
};
95+
_dbContext.Add(orderEntity);
96+
foreach (var item in order.Items)
97+
{
98+
var orderItem = new OrderItemEntity
99+
{
100+
ItemCostCurrencyCode = item.Cost.CurrencyCode,
101+
ItemCostUnits = item.Cost.Units,
102+
ItemCostNanos = item.Cost.Nanos,
103+
ProductId = item.Item.ProductId,
104+
Quantity = item.Item.Quantity,
105+
OrderId = order.OrderId
106+
};
107+
108+
_dbContext.Add(orderItem);
109+
}
110+
111+
var shipping = new ShippingEntity
112+
{
113+
ShippingTrackingId = order.ShippingTrackingId,
114+
ShippingCostCurrencyCode = order.ShippingCost.CurrencyCode,
115+
ShippingCostUnits = order.ShippingCost.Units,
116+
ShippingCostNanos = order.ShippingCost.Nanos,
117+
StreetAddress = order.ShippingAddress.StreetAddress,
118+
City = order.ShippingAddress.City,
119+
State = order.ShippingAddress.State,
120+
Country = order.ShippingAddress.Country,
121+
ZipCode = order.ShippingAddress.ZipCode,
122+
OrderId = order.OrderId
123+
};
124+
_dbContext.Add(shipping);
125+
_dbContext.SaveChanges();
66126
}
67127
catch (Exception ex)
68128
{

src/accounting/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ RUN mkdir -p "/var/log/opentelemetry/dotnet"
3131
RUN chown app "/var/log/opentelemetry/dotnet"
3232
RUN chown app "/app/instrument.sh"
3333
USER app
34+
ENV OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES=Accounting.Consumer
3435

3536
ENTRYPOINT ["./instrument.sh", "dotnet", "Accounting.dll"]

src/accounting/Entities.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using Microsoft.EntityFrameworkCore;
5+
using System.ComponentModel.DataAnnotations.Schema;
6+
7+
namespace Accounting;
8+
9+
[Table("shipping")]
10+
[PrimaryKey(nameof(ShippingTrackingId))]
11+
internal class ShippingEntity
12+
{
13+
14+
public required string ShippingTrackingId { get; set; }
15+
16+
public required string ShippingCostCurrencyCode { get; set; }
17+
18+
public required long ShippingCostUnits { get; set; }
19+
20+
public required int ShippingCostNanos { get; set; }
21+
22+
public required string StreetAddress { get; set; }
23+
24+
public required string City { get; set; }
25+
26+
public required string State { get; set; }
27+
28+
public required string Country { get; set; }
29+
30+
public required string ZipCode { get; set; }
31+
32+
public required string OrderId { get; set; }
33+
}
34+
35+
[Table("orderitem")]
36+
[PrimaryKey(nameof(ProductId), nameof(OrderId))]
37+
internal class OrderItemEntity
38+
{
39+
public required string ItemCostCurrencyCode { get; set; }
40+
41+
public required long ItemCostUnits { get; set; }
42+
43+
public required int ItemCostNanos { get; set; }
44+
45+
public required string ProductId { get; set; }
46+
47+
public required int Quantity { get; set; }
48+
49+
public required string OrderId { get; set; }
50+
}
51+
52+
[Table("order")]
53+
[PrimaryKey(nameof(Id))]
54+
internal class OrderEntity
55+
{
56+
[Column("order_id")]
57+
public required string Id { get; set; }
58+
59+
}

src/accounting/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ This service consumes new orders from a Kafka topic.
77
To build the service binary, run:
88

99
```sh
10-
cp pb/demo.proto src/accouting/proto/demo.proto # root context
10+
mkdir -p src/accounting/proto/ # root context
11+
cp pb/demo.proto src/accounting/proto/demo.proto # root context
1112
dotnet build # accounting service context
1213
```
1314

src/postgres/init.sql

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-- Copyright The OpenTelemetry Authors
2+
-- SPDX-License-Identifier: Apache-2.0
3+
4+
CREATE USER otelu WITH PASSWORD 'otelp';
5+
6+
7+
-- Create a table
8+
CREATE TABLE "order" (
9+
order_id TEXT PRIMARY KEY
10+
);
11+
12+
CREATE TABLE shipping (
13+
shipping_tracking_id TEXT PRIMARY KEY,
14+
shipping_cost_currency_code TEXT NOT NULL,
15+
shipping_cost_units BIGINT NOT NULL,
16+
shipping_cost_nanos INT NOT NULL,
17+
street_address TEXT,
18+
city TEXT,
19+
state TEXT,
20+
country TEXT,
21+
zip_code TEXT,
22+
order_id TEXT NOT NULL,
23+
FOREIGN KEY (order_id) REFERENCES "order"(order_id) ON DELETE CASCADE
24+
);
25+
26+
CREATE TABLE orderitem (
27+
item_cost_currency_code TEXT NOT NULL,
28+
item_cost_units BIGINT NOT NULL,
29+
item_cost_nanos INT NOT NULL,
30+
product_id TEXT NOT NULL,
31+
quantity INT NOT NULL,
32+
order_id TEXT NOT NULL,
33+
PRIMARY KEY (order_id, product_id),
34+
FOREIGN KEY (order_id) REFERENCES "order"(order_id) ON DELETE CASCADE
35+
);
36+
37+
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO otelu;

0 commit comments

Comments
 (0)