DEPSTRCZ

toml

Nov 7th, 2023
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 49.71 KB | None | 0 0
  1. type = "http"
  2. method = "post"
  3. uri = "https://in.logs.betterstack.com/metrics"
  4. encoding.codec = "json"
  5. auth.strategy = "bearer"
  6. auth.token = "enfUhPmsJT6tbkBC5jpkxe9L"
  7. inputs = ["better_stack_docker_metrics_parser_enfUhPmsJT6tbkBC5jpkxe9L"]
  8.  
  9. # --- end of 2023-08-18: https://logs.betterstack.com/vector-toml/ubuntu/enfUhPmsJT6tbkBC5jpkxe9L
  10.  
  11. root@ethernity:/etc/vector# grep vector.toml
  12. ^C
  13. root@ethernity:/etc/vector# ^C
  14. root@ethernity:/etc/vector# ^C
  15. root@ethernity:/etc/vector# cat vector.yaml
  16. # __ __ __
  17. # \ \ / / / /
  18. # \ V / / /
  19. # \_/ \/
  20. #
  21. # V E C T O R
  22. # Configuration
  23. #
  24. # ------------------------------------------------------------------------------
  25. # Website: https://vector.dev
  26. # Docs: https://vector.dev/docs
  27. # Chat: https://chat.vector.dev
  28. # ------------------------------------------------------------------------------
  29.  
  30. # Change this to use a non-default directory for Vector data storage:
  31. # data_dir = "/var/lib/vector"
  32.  
  33. # Random Syslog-formatted logs
  34. sources:
  35. dummy_logs:
  36. type: "demo_logs"
  37. format: "syslog"
  38. interval: 1
  39.  
  40. # Parse Syslog logs
  41. # See the Vector Remap Language reference for more info: https://vrl.dev
  42. transforms:
  43. parse_logs:
  44. type: "remap"
  45. inputs: ["dummy_logs"]
  46. source: |
  47. . = parse_syslog!(string!(.message))
  48.  
  49. # Print parsed logs to stdout
  50. sinks:
  51. print:
  52. type: "console"
  53. inputs: ["parse_logs"]
  54. encoding:
  55. codec: "json"
  56.  
  57. # Vector's GraphQL API (disabled by default)
  58. # Uncomment to try it out with the `vector top` command or
  59. # in your browser at http://localhost:8686
  60. # api:
  61. # enabled: true
  62. # address: "127.0.0.1:8686"
  63. root@ethernity:/etc/vector#
  64. root@ethernity:/etc/vector# cat vector.toml
  65. # __ __ __
  66. # \ \ / / / /
  67. # \ V / / /
  68. # \_/ \/
  69. #
  70. # V E C T O R
  71. # Configuration
  72. #
  73. # ------------------------------------------------------------------------------
  74. # Website: https://vector.dev
  75. # Docs: https://vector.dev/docs
  76. # Chat: https://chat.vector.dev
  77. # ------------------------------------------------------------------------------
  78.  
  79. # Change this to use a non-default directory for Vector data storage:
  80. # data_dir = "/var/lib/vector"
  81.  
  82. # Random Syslog-formatted logs
  83. [sources.dummy_logs]
  84. type = "demo_logs"
  85. format = "syslog"
  86. interval = 1
  87.  
  88. # Parse Syslog logs
  89. # See the Vector Remap Language reference for more info: https://vrl.dev
  90. [transforms.parse_logs]
  91. type = "remap"
  92. inputs = ["dummy_logs"]
  93. source = '''
  94. . = parse_syslog!(string!(.message))
  95. '''
  96.  
  97. # Print parsed logs to stdout
  98. [sinks.print]
  99. type = "console"
  100. inputs = ["parse_logs"]
  101. encoding.codec = "json"
  102.  
  103. # Vector's GraphQL API (disabled by default)
  104. # Uncomment to try it out with the `vector top` command or
  105. # in your browser at http://localhost:8686
  106. #[api]
  107. #enabled = true
  108. #address = "127.0.0.1:8686"
  109.  
  110. # Forwarding logs to Logs.betterstack.com
  111. # ---------------------------------------
  112. # Generated on 2023-08-18: https://logs.betterstack.com/vector-toml/ubuntu/enfUhPmsJT6tbkBC5jpkxe9L
  113. # Learn more about Vector configuration: https://vector.dev/docs/reference/configuration/
  114.  
  115. # - Apache2: v5
  116. # - Nginx: v5
  117. # - PostgreSQL: v5
  118. # - MySQL: v5
  119. # - MongoDB: v5
  120. # - Redis: v5
  121. # - Auth log: v5
  122. # - Uncomplicated Firewall (UFW): v5
  123. # - Docker: v3
  124.  
  125. [sources.better_stack_apache2_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  126. type = "file"
  127. read_from = "beginning"
  128. ignore_older_secs = 600
  129. include = ["/var/log/apache2/*.log"]
  130. exclude = []
  131.  
  132. [transforms.better_stack_apache2_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  133. type = "remap"
  134. inputs = ["better_stack_apache2_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  135. source = '''
  136. del(.source_type)
  137. .dt = del(.timestamp)
  138. .apache2 = parse_apache_log(.message, format: "combined") ??
  139. parse_apache_log(.message, format: "common") ??
  140. parse_apache_log(.message, format: "error") ??
  141. {}
  142.  
  143. if .apache2 != {} {
  144. .platform = "Apache2"
  145.  
  146. .dt = format_timestamp!(parse_timestamp(del(.apache2.timestamp), "%d/%b/%Y:%T %z") ?? .dt, "%+")
  147. .level = del(.apache2.severity)
  148. .message = del(.apache2.message)
  149.  
  150. request_msg = (string(.apache2.method) ?? "") + " " + (string(.apache2.path) ?? "") + " " + (string(.apache2.protocol) ?? "")
  151. if .message == request_msg { del(.message) }
  152. } else {
  153. del(.apache2)
  154. }
  155. '''
  156.  
  157. [sources.better_stack_nginx_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  158. type = "file"
  159. read_from = "beginning"
  160. ignore_older_secs = 600
  161. include = ["/var/log/nginx/*.log"]
  162. exclude = []
  163.  
  164. [transforms.better_stack_nginx_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  165. type = "remap"
  166. inputs = ["better_stack_nginx_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  167. source = '''
  168. del(.source_type)
  169. .dt = del(.timestamp)
  170. .nginx = parse_regex(.message, r'^\s*(-|(?P<client>\S+))\s+\-\s+(-|(?P<user>\S+))\s+\[(?P<timestamp>.+)\]\s+"(?P<request>(?P<method>\w+)\s+(?P<path>\S+)\s+(?P<protocol>\S+))"\s+(?P<status>\d+)\s+(?P<size>\d+)\s+"(-|(?P<referrer>.+))"\s+"(-|(?P<agent>.+))"\s*') ??
  171. parse_regex(.message, r'^\s*(?P<timestamp>.+)\s+\[(?P<severity>\w+)\]\s+(?P<pid>\d+)\#(?P<tid>\d+):\s+\*(?P<cid>\d+)\s+(?P<message>.*)(?:,\s+client:\s+(?P<client>[^,z]+))(?:,\s+server:\s+(?P<server>[^,z]+))(?:,\s+request:\s+"(?P<request>[^"]+)")(?:,\s+subrequest:\s+"(?P<subrequest>[^"]+)")?(?:,\s+upstream:\s+"(?P<upstream>[^"]+)")?(?:,\s+host:\s+"(?P<host>[^"]+)")(?:,\s+referrer:\s+"(?P<referrer>[^"]+)")?\s*') ??
  172. parse_nginx_log(.message, format: "combined") ??
  173. parse_nginx_log(.message, format: "error") ??
  174. {}
  175.  
  176. if .nginx != {} {
  177. .platform = "Nginx"
  178. .level = del(.nginx.severity)
  179. .message = del(.nginx.message)
  180.  
  181. if is_null(.message) { del(.message) }
  182. if exists(.nginx.timestamp) {
  183. .dt = format_timestamp!(
  184. parse_timestamp(.nginx.timestamp, "%d/%b/%Y:%T %z") ??
  185. parse_timestamp(.nginx.timestamp, "%Y/%m/%d %T") ??
  186. .dt,
  187. "%+"
  188. )
  189.  
  190. del(.nginx.timestamp)
  191. }
  192.  
  193. if is_string(.nginx.status) { .nginx.status = to_int(.nginx.status) ?? .nginx.status }
  194. if is_string(.nginx.size) { .nginx.size = to_int(.nginx.size) ?? .nginx.size }
  195. if is_string(.nginx.cid) { .nginx.cid = to_int(.nginx.cid) ?? .nginx.cid }
  196. if is_string(.nginx.pid) { .nginx.pid = to_int(.nginx.pid) ?? .nginx.pid }
  197. if is_string(.nginx.tid) { .nginx.tid = to_int(.nginx.tid) ?? .nginx.tid }
  198.  
  199. if is_null(.nginx.subrequest) { del(.nginx.subrequest) }
  200. if is_null(.nginx.upstream) { del(.nginx.upstream) }
  201. if is_null(.nginx.referrer) { del(.nginx.referrer) }
  202. } else {
  203. del(.nginx)
  204. }
  205. '''
  206.  
  207. [sources.better_stack_postgresql_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  208. type = "file"
  209. read_from = "beginning"
  210. ignore_older_secs = 600
  211. include = ["/var/log/postgresql/*.log"]
  212. exclude = []
  213.  
  214. [transforms.better_stack_postgresql_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  215. type = "remap"
  216. inputs = ["better_stack_postgresql_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  217. source = '''
  218. del(.source_type)
  219. .dt = del(.timestamp)
  220. .postgres = parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+ \d+:\d+:\d+\.\d+ \S+) \[(?P<pid>\d+)\] (?:(?:(?P<username>\S+)@(?P<database>\S+))?\s*(?P<level>\w+):\s*(?P<message>.*))?') ?? {}
  221.  
  222. if .postgres != {} {
  223. .platform = "PostgreSQL"
  224. if exists(.postgres.pid) { .postgres.pid = to_int!(.postgres.pid) }
  225. if exists(.postgres.level) { .level = downcase!(del(.postgres.level)) }
  226. if exists(.postgres.message) { .message = del(.postgres.message) }
  227.  
  228. if exists(.postgres.dt) {
  229. parsed_dt = to_string(.postgres.dt)
  230.  
  231. if !ends_with(parsed_dt, " UTC") {
  232. .postgres.local_date_time = del(.postgres.dt)
  233. } else {
  234. .dt = del(.postgres.dt)
  235. }
  236. }
  237.  
  238. # extract message metadata
  239. tmp = string!(.message)
  240. .message_metadata = {}
  241.  
  242. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  243. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  244. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  245. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  246. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  247.  
  248. # we match only full IPv6 addresses
  249. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  250. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  251. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  252. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  253. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  254. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  255.  
  256. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  257. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  258. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  259. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  260. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  261. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  262. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  263. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  264. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  265. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  266. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  267.  
  268. } else {
  269. del(.postgres)
  270. }
  271. '''
  272.  
  273. [sources.better_stack_mysql_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  274. type = "file"
  275. read_from = "beginning"
  276. ignore_older_secs = 600
  277. include = ["/var/log/mysql/*.log"]
  278. exclude = []
  279.  
  280. [transforms.better_stack_mysql_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  281. type = "remap"
  282. inputs = ["better_stack_mysql_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  283. source = '''
  284. del(.source_type)
  285. .dt = del(.timestamp)
  286. .mysql = parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P<thread>\d+)\s+\[(?P<priority>\S+)\]\s*\[(?P<error_code>\S+)\]\s*\[(?P<subsystem>\S+)\]\s*(?P<message>.*)') ??
  287. parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s*(?P<id>\d+)\s*(?P<command>[^\t]+)\s*(?P<message>.*)?') ??
  288. {}
  289.  
  290. if .mysql != {} {
  291. .platform = "MySQL"
  292. if exists(.mysql.dt) { .dt = del(.mysql.dt) }
  293. if exists(.mysql.thread) { .mysql.thread = to_int!(.mysql.thread) }
  294. if exists(.mysql.id) { .mysql.id = to_int!(.mysql.id) }
  295. .message = del(.mysql.message)
  296.  
  297. # extract message metadata
  298. tmp = string!(.message)
  299. .message_metadata = {}
  300.  
  301. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  302. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  303. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  304. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  305. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  306.  
  307. # we match only full IPv6 addresses
  308. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  309. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  310. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  311. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  312. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  313. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  314.  
  315. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  316. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  317. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  318. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  319. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  320. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  321. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  322. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  323. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  324. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  325. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  326.  
  327. } else {
  328. del(.mysql)
  329. }
  330. '''
  331.  
  332. [sources.better_stack_mongodb_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  333. type = "file"
  334. read_from = "beginning"
  335. ignore_older_secs = 600
  336. include = ["/var/log/mongodb/*.log"]
  337. exclude = []
  338.  
  339. [transforms.better_stack_mongodb_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  340. type = "remap"
  341. inputs = ["better_stack_mongodb_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  342. source = '''
  343. del(.source_type)
  344. .dt = del(.timestamp)
  345. .mongodb = object!(parse_json(.message) ?? {})
  346.  
  347. if .mongodb != {} && exists(.mongodb.t."$$date") {
  348. .platform = "MongoDB"
  349. .dt = .mongodb.t."$$date"
  350. .message = del(.mongodb.msg)
  351.  
  352. if .mongodb.s == "I" {
  353. .level = "info"
  354. } else if .mongodb.s == "W" {
  355. .level = "warning"
  356. } else if .mongodb.s == "E" {
  357. .level = "error"
  358. } else if .mongodb.s == "F" {
  359. .level = "fatal"
  360. } else if .mongodb.s == "D" {
  361. .level = "debug"
  362. } else if .mongodb.s == "D1" {
  363. .level = "debug1"
  364. } else if .mongodb.s == "D2" {
  365. .level = "debug2"
  366. } else if .mongodb.s == "D3" {
  367. .level = "debug3"
  368. } else if .mongodb.s == "D4" {
  369. .level = "debug4"
  370. } else if .mongodb.s == "D5" {
  371. .level = "debug5"
  372. }
  373.  
  374. # extract message metadata
  375. tmp = string!(.message)
  376. .message_metadata = {}
  377.  
  378. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  379. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  380. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  381. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  382. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  383.  
  384. # we match only full IPv6 addresses
  385. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  386. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  387. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  388. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  389. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  390. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  391.  
  392. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  393. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  394. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  395. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  396. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  397. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  398. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  399. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  400. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  401. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  402. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  403.  
  404. } else {
  405. del(.mongodb)
  406. }
  407. '''
  408.  
  409. [sources.better_stack_redis_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  410. type = "file"
  411. read_from = "beginning"
  412. ignore_older_secs = 600
  413. include = ["/var/log/redis/*.log"]
  414. exclude = []
  415.  
  416. [transforms.better_stack_redis_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  417. type = "remap"
  418. inputs = ["better_stack_redis_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  419. source = '''
  420. del(.source_type)
  421. .dt = del(.timestamp)
  422. .redis = parse_regex(.message, r'^(?P<pid>\d+):(?P<role_char>\w)\s+(?P<dt>\d+ \w+ \d+ \d{2}:\d{2}:\d{2}.\d+) (?P<level_symbol>.) (?P<message>.*)') ??
  423. parse_regex(.message, r'^(?P<pid>\d+):(?P<role>\S+) \((?P<unix_timestamp>\d+)\) (?P<message>.*)') ??
  424. {}
  425.  
  426. if .redis != {} {
  427. .platform = "Redis"
  428. if .redis.role_char == "M" {
  429. .redis.role = "master"
  430. } else if .redis.role_char == "S" {
  431. .redis.role = "slave"
  432. } else if .redis.role_char == "C" {
  433. .redis.role = "RDB/AOF writing child"
  434. } else if .redis.role_char == "X" {
  435. .redis.role = "sentinel"
  436. }
  437.  
  438. if .redis.level_symbol == "." {
  439. .level = "debug"
  440. } else if .redis.level_symbol == "-" {
  441. .level = "verbose"
  442. } else if .redis.level_symbol == "*" {
  443. .level = "notice"
  444. } else if .redis.level_symbol == "#" {
  445. .level = "warning"
  446. }
  447.  
  448. .redis.pid = to_int(.redis.pid) ?? null
  449.  
  450. if exists(.redis.dt) {
  451. .dt = format_timestamp!(parse_timestamp(del(.redis.dt), "%d %b %Y %T%.f") ?? now(), "%+")
  452. } else if exists(.redis.unix_timestamp) {
  453. .dt = format_timestamp!(to_timestamp(del(.redis.unix_timestamp)) ?? now(), "%+")
  454. }
  455.  
  456. .message = del(.redis.message)
  457.  
  458. # extract message metadata
  459. tmp = string!(.message)
  460. .message_metadata = {}
  461.  
  462. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  463. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  464. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  465. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  466. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  467.  
  468. # we match only full IPv6 addresses
  469. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  470. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  471. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  472. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  473. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  474. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  475.  
  476. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  477. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  478. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  479. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  480. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  481. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  482. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  483. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  484. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  485. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  486. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  487.  
  488. } else {
  489. del(.redis)
  490. }
  491. '''
  492.  
  493. [sources.better_stack_auth_log_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  494. type = "file"
  495. read_from = "beginning"
  496. ignore_older_secs = 600
  497. include = ["/var/log/auth.log"]
  498. exclude = []
  499.  
  500. [transforms.better_stack_auth_log_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  501. type = "remap"
  502. inputs = ["better_stack_auth_log_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  503. source = '''
  504. del(.source_type)
  505. .dt = del(.timestamp)
  506. .auth_log = parse_linux_authorization(.message) ?? {}
  507.  
  508. if .auth_log != {} {
  509. .platform = "Linux Authorization"
  510. .dt = del(.auth_log.timestamp)
  511. .message = del(.auth_log.message)
  512.  
  513. # extract message metadata
  514. tmp = string!(.message)
  515. .message_metadata = {}
  516.  
  517. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  518. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  519. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  520. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  521. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  522.  
  523. # we match only full IPv6 addresses
  524. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  525. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  526. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  527. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  528. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  529. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  530.  
  531. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  532. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  533. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  534. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  535. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  536. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  537. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  538. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  539. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  540. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  541. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  542.  
  543. } else {
  544. del(.auth_log)
  545. }
  546. '''
  547.  
  548. [sources.better_stack_ufw_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  549. type = "file"
  550. read_from = "beginning"
  551. ignore_older_secs = 600
  552. include = ["/var/log/ufw.log"]
  553. exclude = []
  554.  
  555. [transforms.better_stack_ufw_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  556. type = "remap"
  557. inputs = ["better_stack_ufw_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  558. source = '''
  559. del(.source_type)
  560. .dt = del(.timestamp)
  561. .ufw = parse_regex(.message, r'(?P<local_date_time>\w+\s+\d+\s+\d{2}:\d{2}:\d{2})\s+(?P<host>\S+)\s+kernel:\s*(?:\[\s*(?P<kernel_time>\d+(?:.\d+))?\s*\])?\s*\[UFW (?P<action>\w+)\]\s+(?P<data>.*)') ?? {}
  562.  
  563. if .ufw != {} {
  564. .platform = "UFW"
  565.  
  566. if exists(.ufw.kernel_time) { .ufw.kernel_time = to_float!(.ufw.kernel_time) }
  567.  
  568. .ufw |= parse_regex(.ufw.data, r'\bIN=(?P<in>\S+)(?:$|\s)') ?? {}
  569. .ufw |= parse_regex(.ufw.data, r'\bOUT=(?P<out>\S+)(?:$|\s)') ?? {}
  570.  
  571. .ufw |= parse_regex(.ufw.data, r'\bSRC=(?P<src>(?:\d{1,3}\.\b){3}\d{1,3})(?:$|\s)') ?? {}
  572. .ufw |= parse_regex(.ufw.data, r'\bDST=(?P<dst>(?:\d{1,3}\.\b){3}\d{1,3})(?:$|\s)') ?? {}
  573.  
  574. .ufw |= parse_regex(.ufw.data, r'\bPROTO=(?P<proto>\S+)(?:$|\s)') ?? {}
  575. .ufw |= parse_regex(.ufw.data, r'\bMAC=(?P<mac>(?:\w{2}:)*\w{2})(?:$|\s)') ?? {}
  576.  
  577. .ufw |= parse_regex(.ufw.data, r'\bTOS=(?P<tos>\S+)(?:$|\s)') ?? {}
  578. .ufw |= parse_regex(.ufw.data, r'\bPREC=(?P<prec>\S+)(?:$|\s)') ?? {}
  579. .ufw |= parse_regex(.ufw.data, r'\bRES=(?P<res>\S+)(?:$|\s)') ?? {}
  580.  
  581. .ufw |= parse_regex(.ufw.data, r'\bTTL=(?P<ttl>\d+)(?:$|\s)') ?? {}
  582. .ufw |= parse_regex(.ufw.data, r'\bWINDOW=(?P<window>\d+)(?:$|\s)') ?? {}
  583. .ufw |= parse_regex(.ufw.data, r'\bDPT=(?P<dpt>\d+)(?:$|\s)') ?? {}
  584. .ufw |= parse_regex(.ufw.data, r'\bID=(?P<id>\d+)(?:$|\s)') ?? {}
  585. .ufw |= parse_regex(.ufw.data, r'\bLEN=(?P<len>\d+)(?:$|\s)') ?? {}
  586. .ufw |= parse_regex(.ufw.data, r'\bSPT=(?P<spt>\d+)(?:$|\s)') ?? {}
  587. .ufw |= parse_regex(.ufw.data, r'\bURGP=(?P<urgp>\d+)(?:$|\s)') ?? {}
  588. .ufw.ttl = to_int(.ufw.ttl) ?? .ufw.ttl
  589. .ufw.window = to_int(.ufw.window) ?? .ufw.window
  590. .ufw.dpt = to_int(.ufw.dpt) ?? .ufw.dpt
  591. .ufw.id = to_int(.ufw.id) ?? .ufw.id
  592. .ufw.len = to_int(.ufw.len) ?? .ufw.len
  593. .ufw.spt = to_int(.ufw.spt) ?? .ufw.spt
  594. .ufw.urgp = to_int(.ufw.urgp) ?? .ufw.urgp
  595.  
  596. ufw_data = string!(.ufw.data)
  597. if match(ufw_data, r'\bSYN(?:$|\s)') { .ufw.syn = true }
  598. if match(ufw_data, r'\bDF(?:$|\s)') { .ufw.df = true }
  599. if match(ufw_data, r'\bCWR(?:$|\s)') { .ufw.cwr = true }
  600. if match(ufw_data, r'\bECE(?:$|\s)') { .ufw.ece = true }
  601. if match(ufw_data, r'\bACK(?:$|\s)') { .ufw.ack = true }
  602. if match(ufw_data, r'\bPSH(?:$|\s)') { .ufw.psh = true }
  603.  
  604. .message = (.ufw.action + " " + del(.ufw.data)) ?? .message
  605. } else {
  606. del(.ufw)
  607. }
  608. '''
  609.  
  610. [sources.better_stack_docker_logs_enfUhPmsJT6tbkBC5jpkxe9L]
  611. type = "docker_logs"
  612.  
  613. [sources.better_stack_docker_metrics_enfUhPmsJT6tbkBC5jpkxe9L]
  614. type = "exec"
  615. command = [ "docker", "stats", "--format", "json" ]
  616. decoding.codec = "bytes"
  617. mode = "streaming"
  618.  
  619. [transforms.better_stack_docker_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  620. type = "remap"
  621. inputs = ["better_stack_docker_logs_enfUhPmsJT6tbkBC5jpkxe9L"]
  622. source = '''
  623. del(.source_type)
  624. .dt = del(.timestamp)
  625. .docker = del(.)
  626. .dt = del(.docker.dt)
  627. .message = del(.docker.message)
  628. .platform = "Docker"
  629.  
  630. .apache2 = parse_apache_log(.message, format: "combined") ??
  631. parse_apache_log(.message, format: "common") ??
  632. parse_apache_log(.message, format: "error") ??
  633. {}
  634.  
  635. if .apache2 != {} {
  636. .platform = "Apache2"
  637.  
  638. .dt = format_timestamp!(parse_timestamp(del(.apache2.timestamp), "%d/%b/%Y:%T %z") ?? .dt, "%+")
  639. .level = del(.apache2.severity)
  640. .message = del(.apache2.message)
  641.  
  642. request_msg = (string(.apache2.method) ?? "") + " " + (string(.apache2.path) ?? "") + " " + (string(.apache2.protocol) ?? "")
  643. if .message == request_msg { del(.message) }
  644. } else {
  645. del(.apache2)
  646. }
  647.  
  648. .nginx = parse_regex(.message, r'^\s*(-|(?P<client>\S+))\s+\-\s+(-|(?P<user>\S+))\s+\[(?P<timestamp>.+)\]\s+"(?P<request>(?P<method>\w+)\s+(?P<path>\S+)\s+(?P<protocol>\S+))"\s+(?P<status>\d+)\s+(?P<size>\d+)\s+"(-|(?P<referrer>.+))"\s+"(-|(?P<agent>.+))"\s*') ??
  649. parse_regex(.message, r'^\s*(?P<timestamp>.+)\s+\[(?P<severity>\w+)\]\s+(?P<pid>\d+)\#(?P<tid>\d+):\s+\*(?P<cid>\d+)\s+(?P<message>.*)(?:,\s+client:\s+(?P<client>[^,z]+))(?:,\s+server:\s+(?P<server>[^,z]+))(?:,\s+request:\s+"(?P<request>[^"]+)")(?:,\s+subrequest:\s+"(?P<subrequest>[^"]+)")?(?:,\s+upstream:\s+"(?P<upstream>[^"]+)")?(?:,\s+host:\s+"(?P<host>[^"]+)")(?:,\s+referrer:\s+"(?P<referrer>[^"]+)")?\s*') ??
  650. parse_nginx_log(.message, format: "combined") ??
  651. parse_nginx_log(.message, format: "error") ??
  652. {}
  653.  
  654. if .nginx != {} {
  655. .platform = "Nginx"
  656. .level = del(.nginx.severity)
  657. .message = del(.nginx.message)
  658.  
  659. if is_null(.message) { del(.message) }
  660. if exists(.nginx.timestamp) {
  661. .dt = format_timestamp!(
  662. parse_timestamp(.nginx.timestamp, "%d/%b/%Y:%T %z") ??
  663. parse_timestamp(.nginx.timestamp, "%Y/%m/%d %T") ??
  664. .dt,
  665. "%+"
  666. )
  667.  
  668. del(.nginx.timestamp)
  669. }
  670.  
  671. if is_string(.nginx.status) { .nginx.status = to_int(.nginx.status) ?? .nginx.status }
  672. if is_string(.nginx.size) { .nginx.size = to_int(.nginx.size) ?? .nginx.size }
  673. if is_string(.nginx.cid) { .nginx.cid = to_int(.nginx.cid) ?? .nginx.cid }
  674. if is_string(.nginx.pid) { .nginx.pid = to_int(.nginx.pid) ?? .nginx.pid }
  675. if is_string(.nginx.tid) { .nginx.tid = to_int(.nginx.tid) ?? .nginx.tid }
  676.  
  677. if is_null(.nginx.subrequest) { del(.nginx.subrequest) }
  678. if is_null(.nginx.upstream) { del(.nginx.upstream) }
  679. if is_null(.nginx.referrer) { del(.nginx.referrer) }
  680. } else {
  681. del(.nginx)
  682. }
  683.  
  684. # we can't distinguish apache and nginx logs (they have the same format)
  685. # so we merge them under the generalized "HTTP" platform
  686. if .platform == "Apache2" || .platform == "Nginx" {
  687. apache2 = del(.apache2)
  688. if is_null(apache2) { apache2 = {} }
  689.  
  690. nginx = del(.nginx)
  691. if is_null(nginx) { nginx = {} }
  692.  
  693. .platform = "HTTP"
  694. .http = merge!(apache2, nginx)
  695. }
  696.  
  697.  
  698. .postgres = parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+ \d+:\d+:\d+\.\d+ \S+) \[(?P<pid>\d+)\] (?:(?:(?P<username>\S+)@(?P<database>\S+))?\s*(?P<level>\w+):\s*(?P<message>.*))?') ?? {}
  699.  
  700. if .postgres != {} {
  701. .platform = "PostgreSQL"
  702. if exists(.postgres.pid) { .postgres.pid = to_int!(.postgres.pid) }
  703. if exists(.postgres.level) { .level = downcase!(del(.postgres.level)) }
  704. if exists(.postgres.message) { .message = del(.postgres.message) }
  705.  
  706. if exists(.postgres.dt) {
  707. parsed_dt = to_string(.postgres.dt)
  708.  
  709. if !ends_with(parsed_dt, " UTC") {
  710. .postgres.local_date_time = del(.postgres.dt)
  711. } else {
  712. .dt = del(.postgres.dt)
  713. }
  714. }
  715.  
  716. # extract message metadata
  717. tmp = string!(.message)
  718. .message_metadata = {}
  719.  
  720. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  721. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  722. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  723. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  724. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  725.  
  726. # we match only full IPv6 addresses
  727. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  728. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  729. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  730. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  731. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  732. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  733.  
  734. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  735. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  736. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  737. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  738. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  739. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  740. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  741. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  742. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  743. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  744. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  745.  
  746. } else {
  747. del(.postgres)
  748. }
  749.  
  750. .mysql = parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s+(?P<thread>\d+)\s+\[(?P<priority>\S+)\]\s*\[(?P<error_code>\S+)\]\s*\[(?P<subsystem>\S+)\]\s*(?P<message>.*)') ??
  751. parse_regex(.message, r'^(?P<dt>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\w+)\s*(?P<id>\d+)\s*(?P<command>[^\t]+)\s*(?P<message>.*)?') ??
  752. {}
  753.  
  754. if .mysql != {} {
  755. .platform = "MySQL"
  756. if exists(.mysql.dt) { .dt = del(.mysql.dt) }
  757. if exists(.mysql.thread) { .mysql.thread = to_int!(.mysql.thread) }
  758. if exists(.mysql.id) { .mysql.id = to_int!(.mysql.id) }
  759. .message = del(.mysql.message)
  760.  
  761. # extract message metadata
  762. tmp = string!(.message)
  763. .message_metadata = {}
  764.  
  765. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  766. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  767. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  768. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  769. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  770.  
  771. # we match only full IPv6 addresses
  772. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  773. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  774. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  775. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  776. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  777. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  778.  
  779. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  780. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  781. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  782. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  783. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  784. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  785. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  786. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  787. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  788. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  789. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  790.  
  791. } else {
  792. del(.mysql)
  793. }
  794.  
  795. .mongodb = object!(parse_json(.message) ?? {})
  796.  
  797. if .mongodb != {} && exists(.mongodb.t."$$date") {
  798. .platform = "MongoDB"
  799. .dt = .mongodb.t."$$date"
  800. .message = del(.mongodb.msg)
  801.  
  802. if .mongodb.s == "I" {
  803. .level = "info"
  804. } else if .mongodb.s == "W" {
  805. .level = "warning"
  806. } else if .mongodb.s == "E" {
  807. .level = "error"
  808. } else if .mongodb.s == "F" {
  809. .level = "fatal"
  810. } else if .mongodb.s == "D" {
  811. .level = "debug"
  812. } else if .mongodb.s == "D1" {
  813. .level = "debug1"
  814. } else if .mongodb.s == "D2" {
  815. .level = "debug2"
  816. } else if .mongodb.s == "D3" {
  817. .level = "debug3"
  818. } else if .mongodb.s == "D4" {
  819. .level = "debug4"
  820. } else if .mongodb.s == "D5" {
  821. .level = "debug5"
  822. }
  823.  
  824. # extract message metadata
  825. tmp = string!(.message)
  826. .message_metadata = {}
  827.  
  828. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  829. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  830. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  831. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  832. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  833.  
  834. # we match only full IPv6 addresses
  835. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  836. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  837. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  838. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  839. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  840. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  841.  
  842. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  843. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  844. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  845. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  846. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  847. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  848. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  849. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  850. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  851. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  852. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  853.  
  854. } else {
  855. del(.mongodb)
  856. }
  857.  
  858. .redis = parse_regex(.message, r'^(?P<pid>\d+):(?P<role_char>\w)\s+(?P<dt>\d+ \w+ \d+ \d{2}:\d{2}:\d{2}.\d+) (?P<level_symbol>.) (?P<message>.*)') ??
  859. parse_regex(.message, r'^(?P<pid>\d+):(?P<role>\S+) \((?P<unix_timestamp>\d+)\) (?P<message>.*)') ??
  860. {}
  861.  
  862. if .redis != {} {
  863. .platform = "Redis"
  864. if .redis.role_char == "M" {
  865. .redis.role = "master"
  866. } else if .redis.role_char == "S" {
  867. .redis.role = "slave"
  868. } else if .redis.role_char == "C" {
  869. .redis.role = "RDB/AOF writing child"
  870. } else if .redis.role_char == "X" {
  871. .redis.role = "sentinel"
  872. }
  873.  
  874. if .redis.level_symbol == "." {
  875. .level = "debug"
  876. } else if .redis.level_symbol == "-" {
  877. .level = "verbose"
  878. } else if .redis.level_symbol == "*" {
  879. .level = "notice"
  880. } else if .redis.level_symbol == "#" {
  881. .level = "warning"
  882. }
  883.  
  884. .redis.pid = to_int(.redis.pid) ?? null
  885.  
  886. if exists(.redis.dt) {
  887. .dt = format_timestamp!(parse_timestamp(del(.redis.dt), "%d %b %Y %T%.f") ?? now(), "%+")
  888. } else if exists(.redis.unix_timestamp) {
  889. .dt = format_timestamp!(to_timestamp(del(.redis.unix_timestamp)) ?? now(), "%+")
  890. }
  891.  
  892. .message = del(.redis.message)
  893.  
  894. # extract message metadata
  895. tmp = string!(.message)
  896. .message_metadata = {}
  897.  
  898. ips = parse_regex_all!(tmp, r'\b(?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\b') if exists(ips[0].ip) { .message_metadata.ipv4_1 = ips[0].ip; tmp = replace(tmp, string!(ips[0].ip), "") }
  899. if exists(ips[1].ip) { .message_metadata.ipv4_2 = ips[1].ip; tmp = replace(tmp, string!(ips[1].ip), "") }
  900. if exists(ips[2].ip) { .message_metadata.ipv4_3 = ips[2].ip; tmp = replace(tmp, string!(ips[2].ip), "") }
  901. if exists(ips[3].ip) { .message_metadata.ipv4_4 = ips[3].ip; tmp = replace(tmp, string!(ips[3].ip), "") }
  902. if exists(ips[4].ip) { .message_metadata.ipv4_5 = ips[4].ip; tmp = replace(tmp, string!(ips[4].ip), "") }
  903.  
  904. # we match only full IPv6 addresses
  905. ipv6s = parse_regex_all!(tmp, r'\b(?P<ip>(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})\b')
  906. if exists(ipv6s[0].ip) { .message_metadata.ipv6_1 = ipv6s[0].ip; tmp = replace(tmp, string!(ipv6s[0].ip), "") }
  907. if exists(ipv6s[1].ip) { .message_metadata.ipv6_2 = ipv6s[1].ip; tmp = replace(tmp, string!(ipv6s[1].ip), "") }
  908. if exists(ipv6s[2].ip) { .message_metadata.ipv6_3 = ipv6s[2].ip; tmp = replace(tmp, string!(ipv6s[2].ip), "") }
  909. if exists(ipv6s[3].ip) { .message_metadata.ipv6_4 = ipv6s[3].ip; tmp = replace(tmp, string!(ipv6s[3].ip), "") }
  910. if exists(ipv6s[4].ip) { .message_metadata.ipv6_5 = ipv6s[4].ip; tmp = replace(tmp, string!(ipv6s[4].ip), "") }
  911.  
  912. numbers = parse_regex_all!(tmp, r'(?P<num>\b\d+(?:\.\d+)?\b)')
  913. if exists(numbers[0].num) { .message_metadata.param1 = to_int(numbers[0].num) ?? to_float(numbers[0].num) ?? null }
  914. if exists(numbers[1].num) { .message_metadata.param2 = to_int(numbers[1].num) ?? to_float(numbers[1].num) ?? null }
  915. if exists(numbers[2].num) { .message_metadata.param3 = to_int(numbers[2].num) ?? to_float(numbers[2].num) ?? null }
  916. if exists(numbers[3].num) { .message_metadata.param4 = to_int(numbers[3].num) ?? to_float(numbers[3].num) ?? null }
  917. if exists(numbers[4].num) { .message_metadata.param5 = to_int(numbers[4].num) ?? to_float(numbers[4].num) ?? null }
  918. if exists(numbers[5].num) { .message_metadata.param6 = to_int(numbers[5].num) ?? to_float(numbers[5].num) ?? null }
  919. if exists(numbers[6].num) { .message_metadata.param7 = to_int(numbers[6].num) ?? to_float(numbers[6].num) ?? null }
  920. if exists(numbers[7].num) { .message_metadata.param8 = to_int(numbers[7].num) ?? to_float(numbers[7].num) ?? null }
  921. if exists(numbers[8].num) { .message_metadata.param9 = to_int(numbers[8].num) ?? to_float(numbers[8].num) ?? null }
  922. if exists(numbers[9].num) { .message_metadata.param10 = to_int(numbers[9].num) ?? to_float(numbers[9].num) ?? null }
  923.  
  924. } else {
  925. del(.redis)
  926. }
  927. '''
  928.  
  929. [transforms.better_stack_docker_metrics_parser_enfUhPmsJT6tbkBC5jpkxe9L]
  930. type = "remap"
  931. inputs = ["better_stack_docker_metrics_enfUhPmsJT6tbkBC5jpkxe9L"]
  932. source = '''
  933. del(.source_type)
  934. .dt = del(.timestamp)
  935. raw_data = .message
  936. dt = .timestamp
  937. host = .host
  938. pid = .pid
  939.  
  940. . = []
  941. data, err = parse_json(strip_ansi_escape_codes(string!(raw_data)))
  942. if err == null {
  943. container_id = data.Container
  944. container_name = data.Name
  945.  
  946. gauges = {
  947. "cpu_percentage": to_float(replace(data.CPUPerc, "%", "") ?? "") ?? null,
  948. "memory_percentage": to_float(replace(data.MemPerc, "%", "") ?? "") ?? null,
  949. "memory_used_bytes": split(data.MemUsage, " / ")[0] ?? null,
  950. "memory_limit_bytes": split(data.MemUsage, " / ")[1] ?? null,
  951. "block_in_bytes": split(data.BlockIO, " / ")[0] ?? null,
  952. "block_out_bytes": split(data.BlockIO, " / ")[1] ?? null,
  953. "network_in_bytes": split(data.NetIO, " / ")[0] ?? null,
  954. "network_out_bytes": split(data.NetIO, " / ")[1] ?? null,
  955. "pids_count": to_int(data.PIDs) ?? null
  956. }
  957.  
  958. gauges_bytes = map_values(gauges) -> |data| {
  959. if !is_string(data) {
  960. data
  961. } else {
  962. data = string!(data)
  963. if !ends_with(data, "B") {
  964. data
  965. } else if ends_with(data, "TiB") {
  966. round(1024 * 1024 * 1024 * 1024 * to_float(replace(data, "TiB", "")) ?? null) ?? null
  967. } else if ends_with(data, "GiB") {
  968. round(1024 * 1024 * 1024 * to_float(replace(data, "GiB", "")) ?? null) ?? null
  969. } else if ends_with(data, "MiB") {
  970. round(1024 * 1024 * to_float(replace(data, "MiB", "")) ?? null) ?? null
  971. } else if ends_with(data, "KiB") {
  972. round(1024 * to_float(replace(data, "KiB", "")) ?? null) ?? null
  973. } else if ends_with(data, "TB") {
  974. round(1000 * 1000 * 1000 * 1000 * to_float(replace(data, "TB", "")) ?? null) ?? null
  975. } else if ends_with(data, "GB") {
  976. round(1000 * 1000 * 1000 * to_float(replace(data, "GB", "")) ?? null) ?? null
  977. } else if ends_with(data, "MB") {
  978. round(1000 * 1000 * to_float(replace(data, "MB", "")) ?? null) ?? null
  979. } else if ends_with(data, "kB") {
  980. round(1000 * to_float(replace(data, "kB", "")) ?? null) ?? null
  981. } else {
  982. round(to_int(replace(data, "B", "")) ?? null) ?? null
  983. }
  984. }
  985. }
  986.  
  987. for_each(gauges_bytes) -> |name, value| {
  988. . = push(., {
  989. "name": name,
  990. "kind": "absolute",
  991. "gauge": {
  992. "value": value
  993. },
  994. "tags": {
  995. "pid": to_string!(pid),
  996. "host": to_string!(host),
  997. "container_id": to_string!(container_id),
  998. "container_name": to_string!(container_name)
  999. },
  1000. "dt": dt
  1001. })
  1002. }
  1003. }
  1004. '''
  1005.  
  1006. [sources.better_stack_other_enfUhPmsJT6tbkBC5jpkxe9L]
  1007. type = "file"
  1008. read_from = "beginning"
  1009. ignore_older_secs = 600
  1010. include = [
  1011. "/var/log/*.log",
  1012. "/var/log/**/*.log"
  1013. ]
  1014. exclude = [
  1015. "/var/log/apache2/*.log",
  1016. "/var/log/nginx/*.log",
  1017. "/var/log/postgresql/*.log",
  1018. "/var/log/mysql/*.log",
  1019. "/var/log/mongodb/*.log",
  1020. "/var/log/redis/*.log",
  1021. "/var/log/auth.log",
  1022. "/var/log/ufw.log",
  1023. "/var/log/docker/*.log"
  1024. ]
  1025.  
  1026. [sinks.better_stack_http_sink_enfUhPmsJT6tbkBC5jpkxe9L]
  1027. type = "http"
  1028. method = "post"
  1029. uri = "https://in.logs.betterstack.com/"
  1030. encoding.codec = "json"
  1031. auth.strategy = "bearer"
  1032. auth.token = "enfUhPmsJT6tbkBC5jpkxe9L"
  1033. inputs = [
  1034. "better_stack_apache2_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1035. "better_stack_nginx_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1036. "better_stack_postgresql_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1037. "better_stack_mysql_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1038. "better_stack_mongodb_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1039. "better_stack_redis_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1040. "better_stack_auth_log_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1041. "better_stack_ufw_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1042. "better_stack_docker_parser_enfUhPmsJT6tbkBC5jpkxe9L",
  1043. "better_stack_other_enfUhPmsJT6tbkBC5jpkxe9L"
  1044. ]
  1045.  
  1046. [sinks.better_stack_http_metrics_sink_enfUhPmsJT6tbkBC5jpkxe9L]
  1047. type = "http"
  1048. method = "post"
  1049. uri = "https://in.logs.betterstack.com/metrics"
  1050. encoding.codec = "json"
  1051. auth.strategy = "bearer"
  1052. auth.token = "enfUhPmsJT6tbkBC5jpkxe9L"
  1053. inputs = ["better_stack_docker_metrics_parser_enfUhPmsJT6tbkBC5jpkxe9L"]
  1054.  
  1055. # --- end of 2023-08-18: https://logs.betterstack.com/vector-toml/ubuntu/enfUhPmsJT6tbkBC5jpkxe9L
  1056.  
Advertisement
Add Comment
Please, Sign In to add comment