elasticsearch - 如何将日志与 APM 关联起来?
问题描述
我有一个应用程序,它将使用 serilog 将日志写入弹性搜索。我使用 docker-compose 配置了 APM 服务器。一旦我启动应用程序并执行操作(浏览浏览器中的页面),然后关闭应用程序。然后将这些日志记录到 elasticsearch。我遇到了这篇文章,它讨论了将日志与 APM 关联起来。我选择了几个步骤,因为我没有在这个应用程序中使用 python,并注意到 APM 内部有一些事务。
通过这些事务,我将如何将日志相互关联。换句话说,我怎样才能将这些日志绑定在一起?是否有一个唯一的变量/id/key 可以将记录在一个事务中的所有日志绑定在一起(当我启动应用程序,执行操作,然后关闭应用程序时)?
当我查看每个事务时,我注意到它们有一个 transcation_id 和一个 trace_id。但是,它们会随着我执行的每个操作而改变。我想知道这是否可能,如果可能,我如何收集与该单一事务有关的所有日志?例如,如果我通过单个 id 查询,那么所有这些日志都将被返回。
docker-compose.yml
version: '2.2'
services:
apm-server:
image: docker.elastic.co/apm/apm-server:7.13.0
depends_on:
elasticsearch:
condition: service_healthy
kibana:
condition: service_healthy
cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"]
cap_drop: ["ALL"]
ports:
- 8200:8200
networks:
- elastic
command: >
apm-server -e
-E apm-server.rum.enabled=true
-E setup.kibana.host=kibana:5601
-E setup.template.settings.index.number_of_replicas=0
-E apm-server.kibana.enabled=true
-E apm-server.kibana.host=kibana:5601
-E output.elasticsearch.hosts=["elasticsearch:9200"]
healthcheck:
interval: 10s
retries: 12
test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8200/
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.0
environment:
- bootstrap.memory_lock=true
- cluster.name=docker-cluster
- cluster.routing.allocation.disk.threshold_enabled=false
- discovery.type=single-node
- ES_JAVA_OPTS=-XX:UseAVX=2 -Xms1g -Xmx1g
ulimits:
memlock:
hard: -1
soft: -1
volumes:
- esdata:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
healthcheck:
interval: 20s
retries: 10
test: curl -s http://localhost:9200/_cluster/health | grep -vq '"status":"red"'
kibana:
image: docker.elastic.co/kibana/kibana:7.13.0
depends_on:
elasticsearch:
condition: service_healthy
environment:
ELASTICSEARCH_URL: http://elasticsearch:9200
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
ports:
- 5601:5601
networks:
- elastic
healthcheck:
interval: 10s
retries: 20
test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:5601/api/status
volumes:
esdata:
driver: local
networks:
elastic:
driver: bridge
更新
在查看了 的文档后Elastic.Apm.SerilogEnricher
,我继续将其包含到我的Startup.cs
文件和我的Program.cs
文件中。只是想仔细检查一下我是否正确地合并了它。
Startup.cs
:
namespace CustomerSimulatorApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
var logger = new LoggerConfiguration()
.Enrich.WithElasticApmCorrelationInfo()
.WriteTo.Console(outputTemplate: "[{ElasticApmTraceId} {ElasticApmTransactionId} {Message:lj} {NewLine}{Exception}")
.CreateLogger();
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// create a new node instance
var node = new Uri("http://localhost:9200");
// settings instance for the node
var settings = new ConnectionSettings(node);
settings.DefaultFieldNameInferrer(p => p);
services.AddSingleton<IElasticClient>(new ElasticClient(settings));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAllElasticApm(Configuration);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
Program.cs
namespace CustomerSimulatorApp
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog((context, configuration) =>
{
configuration.Enrich.FromLogContext()
.Enrich.WithElasticApmCorrelationInfo()
.Enrich.WithMachineName()
.WriteTo.Console()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(context.Configuration["ElasticConfiguration:Uri"]))
{
IndexFormat = $"{context.Configuration["ApplicationName"]}-logs-{context.HostingEnvironment.EnvironmentName?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}",
AutoRegisterTemplate = true
})
.Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
.ReadFrom.Configuration(context.Configuration);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAllElasticApm();
}
}
我注意到当我运行程序并在浏览器上执行操作然后检查 APM 时 trace.id 和 transaction.id 仍在变化,因此我无法将我在浏览器上执行的单个事务与日志相关联。我是否执行了Elastic.Apm.SerilogEnricher
上述错误?
不同的ID(有更多不同的,但不想用截图扩展它)
它们每页重定向都会更改,因此我无法从单个 ID 收集日志。
这也是我在控制台上看到的更新的 startup.cs 和 program.cs 文件:
我最终关闭了程序:
解决方案
如果您使用 Serilog 将日志发送到 Elasticsearch,并在应用程序中使用 Elastic APM .NET 代理来捕获跟踪,则可以参考Elastic.Apm.SerilogEnricher
使用 APM 跟踪 id 和事务 id 丰富日志(在即将发布的 1.6 版本中,跨度 id ) 如果在记录时有一个活动事务
var logger = new LoggerConfiguration()
.Enrich.WithElasticApmCorrelationInfo()
.WriteTo.Console(outputTemplate: "[{ElasticApmTraceId} {ElasticApmTransactionId} {Message:lj} {NewLine}{Exception}")
.CreateLogger();
查看文档,其中包含更多信息。
推荐阅读
- regex - 确定序列中下一个字符的有效选项
- python - django-rest-framework:使用 ENUMS 和 source='get_label_display' 时的模型序列化程序
- java - 如何为非活动类创建应用程序快捷方式
- .net - Powershell Winforms - 处理窗口事件
- machine-learning - 如何以更少的图像在 CNN 上获得更高的准确性
- ios - 仅为 AppDelegate.m iOS 中的首次启动设置特定方向
- python - 如何将条目的值从一个类传递到另一个类?
- c# - Unity 帮助解决 HTML5 Build 上的 Uncaught Abort
- android - 错误:无法确定 androidx.cardview:cardview:1.0.0 的工件:没有可用于离线模式的缓存版本
- android - 在线性布局中自动调整项目