如何借助OpenTelemetry识别数据库依赖关系?
发布时间:2025-08-02
我们采用SDK含有的OpenTelemetry Protocol(OTLP)Exporter。该推工具让我们可以将统需用据直接发送给遥测统需用据进食公共服务。Jaeger和Lightstep等OpenTelemetry平台单体行踪,鼓励您获得洞察力。
与SDK构建后,软件的各个大多(比如ASP.NET Core允诺指派程序中和SQL应将用领域程序)不会自动开始填充含有系统特质讯息的行踪。您的字符可以填充其他行踪,以多样化需用讯息。
以.NET为例,OpenTelemetry充分利用基于System.Diagnostics.*命名空间中都的现有特特质,如下下图:
System.Diagnostics.ActivitySource代表负责填充Span的OpenTelemetry行踪器。 System.Diagnostics.Activity代表 Span。 您可以采用AddTag参数为span去除特特质。此外,您可以采用AddBaggage功能去除车上。车上被运送到姪娱乐活动,采用W3C标头的其他公共服务中都有姪娱乐活动。测定软件后,您可以调试自动化试验,或而无须浏览器采用您的软件来覆盖面积软件和统计在线中都间的所有交互方向。
示范
不妨成立一个简单的多肽职员管理公共服务(EMS),以SP.NET Core minimal API为模型。我们的API将具有都有交叉处:
POST /ems/billing:记录下来职员为新项目太短的劳基法。 GET /ems/billing/{employeeId}:给予职员为并不相同新项目太短的劳基法。 POST /ems/payroll/add:将职员去除到工资单上。 GET /ems/payroll/{employeeId}:给予职员的工资单统需用据。您不会注意到多肽软件公共服务于两个并不相同的领域:计费和工资单。这种倚赖彼此间在复杂的多肽软件中都似乎不是很突出,将它们复合或多或少似乎须要大量的字符重构。
然而,如果数据分析倚赖彼此间,您可以轻松地将它们复合或多或少。EMS软件的原始源字符可在该GitHub存储特中都找寻。
启动时统计在线
我们再在Docker中都启动时一个SQL server重构:
副本
docker run
-e "ACCEPT_EULA=Y"
-e "SA_PASSWORD=Str0ngPa$$w0rd"
-p 1433:1433
----name monolith-db
----hostname sql1
-d mcr.microsoft.com/mssql/server:2019-latest
我们采用下列SQL脚本来成立我们的软件所采用的EMS统计在线和表:
副本
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'EMSDb')
BEGIN
CREATE DATABASE EMSDb
END
GO
USE EMSDb
IF OBJECT_ID('[dbo].[Timekeeping]', 'U') IS NULL
BEGIN
CREATE TABLE [Timekeeping] (
[EmployeeId] INT NOT NULL,
[ProjectId] INT NOT NULL,
[WeekClosingDate] DATETIME NOT NULL,
[HoursWorked] INT NOT NULL,
CONSTRAINT [PK_Timekeeping] PRIMARY KEY CLUSTERED ([EmployeeId] ASC, [ProjectId] ASC, [WeekClosingDate] ASC)
END
GO
IF OBJECT_ID('[dbo].[Payroll]', 'U') IS NULL
BEGIN
CREATE TABLE [Payroll] (
[EmployeeId] INT NOT NULL,
[PayRateInUSD] MONEY DEFAULT 0 NOT NULL,
CONSTRAINT [PK_Payroll] PRIMARY KEY CLUSTERED ([EmployeeId] ASC)
END
GO
充分利用API公共服务
再一,我们为API交叉处改写字符。我们把Program类中都的;也字符换成都有字符:
副本
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped(_ =>
new SqlConnection(builder.Configuration.GetConnectionString("EmployeeDbConnectionString")));
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.MapPost("/ems/billing", async (Timekeeping timekeepingRecord, SqlConnection db) =>
{
await db.ExecuteAsync(
"INSERT INTO Timekeeping Values(@EmployeeId, @ProjectId, @WeekClosingDate, @HoursWorked)",
timekeepingRecord);
return Results.Created($"/ems/billing/{timekeepingRecord.EmployeeId}", timekeepingRecord);
})
.WithName("RecordProjectWork")
.Produces(StatusCodes.Status201Created);
app.MapGet("/ems/billing/{empId}/", async (int empId, SqlConnection db) =>
{
var result = await db.QueryAsync("SELECT * FROM Timekeeping WHERE EmployeeId=@empId", empId);
return result.Any() ? Results.Ok(result) : Results.NotFound();
})
.WithName("GetBillingDetails")
.Produces
.Produces(StatusCodes.Status404NotFound);
app.MapPost("/ems/payroll/add/", async (Payroll payrollRecord, SqlConnection db) =>
{
await db.ExecuteAsync(
"INSERT INTO Payroll Values(@EmployeeId, @PayRateInUSD)", payrollRecord);
return Results.Created($"/ems/payroll/{payrollRecord.EmployeeId}", payrollRecord);
})
.WithName("AddEmployeeToPayroll")
.Produces(StatusCodes.Status201Created);
app.MapGet("/ems/payroll/{empId}", async (int empId, SqlConnection db) =>
{
var result = await db.QueryAsync("SELECT * FROM Payroll WHERE EmployeeId=@empId", empId);
return result.Any() ? Results.Ok(result) : Results.NotFound();
})
.WithName("GetEmployeePayroll")
.Produces
.Produces(StatusCodes.Status404NotFound);
app.Run();
public class Timekeeping
{
public int EmployeeId { get; set; }
public int ProjectId { get; set; }
public DateTime WeekClosingDate { get; set; }
public int HoursWorked { get; set; }
}
public class Payroll
{
public int EmployeeId { get; set; }
public decimal PayRateInUSD { get; set; }
}
此时,我们可以调试软件,试验各交叉处,并发送给保存在统计在线中都的记录下来。虽然各交叉处和允诺方向的统计在线倚赖彼此间在这个示范示例中都很突出,但在大型软件中都实际似乎并非如此。
再一,不妨使见到统计在线倚赖彼此间的全过程充分利用自动化。
去除测定
我们采用OpenTelemetry SDK和一个大.NET的SqlClient测定特来测定软件。我们再将都有NuGet打包举出去除到API的新项目明文中都:
副本
SDK为我们提供了几种扩展工具,我们可以采用这些工具将OpenTelemetry加速接入到允诺指派燃气。
都有字符在我们的API中都测定OpenTelemetry。它还将测定SqlClient以放出简略的遥测统需用据。来自SqlClient的遥测统需用据是简略辨识统计在线倚赖彼此间的最重要。
副本
// Configure tracing
builder.Services.AddOpenTelemetryTracing(builder => builder
// Customize the traces gathered by the HTTP request handler
.AddAspNetCoreInstrumentation(options =>
{
// Only capture the spans generated from the ems/* endpoints
options.Filter = context => context.Request.Path.Value?.Contains("ems") ?? false;
options.RecordException = true;
// Add metadata for the request such as the HTTP method and response length
options.Enrich = (activity, eventName, rawObject) =>
{
switch (eventName)
{
case "OnStartActivity":
{
if (rawObject is not HttpRequest httpRequest)
{
return;
}
activity.SetTag("requestProtocol", httpRequest.Protocol);
activity.SetTag("requestMethod", httpRequest.Method);
break;
}
case "OnStopActivity":
{
if (rawObject is HttpResponse httpResponse)
{
activity.SetTag("responseLength", httpResponse.ContentLength);
}
break;
}
}
};
})
// Customize the telemetry generated by the SqlClient
.AddSqlClientInstrumentation(options =>
{
options.EnableConnectionLevelAttributes = true;
options.SetDbStatementForStoredProcedure = true;
options.SetDbStatementForText = true;
options.RecordException = true;
options.Enrich = (activity, x, y) => activity.SetTag("db.type", "sql");
})
.AddSource("my-corp.ems.ems-api")
// Create resources (key-value pairs) that describe your service such as service name and version
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ems-api")
.AddAttributes(new[] { new KeyValuePair("service.version", "1.0.0.0") }))
// Ensures that all activities are recorded and sent to exporter
.SetSampler(new AlwaysOnSampler())
// Exports spans to Lightstep
.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new
Uri("");
otlpOptions.Headers = $"lightstep-access-token={lsToken}";
otlpOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
}));
虽然测定在也就是说精神状态下对我们来说必要了,还是不妨去除系统特质行踪,进一步多样化统需用据。
首再,我们定义行踪器,软件的span将来自该行踪器。
副本
var activitySource = new ActivitySource("my-corp.ems.ems-api");
再一,我们成立一个span,并去除系统特质细节、特特质和重大事件:
副本
app.MapPost("/ems/billing", async (Timekeeping timekeepingRecord, SqlConnection db) =>
{
using var activity = activitySource.StartActivity("Record project work", ActivityKind.Server);
activity?.AddEvent(new ActivityEvent("Project billed"));
activity?.SetTag(nameof(Timekeeping.EmployeeId), timekeepingRecord.EmployeeId);
activity?.SetTag(nameof(Timekeeping.ProjectId), timekeepingRecord.ProjectId);
activity?.SetTag(nameof(Timekeeping.WeekClosingDate), timekeepingRecord.WeekClosingDate);
await db.ExecuteAsync(
"INSERT INTO Timekeeping Values(@EmployeeId, @ProjectId, @WeekClosingDate, @HoursWorked)",
timekeepingRecord);
return Results.Created($"/ems/billing/{timekeepingRecord.EmployeeId}", timekeepingRecord);
})
.WithName("RecordProjectWork")
.Produces(StatusCodes.Status201Created);
我们遵循同样的程序中来测定剩余的交叉处。
相连到Lightstep
最后,我们须要一个API加密将行踪讯息发送给Lightstep。我们再成立一个帐户。在该网站的Project所设网址中都,我们找寻接管者(Token),它将充当API加密。
布3. Lightstep中都的API加密我们拷贝接管者,并将它水印到appsettings明文中都。
副本
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"EmployeeDbConnectionString": "Server=localhost;Database=EMSDb;User Id=sa;Password=Str0ngPa$$w0rd;"
},
"LsToken": ""
}
发送允诺
我们的软件已早些。我们启动时软件,向每个交叉处发送一些允诺。都有是我发送给/ems/billing交叉处的允诺。该允诺应将在统计在线的Timekeeping表中都成立一条记录下来。
布4. 将允诺发送给计费交叉处这是我向/emp/payroll/add交叉处放出的另一个允诺,主要用途将记录下来去除到Payroll表:
布5. 将允诺发送给工资单交叉处进入到Lightstep可捕捉到特质网易后,我们可以双击Operations选项卡,发送给Lightstep从软件接管到的所有span。
布6. Lightstep中都发送给来自软件的span我们双击/ems/payroll/add配置后,可以发送给侧到侧行踪。通过发送给span,我们可以考虑到任何允诺的配置顺序。双击span可说明了其重大事件和特特质,更进一步都我们可以非常透彻地认识配置。
行踪中都可见的最后一个span是EMSDb,它是由我们测定的SQL应将用领域程序填充的。双击span可发送给其特特质和重大事件,如下下图:
布7. 工资单交叉处填充的span简略讯息我们可以从特特质得到一些最重要讯息:
统计在线中文名称 统计在线配置中都采用的SQL操作符 SQL操作符的特特质(PDF或存储全过程) 放出允诺的公共服务的主机名我们从/ems/billing配置的姪span中都找寻了四组类似的简略讯息。
布8. 计费交叉处填充的span的简略讯息如果一目了然来自行踪的讯息,我们可以相符合出具体内容:
入站配置(接管外部允诺的配置) 进行时允诺的一系列娱乐活动,打还包括外部公共服务参数调用和统计在线配置。 每个配置涉及的统计在线配置。总之,这些讯息根本无法让我们建设公共服务和统计在线的复合,并为不显公共服务中都间的通信试探特质。
论断本文提问了开发者将多肽软件转换成不显公共服务时碰见的少见过关斩将之一。在所有问题中都,重组统计在线是一项复杂的工作,因为访问统计在线的任何公共服务都可以指派统计在线。
通过采用OpenTelemetry,我们可以辨识各接口中都间以及接口与统计在线中都间的倚赖彼此间。 认识倚赖彼此间后,我们可以为自己的接口制定重构计划案,建设它们作为独立的不显公共服务应将如何奋进。
原文副标题:How to Use OpenTelemetry to Identify Database Dependencies,作者:Rahul Rai
。动脉粥样硬化吃脉血康有用吗视疲劳滴眼药水多久能好
湖南干细胞医院都有哪家
骨质增生
奥美拉唑治疗幽门螺旋杆菌吗

-
2022年,富贵有余,大波好运再次出现的3大生肖
生肖牛 龙神的朋友们都很聪明,贫困也很顺利。他们并不知道,他们能够不断学习仍然领先于他人。他们并没有被时代淘汰。他们冷酷无情,不爱交际。他们喜好把过关斩将当成机遇。他们的动机主要集