运行 Logstash 时,它会自动捕获可用于监视Logstash部署的运行状况和性能的运行时指标。
Logstash 收集的指标包括:
- Logstash 节点信息,如配置信息,OS 信息和 JVM 信息;
- 插件信息,包括已安装插件的列表;
- 节点统计信息,如 JVM 统计信息,进程统计信息,事件相关(event-related)统计信息和流水线运行时(pipeline runtime)统计信息;
- 热线程;
我们可以使用 X-Pack 中的monitoring UI 来查看这些指标,深入了解 Logstash 如何运行,或者可以使用 Logstash 提供的基本监视 API 来检索这些指标。对于我湾,调研确定采用 searchguard 作为核心安全插件,所以不会为了一个无法整合到监控平台的 X-Pack monitoring 功能而去引入,我决定直接走 API 的方式提供指标数据。
监控 API 介绍
Logstash提供以下监视API来检索有关Logstash的运行时指标:
- 节点信息API
- 插件信息API
- 节点统计API
- 热线程API
您可以使用根资源来检索有关Logstash实例的一般信息,包括主机和版本。
curl -XGET 'localhost:9600/?pretty'
响应示例:
{
"host": "skywalker",
"version": "5.5.0",
"http_address": "127.0.0.1:9600"
}
默认情况下,监视 API 尝试绑定到 tcp:9600。如果此端口已被另一个 Logstash 实例使用,则需要使用指定的—http.port 标志启动 Logstash 以绑定到其他端口。有关详细信息,请参阅命令行标志。
通用选项
以下选项可以应用于所有 Logstash 监控 API。
- Pretty 式返回
当对任何请求进行追加 ?pretty=true
时,返回的 JSON 将被格式化展示(仅用于调试);
- Human-Readable 式输出
对于Logstash 5.5.0,只有 Hot Threads API 支持该选项。当指定
human=true
时,结果将以纯文本而不是 JSON 格式返回。默认值为false。
统计信息会以适合人类阅读的格式(例如 "exists_time": "1h"
or "size": "1kb"
)和计算机适合解释处理的格式(例如 "exists_time_in_millis": 3600000
or "size_in_bytes": 1024
)返回。可以通过向查询字符串添加 ?human=false
来关闭。当统计数据的结果被监视工具消费时,而不是为人类消费而言,这是有道理的。human 标识位默认为 false。
节点信息 API
该 API 用于获取关于 logstash 节点的信息:
curl -XGET 'localhost:9600/_node/<types>'
<types>
是可选项,用来指定返回哪个类型的数据。
我们可以通过以下几种类型的组合来限制返回的信息(类型之间用逗号间隔):
类型 | 描述 |
---|---|
pipeline |
获取 pipeline 相关的信息和配置; |
os |
获取节点级别的 OS 信息; |
jvm |
获取节点级别的 JVM 信息,包括线程信息; |
Pipeline 信息
以下的请求返回 pipeline 相关信息,包括 workers 的数量,批处理大小,以及批处理延迟:
curl -XGET 'localhost:9600/_node/pipeline?pretty'
如果想获得更多的 pipeline 信息,比如各个 input/filter/output 的信息,可以参阅 Pipeline Stats 部分。
返回示例:
{
"pipeline": {
"workers": 8,
"batch_size": 125,
"batch_delay": 5,
"config_reload_automatic": true,
"config_reload_interval": 3
"id" : "main"
}
OS 信息
以下请求返回关于 OS 相关信息,比如 OS 名称、架构、版本和可用的处理器个数:
curl -XGET 'localhost:9600/_node/os?pretty'
返回示例:
{
"os": {
"name": "Mac OS X",
"arch": "x86_64",
"version": "10.12.4",
"available_processors": 8
}
JVM 信息
以下请求返回节点级别 JVM 信息,比如节点级别 JVM 进程号、版本、VM 信息、内存使用率以及 GC 信息:
curl -XGET 'localhost:9600/_node/jvm?pretty'
返回示例:
{
"jvm": {
"pid": 59616,
"version": "1.8.0_65",
"vm_name": "Java HotSpot(TM) 64-Bit Server VM",
"vm_version": "1.8.0_65",
"vm_vendor": "Oracle Corporation",
"start_time_in_millis": 1484251185878,
"mem": {
"heap_init_in_bytes": 268435456,
"heap_max_in_bytes": 1037959168,
"non_heap_init_in_bytes": 2555904,
"non_heap_max_in_bytes": 0
},
"gc_collectors": [
"ParNew",
"ConcurrentMarkSweep"
]
}
}
插件信息 API
插件信息 API 可以获取所有已安装的 logstash 的插件信息。该 API 是基于 bin/logstash-plugin list --verbose
命令返回的信息进行处理后得到的。
curl -XGET 'localhost:9600/_node/plugins?pretty'
返回示例:
{
"total": 93,
"plugins": [
{
"name": "logstash-codec-cef",
"version": "4.1.2"
},
{
"name": "logstash-codec-collectd",
"version": "3.0.3"
},
{
"name": "logstash-codec-dots",
"version": "3.0.2"
},
{
"name": "logstash-codec-edn",
"version": "3.0.2"
},
.
.
.
]
节点状态 API
节点状态 API 用于获取 logstash 运行时的统计信息。
curl -XGET 'localhost:9600/_node/stats/<types>'
<types>
是可选项,用于指定具体返回类型。
默认情况下,所有状态都会返回。我们可以通过各种类型组合(以逗号分隔)来过滤出我们想要的信息:
类型 | 描述 |
---|---|
jvm |
获取 JVM 状态,包括线程信息、内存使用率、GC 和 uptime。 |
process |
获取进程信息,包括文件描述符、内存占用以及 CPU 使用率。 |
pipeline |
获取运行时 logstash pipeline 信息。 |
reloads |
获取运行时配置 reload 的失败和成功信息。 |
os |
获取运行时当 logstash 运行在容器中的 cgroups 信息。 |
JVM 信息
以下请求返回 JVM 信息:
curl -XGET 'localhost:9600/_node/stats/jvm?pretty'
返回示例:
{
"jvm": {
"threads": {
"count": 35,
"peak_count": 36
},
"mem": {
"heap_used_in_bytes": 318691184,
"heap_used_percent": 15,
"heap_committed_in_bytes": 519045120,
"heap_max_in_bytes": 2075918336,
"non_heap_used_in_bytes": 189382304,
"non_heap_committed_in_bytes": 200728576,
"pools": {
"survivor": {
"peak_used_in_bytes": 8912896,
"used_in_bytes": 9538656,
"peak_max_in_bytes": 35782656,
"max_in_bytes": 71565312,
"committed_in_bytes": 17825792
},
"old": {
"peak_used_in_bytes": 106946320,
"used_in_bytes": 181913072,
"peak_max_in_bytes": 715849728,
"max_in_bytes": 1431699456,
"committed_in_bytes": 357957632
},
"young": {
"peak_used_in_bytes": 71630848,
"used_in_bytes": 127239456,
"peak_max_in_bytes": 286326784,
"max_in_bytes": 572653568,
"committed_in_bytes": 143261696
}
}
},
"gc": {
"collectors": {
"old": {
"collection_time_in_millis": 58,
"collection_count": 2
},
"young": {
"collection_time_in_millis": 338,
"collection_count": 26
}
}
},
"uptime_in_millis": 382701
}
进程信息
以下请求返回进程信息:
curl -XGET 'localhost:9600/_node/stats/process?pretty'
返回示例
{
"process": {
"open_file_descriptors": 164,
"peak_open_file_descriptors": 166,
"max_file_descriptors": 10240,
"mem": {
"total_virtual_in_bytes": 5399474176
},
"cpu": {
"total_in_millis": 72810537000,
"percent": 0,
"load_average": {
"1m": 2.41943359375
}
}
}
}
Pipeline 信息
以下请求返回 pipeline 信息,包括:
- Input/filter/output 的事件数量;
- 配置的各个 filter/output 信息;
- Config reload 成功或失败的信息(当 config reload enable 情况下);
- 持久化队列的信息(当 persistent queues enable 情况下);
curl -XGET 'localhost:9600/_node/stats/pipeline?pretty'
返回示例:
{
"pipeline" : {
"events" : {
"duration_in_millis" : 1955,
"in" : 100,
"filtered" : 100,
"out" : 100,
"queue_push_duration_in_millis" : 71
},
"plugins" : {
"inputs" : [ {
"id" : "729b0efdc657715a4a59103ab2643c010fc46e77-1",
"events" : {
"out" : 100,
"queue_push_duration_in_millis" : 71
},
"name" : "beats"
} ],
"filters" : [ {
"id" : "729b0efdc657715a4a59103ab2643c010fc46e77-2",
"events" : {
"duration_in_millis" : 64,
"in" : 100,
"out" : 100
},
"matches" : 100,
"patterns_per_field" : {
"message" : 1
},
"name" : "grok"
} ],
"outputs" : [ {
"id" : "729b0efdc657715a4a59103ab2643c010fc46e77-3",
"events" : {
"duration_in_millis" : 1724,
"in" : 100,
"out" : 100
},
"name" : "stdout"
} ]
},
"reloads" : {
"last_error" : null,
"successes" : 2,
"last_success_timestamp" : "2017-05-25T02:40:40.974Z",
"last_failure_timestamp" : null,
"failures" : 0
},
"queue" : {
"events" : 0,
"type" : "persisted",
"capacity" : {
"page_capacity_in_bytes" : 262144000,
"max_queue_size_in_bytes" : 8589934592,
"max_unread_events" : 0
},
"data" : {
"path" : "/path/to/data/queue",
"free_space_in_bytes" : 89280552960,
"storage_type" : "hfs"
}
},
"id" : "main"
}
}
Reload 信息
以下请求返回配置 reload 成功和失败的信息:
curl -XGET 'localhost:9600/_node/stats/reloads?pretty'
返回示例:
{
"reloads": {
"successes": 0,
"failures": 0
}
}
OS 信息
当 logstash 运行在容器中时,以下请求返回 cgroups 相关信息,我们可以从中获取更精确的 CPU 负载,包括容器是否达到瓶颈:
curl -XGET 'localhost:9600/_node/stats/os?pretty'
返回示例:
{
"os" : {
"cgroup" : {
"cpuacct" : {
"control_group" : "/elastic1",
"usage_nanos" : 378477588075
},
"cpu" : {
"control_group" : "/elastic1",
"cfs_period_micros" : 1000000,
"cfs_quota_micros" : 800000,
"stat" : {
"number_of_elapsed_periods" : 4157,
"number_of_times_throttled" : 460,
"time_throttled_nanos" : 581617440755
}
}
}
}
热线程 API
热线程 API 用来获取当前 logstash 的热线程信息。热线程的定义是:该线程占用很高的 CPU并且执行指令持续很长时间。
curl -XGET 'localhost:9600/_node/hot_threads?pretty'
返回示例:
{
"time": "2017-01-12T12:09:45-08:00",
"busiest_threads": 3,
"threads": [
{
"name": "LogStash::Runner",
"percent_of_cpu_time": 1.07,
"state": "timed_waiting",
"traces": [
"java.lang.Object.wait(Native Method)",
"java.lang.Thread.join(Thread.java:1253)",
"org.jruby.internal.runtime.NativeThread.join(NativeThread.java:75)",
"org.jruby.RubyThread.join(RubyThread.java:697)",
"org.jruby.RubyThread$INVOKER$i$0$1$join.call(RubyThread$INVOKER$i$0$1$join.gen)",
"org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:663)",
"org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:198)",
"org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)",
"org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)",
"org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)"
]
},
{
"name": "[main]>worker7",
"percent_of_cpu_time": 0.71,
"state": "waiting",
"traces": [
"sun.misc.Unsafe.park(Native Method)",
"java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)",
"java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)",
"org.jruby.RubyThread.lockInterruptibly(RubyThread.java:1470)",
"org.jruby.ext.thread.Mutex.lock(Mutex.java:91)",
"org.jruby.ext.thread.Mutex.synchronize(Mutex.java:147)",
"org.jruby.ext.thread.Mutex$INVOKER$i$0$0$synchronize.call(Mutex$INVOKER$i$0$0$synchronize.gen)"
]
},
{
"name": "[main]>worker3",
"percent_of_cpu_time": 0.71,
"state": "waiting",
"traces": [
"sun.misc.Unsafe.park(Native Method)",
"java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)",
"java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)",
"java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)",
"org.jruby.RubyThread.lockInterruptibly(RubyThread.java:1470)",
"org.jruby.ext.thread.Mutex.lock(Mutex.java:91)",
"org.jruby.ext.thread.Mutex.synchronize(Mutex.java:147)",
"org.jruby.ext.thread.Mutex$INVOKER$i$0$0$synchronize.call(Mutex$INVOKER$i$0$0$synchronize.gen)"
]
}
]
}
}
被允许使用的参数包括:
参数 | 描述 |
---|---|
threads |
返回的热线程个数,默认为 3。 |
human |
如为 true,返回 plain text,反之则是 json,默认是 false。 |
ignore_idle_threads |
如为 true,不返回闲置线程,默认是 true。 |
可以使用 ?human
参数返回可读性较高的格式。
curl -XGET 'localhost:9600/_node/hot_threads?human=true'
human-readable 返回示例:
::: {}
Hot threads at 2017-01-12T12:10:15-08:00, busiestThreads=3:
================================================================================
1.02 % of cpu usage, state: timed_waiting, thread name: 'LogStash::Runner'
java.lang.Object.wait(Native Method)
java.lang.Thread.join(Thread.java:1253)
org.jruby.internal.runtime.NativeThread.join(NativeThread.java:75)
org.jruby.RubyThread.join(RubyThread.java:697)
org.jruby.RubyThread$INVOKER$i$0$1$join.call(RubyThread$INVOKER$i$0$1$join.gen)
org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:663)
org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:198)
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
--------------------------------------------------------------------------------
0.71 % of cpu usage, state: waiting, thread name: '[main]>worker7'
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
org.jruby.RubyThread.lockInterruptibly(RubyThread.java:1470)
org.jruby.ext.thread.Mutex.lock(Mutex.java:91)
org.jruby.ext.thread.Mutex.synchronize(Mutex.java:147)
org.jruby.ext.thread.Mutex$INVOKER$i$0$0$synchronize.call(Mutex$INVOKER$i$0$0$synchronize.gen)
--------------------------------------------------------------------------------
0.71 % of cpu usage, state: timed_waiting, thread name: '[main]>worker3'
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:497)
org.jruby.javasupport.JavaMethod.invokeDirectWithExceptionHandling(JavaMethod.java:466)
org.jruby.javasupport.JavaMethod.invokeDirect(JavaMethod.java:324)
参考文献
https://www.elastic.co/guide/en/logstash/current/monitoring-logstash.html