{"id":475406,"date":"2025-09-17T09:16:06","date_gmt":"2025-09-17T09:16:06","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=475406"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=475406","title":{"rendered":"\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0434\u043b\u044f OpenTelemetry Collector. \u0410 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u0438 \u043d\u0435\u0442?"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u042f \u0410\u0440\u0442\u0451\u043c, \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440: \u043a\u043e\u0434 \u043f\u0438\u0448\u0443, \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0441\u043c\u043e\u0442\u0440\u044e \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0430\u0436\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u0412 \u0440\u0430\u0431\u043e\u0442\u0435 \u043c\u043d\u0435 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 Observability\u2011\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; OpenTelemetry Collector. \u042d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0439 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0435\u0439 \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0433\u0438\u0431\u043a\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0434\u043b\u044f \u043c\u0435\u0442\u0440\u0438\u043a, \u043b\u043e\u0433\u043e\u0432 \u0438 \u0442\u0440\u0435\u0439\u0441\u043e\u0432.<\/p>\n<p>\u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439 \u0438 \u0438\u0437\u043e\u043b\u0435\u043d\u0442\u044b. \u0422\u043e\u0433\u0434\u0430 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f Otel-Collector.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/s-\/q2\/3o\/s-q23o5pytjgsnj_-mxtk5hgkvw.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/s-\/q2\/3o\/s-q23o5pytjgsnj_-mxtk5hgkvw.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/s-\/q2\/3o\/s-q23o5pytjgsnj_-mxtk5hgkvw.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h4>\n<ul>\n<li>\n<p><a href=\"#section1\" rel=\"noopener noreferrer nofollow\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#section2\" rel=\"noopener noreferrer nofollow\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/a> <\/p>\n<ul>\n<li>\n<p><a href=\"#config\" rel=\"noopener noreferrer nofollow\">Config<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#factory\" rel=\"noopener noreferrer nofollow\">Factory<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#processor\" rel=\"noopener noreferrer nofollow\">Processor<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"#section3\" rel=\"noopener noreferrer nofollow\">\u041a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#section4\" rel=\"noopener noreferrer nofollow\">\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#section5\" rel=\"noopener noreferrer nofollow\">\u0418\u0442\u043e\u0433<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 <code>opentelemetry-collector-contrib<\/code> \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u0432: \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043b\u0438\u043c\u0438\u0442 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430: \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0441\u043f\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0431\u043e\u0440 \u043f\u0430\u043b \u043d\u0430 CSV\u2011\u0444\u0430\u0439\u043b).<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043f\u0430\u043d \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>SolObjectID<\/code>.<br \/> \u0410 \u0432 CSV \u043b\u0435\u0436\u0438\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0430, \u0433\u0434\u0435 \u044d\u0442\u043e\u043c\u0443 <code>SolObjectID<\/code> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u043b\u0435 <code>trace_code<\/code>, \u043e\u0447\u0435\u043d\u044c \u043d\u0443\u0436\u043d\u043e\u0435 \u043d\u0430\u043c, \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c. \u0425\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0432 \u0442\u0440\u0435\u0439\u0441\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u043b\u0441\u044f \u044d\u0442\u043e\u0442 <code>trace_code<\/code> \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0432 contrib \u0432\u0435\u0440\u0441\u0438\u0438 OpenTelemetry Collector \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e, \u043e\u0434\u043d\u0430\u043a\u043e, \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u0442\u044c. \u0412\u0437\u044f\u0442\u044c \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 &#8212; \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u0438\u0434\u0435\u0435\u0439.<\/p>\n<blockquote>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0441\u0432\u043e\u0439 \u043e\u043f\u044b\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0434\u043b\u044f otel-collector. \u041e\u043d \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 CSV\u2011\u0444\u0430\u0439\u043b\u0430: \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u043f\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u044c \u0442\u0440\u0435\u0439\u0441\u043e\u0432. \u041c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u0434 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Collector \u0441 \u044d\u0442\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/blockquote>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/h3>\n<p>\u041b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 Collector (receiver, processor, exporter, connector) \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443: \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c <strong>Config<\/strong>, <strong>Factory<\/strong> \u0438 \u0441\u0430\u043c\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <strong>Processor<\/strong>).<\/p>\n<h4>1. Config (config.go)<\/h4>\n<p>Config \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0434\u0430\u0442\u044c \u0432 YAML\u2011\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Collector.<br \/> \u0412 OpenTelemetry Collector \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433. Collector \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>component.Config<\/code>.<\/p>\n<p>Collector \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u044f \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0430. \u041d\u043e \u043e\u043d \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433 &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>component.Config<\/code>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 Collector \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043b\u044e\u0431\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e.<\/p>\n<p>\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442 Config \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"go\">type Config struct {CSVPath        string        `mapstructure:\"csv_path\"`MatchField     string        `mapstructure:\"match_field\"`EnrichColumns  []string      `mapstructure:\"enrich_columns\"`ReloadInterval time.Duration `mapstructure:\"reload_interval\"`}var _ component.Config = (*Config)(nil)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>CSVPath<\/code> &#8212; \u043f\u0443\u0442\u044c \u043a CSV\u2011\u0444\u0430\u0439\u043b\u0443.<\/p>\n<\/li>\n<li>\n<p><code>MatchField<\/code> &#8212; \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u043f\u0430\u043d\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0438\u0449\u0435\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><code>EnrichColumns<\/code> &#8212; \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0430\u043d.<\/p>\n<\/li>\n<li>\n<p><code>ReloadInterval<\/code> &#8212; \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 CSV \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 Collector.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 <code>collector-config.yaml<\/code>:<\/p>\n<pre><code class=\"yaml\">processors:  csvenricherprocessor:    csv_path: \"\/etc\/mapping.csv\"    match_field: \"SolObjectID\"    enrich_columns: [ \"trace_code\", \"product_id\" ]    reload_interval: \"5m\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>2. Factory (factory.go)<\/h4>\n<p><strong>Factory<\/strong> &#8212; \u044d\u0442\u043e \u00ab\u0444\u0430\u0431\u0440\u0438\u043a\u0430\u00bb \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. Collector \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0443: \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u044f\u0437\u0430\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0431\u0440\u0438\u043a\u0443, \u0447\u0442\u043e\u0431\u044b Collector \u043c\u043e\u0433 \u0435\u0433\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d.<\/p>\n<p>\u0424\u0430\u0431\u0440\u0438\u043a\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u0430:<\/p>\n<ol>\n<li>\n<p><strong>\u0422\u0438\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/strong> &#8212; \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 Collector \u0443\u0437\u043d\u0430\u0451\u0442 \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"go\">var (      strType = component.MustNewType(\"csvenricherprocessor\")  )<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"2\">\n<li>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/strong> &#8212; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u044b \u0432 YAML.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"go\">func createDefaultConfig() component.Config {return &amp;Config{MatchField:    \"SolObjectID\", \/\/ \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430EnrichColumns: []string{\"trace_code\", \"another_code\"}, \/\/ \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0434\u043b\u044f \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"3\">\n<li>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/strong> &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 <code>nextConsumer<\/code> (\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442), \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"go\">   func createTracesProcessor(   ctx context.Context,   set processor.Settings,   cfg component.Config,   nextConsumer consumer.Traces,) (processor.Traces, error) {processorCfg, ok := cfg.(*Config)if !ok {        return nil, fmt.Errorf(\"configuration parsing error\")    }    \/\/ \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440    proc, err := newProcessor(processorCfg, set.Logger)    if err != nil {        return nil, fmt.Errorf(\"cannot create csvenricher processor: %w\", err)    }    \/\/ \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0432 \u0445\u0435\u043b\u043f\u0435\u0440    return processorhelper.NewTraces(        ctx,        set,        cfg,        nextConsumer,        proc.processTraces,        processorhelper.WithCapabilities(consumer.Capabilities{MutatesData: true}),        processorhelper.WithStart(proc.start),        processorhelper.WithShutdown(proc.shutdown),    )}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"4\">\n<li>\n<p><strong>\u0412\u0441\u0451 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0431\u0440\u0438\u043a\u0435:<\/strong><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"go\">   func NewFactory() processor.Factory {   return processor.NewFactory(   strType,   createDefaultConfig,   processor.WithTraces(createTracesProcessor, stability),)   }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, Factory:<\/p>\n<ul>\n<li>\n<p>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector (\u043f\u043e\u0434 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c csvenricherprocessor);<\/p>\n<\/li>\n<li>\n<p>\u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f (\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 YAML \u043f\u0443\u0441\u0442\u043e\u0439);<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0440\u0435\u0439\u0441\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442 lifecycle-\u0445\u0443\u043a\u0438: start, shutdown, processTraces.<\/p>\n<\/li>\n<\/ul>\n<p>\u0411\u0435\u0437 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 Collector \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u00ab\u0443\u0437\u043d\u0430\u0442\u044c\u00bb \u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d.<\/p>\n<h4>3. Processor (processor.go)<\/h4>\n<p>Processor &#8212; \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f <strong>\u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>.<br \/> \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Factory (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442), Processor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0441\u0451: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043f\u0430\u043d\u043e\u0432 \u0438 graceful shutdown.<\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<h3>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/h3>\n<pre><code class=\"go\">type csvEnricherProcessor struct {      logger     *zap.Logger      config     *Config      csvData    []map[string]string  \/\/ \u043c\u0430\u043f\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b    matchIndex map[string]int \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e `MatchField`     mu         sync.RWMutex        ticker   *time.Ticker      stopChan chan struct{}  }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u0435\u0441\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><code>logger<\/code> &#8212; \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0432 Collector).<\/p>\n<\/li>\n<li>\n<p><code>config<\/code> &#8212; \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 Config, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0442\u044c, \u0433\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c CSV, \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0442.\u0434.<\/p>\n<\/li>\n<li>\n<p><code>csvData<\/code> \u0438 <code>matchIndex<\/code> &#8212; \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 CSV \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p><code>mu<\/code> &#8212; <code>sync.RWMutex<\/code> \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c (Collector \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e).<\/p>\n<\/li>\n<li>\n<p><code>ticker<\/code> \u0438 <code>stopChan<\/code> &#8212; \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CSV.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b<\/h3>\n<p>Processor \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f:<\/p>\n<p><code>start()<\/code> &#8212; \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u044d\u043a\u0433\u0440\u0430\u0443\u043d\u0434-\u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u043b\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CSV.<\/p>\n<pre><code class=\"go\">func (p *csvEnricherProcessor) start(ctx context.Context, host component.Host) error {p.logger.Info(\"Starting CSV Enricher Processor\")\/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b &lt;= 0, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u043cif p.config.ReloadInterval &lt;= 0 {...return nil}p.logger.Info(\"Starting background CSV reload loop\",zap.Duration(\"interval\", p.config.ReloadInterval))go func() {ticker := time.NewTicker(p.config.ReloadInterval)defer ticker.Stop()for {select {case &lt;-ticker.C:p.logger.Info(\"Reloading CSV data\")if err := p.loadCSVData(); err != nil {p.logger.Warn(\"Failed to reload CSV data\", zap.Error(err))}case &lt;-ctx.Done():p.logger.Info(\"CSV reload context done, stopping reload loop\")return}}}()return nil}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>shutdown()<\/code> &#8212; \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u0438\u043a\u0435\u0440\u044b \u0438 \u0447\u0438\u0441\u0442\u0438\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b.<\/p>\n<pre><code class=\"go\">func (p *csvEnricherProcessor) shutdown(ctx context.Context) error {      p.logger.Info(\"Shutting Down CSV Enricher Processor\")        if p.ticker != nil {         p.ticker.Stop()      }      close(p.stopChan)        return nil  }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>loadCSVData()<\/code> &#8212; \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 csv \u0432 \u043c\u0430\u043f\u0443<\/p>\n<pre><code class=\"go\">func (p *csvEnricherProcessor) loadCSVData() error {file, err := os.Open(p.config.CSVPath)...records, err := reader.ReadAll()...\/\/ headers + \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043f\u043e MatchField }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0422\u0443\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0442\u0430\u043a\u043e\u0439:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0435\u0440\u0451\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a (header).<\/p>\n<\/li>\n<li>\n<p>\u0421\u0442\u0440\u043e\u0438\u043c <code>map[matchValue]<\/code> \u2192 \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0440\u0435\u0439\u0441\u043e\u0432<\/h3>\n<p>Collector \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0443 \u0431\u0430\u0442\u0447 \u0442\u0440\u0435\u0439\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>processTraces<\/code>.<\/p>\n<pre><code class=\"go\">func (p *csvEnricherProcessor) processTraces(ctx context.Context, td ptrace.Traces) (ptrace.Traces, error) {      p.mu.RLock()      defer p.mu.RUnlock()        resourceSpans := td.ResourceSpans()      for i := 0; i &lt; resourceSpans.Len(); i++ {         resourceSpan := resourceSpans.At(i)           \/\/ enrichment \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 resource         resourceAttrs := resourceSpan.Resource().Attributes()         p.enrichResource(resourceAttrs)      }      return td, nil  }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0440\u0435\u0441\u0443\u0440\u0441\u0430 (<code>Resource.Attributes<\/code>), \u0430 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043f\u0430\u043d\u044b.<\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0440\u0435\u0441\u0443\u0440\u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443\/\u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443, \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0435\u0433\u043e.<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u043d\u044c\u0448\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Resource \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u0441\u043f\u0430\u043d\u0430\u043c \u0432\u043d\u0443\u0442\u0440\u0438.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041b\u043e\u0433\u0438\u043a\u0430 enrichment<\/strong><\/p>\n<pre><code class=\"go\">func (p *csvEnricherProcessor) enrichResource(resourceAttrs pcommon.Map) {matchValue, exists := resourceAttrs.Get(p.config.MatchField)if !exists || matchValue.Type() != pcommon.ValueTypeStr {      return  }...recordIdx, found := p.matchIndex[matchValue.Str()]...for _, column := range p.config.EnrichColumns {if value, ok := record[column]; ok {resourceAttrs.PutStr(column, value)}}}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u0445 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 <code>MatchField<\/code>, \u043c\u044b \u0438\u0449\u0435\u043c \u0435\u0433\u043e \u0432 CSV \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u043a\u0430\u043a \u043d\u043e\u0432\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b.<\/p>\n<p><strong>\u0418\u0442\u043e\u0433\u043e, Processor:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (CSV \u2192 \u043f\u0430\u043c\u044f\u0442\u044c \u2192 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u043e\u0438\u0441\u043a);<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0436\u0438\u0432\u0451\u0442 \u043f\u043e \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u043c\u0443 \u0446\u0438\u043a\u043b\u0443 (start\/shutdown);<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d (<code>sync.RWMutex<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u0443\u043c\u0435\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb \u0431\u0435\u0437 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 Collector.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u043c \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0435 Collector, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/github.com\/open-telemetry\/opentelemetry-collector\/tree\/main\/cmd\/builder\" rel=\"noopener noreferrer nofollow\">otelcol\u2011builder<\/a>. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0441\u0431\u043e\u0440\u043a\u0443 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 <a href=\"https:\/\/opentelemetry.io\/docs\/collector\/custom-collector\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a><\/p>\n<p>\u041c\u044b \u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0438\u043c Docker Image, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0438\u0448\u0443, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0437.<\/p>\n<h3>\u0428\u0430\u0433 1. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 builder-config.yaml<\/h3>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 <code>builder-config.yaml<\/code> \u0432 \u043a\u043e\u043d\u0435\u0446 \u0431\u043b\u043e\u043a\u0430 <code>processors<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u0432\u0435\u0440\u0441\u0438\u044f \u0440\u0435\u043b\u0438\u0437\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430.<\/p>\n<pre><code class=\"yaml\">processors:  - gomod: go.opentelemetry.io\/collector\/processor\/batchprocessor v0.128.0  - gomod: go.opentelemetry.io\/collector\/processor\/memorylimiterprocessor v0.128.0  ...  # \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440  - gomod: github.com\/hiphopzeliboba\/csvenricherprocessorr v0.3.0<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0438\u043b\u0438 \u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>replaces<\/code> \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442:<\/p>\n<pre><code class=\"yaml\">   replaces:     - github.com\/hiphopzeliboba\/csvenricherprocessor =&gt; \/path\/to\/local\/csvenricherprocessor<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435 <code>builder-config.yaml<\/code> \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 <code>name<\/code> \u0438 <code>output_path<\/code>.<br \/> <code>output_path<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043f\u0443\u0442\u0438 <code>ENTRYPOINT [\"\/otelcol-contrib\"]<\/code> \u0432 <code>Dockerfile<\/code><\/p>\n<pre><code class=\"yaml\">   dist:     module: github.com\/open-telemetry\/opentelemetry-collector-contrib\/cmd\/otelcontribcol     name: otelcol-contrib     decription: Local OpenTelemetry Collector Contrib binary, testing only.     version: 0.128.0-dev     output_path: .\/otelcol-contrib<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0428\u0430\u0433 2. \u0421\u0431\u043e\u0440\u043a\u0430 Docker Image<\/h3>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e Do\u0441kerfile \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/hiphopzeliboba\/otel-collector-contrib-custom-processor\/blob\/main\/Dockerfile\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a><\/p>\n<pre><code class=\"bash\">    docker build -t opentelemetry-collector-contrib-custom:1.128.4 .<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0428\u0430\u0433 3. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Collector (\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432)<\/h3>\n<p>\u0422\u0443\u0442 \u043c\u044b \u043f\u0440\u043e\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 <code>collector-config.yaml<\/code> \u0438 \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u043c <code>enrich.csv<\/code> \u0432\u043d\u0443\u0442\u0440\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430<\/p>\n<pre><code class=\"bash\">  docker run -it --rm \\  -v $(pwd)\/enrich.csv:\/data\/enrich.csv \\  -v $(pwd)\/collector-config.yaml:\/otelcol\/collector-config.yaml \\  -p 4317:4317 -p 4318:4318 -p 8888:8888 \\  --name otelcol-custom opentelemetry-collector-contrib-custom:0.128.4<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \ud83d\ude42<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e <a href=\"https:\/\/github.com\/hiphopzeliboba\/otel-collector-contrib-custom-processor\/tree\/main\/test_tracer\" rel=\"noopener noreferrer nofollow\">\u0443\u0442\u0438\u043b\u0438\u0442\u0443 <code>test_tracer<\/code> <\/a>  \u043d\u0430 Go. \u041e\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0441\u043f\u0430\u043d\u044b \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. (\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043f\u043e\u0440\u0442\u0430\u0445 Collector)<\/p>\n<pre><code class=\"bash\">cd test_tracer\/go mod tidygo run tracer.go<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0418\u0442\u043e\u0433<\/h3>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0434\u043b\u044f OpenTelemetry Collector, \u043a\u043e\u0442\u043e\u0440\u044b\u0439:<\/p>\n<ul>\n<li>\n<p>\u0447\u0438\u0442\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 CSV;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0445 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438 \u0441\u043f\u0430\u043d\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 Collector.<\/p>\n<\/li>\n<\/ul>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 Collector, \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u0441\u043b\u043e\u0436\u043d\u043e &#8212; \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u0442\u0440\u0438 \u043a\u0438\u0442\u0430: <em>Config, Factory \u0438 Processor<\/em>.<\/p>\n<blockquote>\n<p>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b &#8212; \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 OpenTelemetry Collector \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u043d\u0443\u0436\u0434\u044b.<br \/> \u0415\u0441\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u00ab\u043a\u0438\u0440\u043f\u0438\u0447\u0438\u043a\u0438\u00bb \u0434\u043b\u044f Observability.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0438 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u043a\u0443\u0447\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432 \u043f\u043e \u043a\u043e\u0434\u0443 contrib\u2011\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f :-).<\/p>\n<\/blockquote>\n<h3>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c<\/h3>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 GitHub:<br \/> <a href=\"https:\/\/github.com\/hiphopzeliboba\/otel-collector-contrib-custom-processor\" rel=\"noopener noreferrer nofollow\">hiphopzeliboba\/otel-collector-contrib-custom-processor<\/a><\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/947724\/\">https:\/\/habr.com\/ru\/articles\/947724\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u042f \u0410\u0440\u0442\u0451\u043c, \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440: \u043a\u043e\u0434 \u043f\u0438\u0448\u0443, \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0441\u043c\u043e\u0442\u0440\u044e \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0430\u0436\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u0412 \u0440\u0430\u0431\u043e\u0442\u0435 \u043c\u043d\u0435 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 Observability\u2011\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; OpenTelemetry Collector. \u042d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0439 \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0435\u0439 \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0433\u0438\u0431\u043a\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0434\u043b\u044f \u043c\u0435\u0442\u0440\u0438\u043a, \u043b\u043e\u0433\u043e\u0432 \u0438 \u0442\u0440\u0435\u0439\u0441\u043e\u0432.\u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439 \u0438 \u0438\u0437\u043e\u043b\u0435\u043d\u0442\u044b. \u0422\u043e\u0433\u0434\u0430 \u043d\u0430 \u0441\u0446\u0435\u043d\u0443 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f Otel-Collector.\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 ConfigFactoryProcessor\u041a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u0418\u0442\u043e\u0433\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u0412 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u043d\u0430\u0431\u043e\u0440\u0435 opentelemetry-collector-contrib \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u0432: \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043b\u0438\u043c\u0438\u0442 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u043e \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430: \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0441\u043f\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0431\u043e\u0440 \u043f\u0430\u043b \u043d\u0430 CSV\u2011\u0444\u0430\u0439\u043b).\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043f\u0430\u043d \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c SolObjectID. \u0410 \u0432 CSV \u043b\u0435\u0436\u0438\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0430, \u0433\u0434\u0435 \u044d\u0442\u043e\u043c\u0443 SolObjectID \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u043b\u0435 trace_code, \u043e\u0447\u0435\u043d\u044c \u043d\u0443\u0436\u043d\u043e\u0435 \u043d\u0430\u043c, \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c. \u0425\u043e\u0447\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0432 \u0442\u0440\u0435\u0439\u0441\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u043b\u0441\u044f \u044d\u0442\u043e\u0442 trace_code \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0432 contrib \u0432\u0435\u0440\u0441\u0438\u0438 OpenTelemetry Collector \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e, \u043e\u0434\u043d\u0430\u043a\u043e, \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438\u043c\u0435\u0442\u044c. \u0412\u0437\u044f\u0442\u044c \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 &#8212; \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u0438\u0434\u0435\u0435\u0439.\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0441\u0432\u043e\u0439 \u043e\u043f\u044b\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0434\u043b\u044f otel-collector. \u041e\u043d \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 CSV\u2011\u0444\u0430\u0439\u043b\u0430: \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u043f\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u044c \u0442\u0440\u0435\u0439\u0441\u043e\u0432. \u041c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u0434 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Collector \u0441 \u044d\u0442\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430\u041b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 Collector (receiver, processor, exporter, connector) \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443: \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c Config, Factory \u0438 \u0441\u0430\u043c\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 Processor).1. Config (config.go)Config \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0434\u0430\u0442\u044c \u0432 YAML\u2011\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Collector. \u0412 OpenTelemetry Collector \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433. Collector \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 component.Config.Collector \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u044f \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0430. \u041d\u043e \u043e\u043d \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433 &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 component.Config. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 Collector \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043b\u044e\u0431\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e.\u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442 Config \u043a\u043e\u0434\u0430:type Config struct {CSVPath        string        `mapstructure:&#187;csv_path&#187;`MatchField     string        `mapstructure:&#187;match_field&#187;`EnrichColumns  []string      `mapstructure:&#187;enrich_columns&#187;`ReloadInterval time.Duration `mapstructure:&#187;reload_interval&#187;`}var _ component.Config = (*Config)(nil)\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e:CSVPath &#8212; \u043f\u0443\u0442\u044c \u043a CSV\u2011\u0444\u0430\u0439\u043b\u0443.MatchField &#8212; \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u043f\u0430\u043d\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0438\u0449\u0435\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f.EnrichColumns &#8212; \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0430\u043d.ReloadInterval &#8212; \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 CSV \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 Collector.\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 collector-config.yaml:processors:  csvenricherprocessor:    csv_path: &#171;\/etc\/mapping.csv&#187;    match_field: &#171;SolObjectID&#187;    enrich_columns: [ &#171;trace_code&#187;, &#171;product_id&#187; ]    reload_interval: &#171;5m&#187;2. Factory (factory.go)Factory &#8212; \u044d\u0442\u043e \u00ab\u0444\u0430\u0431\u0440\u0438\u043a\u0430\u00bb \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430. Collector \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0443: \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u044f\u0437\u0430\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0431\u0440\u0438\u043a\u0443, \u0447\u0442\u043e\u0431\u044b Collector \u043c\u043e\u0433 \u0435\u0433\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d.\u0424\u0430\u0431\u0440\u0438\u043a\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u0430:\u0422\u0438\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 &#8212; \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 Collector \u0443\u0437\u043d\u0430\u0451\u0442 \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440.var (      strType = component.MustNewType(&#171;csvenricherprocessor&#187;)  )\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e &#8212; \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u044b \u0432 YAML.func createDefaultConfig() component.Config {return &amp;Config{MatchField:    &#171;SolObjectID&#187;, \/\/ \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430EnrichColumns: []string{&#171;trace_code&#187;, &#171;another_code&#187;}, \/\/ \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0434\u043b\u044f \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f    }}\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 nextConsumer (\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442), \u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430.   func createTracesProcessor(   ctx context.Context,   set processor.Settings,   cfg component.Config,   nextConsumer consumer.Traces,) (processor.Traces, error) {processorCfg, ok := cfg.(*Config)if !ok {        return nil, fmt.Errorf(&#171;configuration parsing error&#187;)    }    \/\/ \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440    proc, err := newProcessor(processorCfg, set.Logger)    if err != nil {        return nil, fmt.Errorf(&#171;cannot create csvenricher processor: %w&#187;, err)    }    \/\/ \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0432 \u0445\u0435\u043b\u043f\u0435\u0440    return processorhelper.NewTraces(        ctx,        set,        cfg,        nextConsumer,        proc.processTraces,        processorhelper.WithCapabilities(consumer.Capabilities{MutatesData: true}),        processorhelper.WithStart(proc.start),        processorhelper.WithShutdown(proc.shutdown),    )}\u0412\u0441\u0451 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0431\u0440\u0438\u043a\u0435:   func NewFactory() processor.Factory {   return processor.NewFactory(   strType,   createDefaultConfig,   processor.WithTraces(createTracesProcessor, stability),)   }\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, Factory:\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u0448 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector (\u043f\u043e\u0434 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c csvenricherprocessor);\u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f (\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 YAML \u043f\u0443\u0441\u0442\u043e\u0439);\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0440\u0435\u0439\u0441\u043e\u0432;\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442 lifecycle-\u0445\u0443\u043a\u0438: start, shutdown, processTraces.\u0411\u0435\u0437 \u0444\u0430\u0431\u0440\u0438\u043a\u0438 Collector \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u00ab\u0443\u0437\u043d\u0430\u0442\u044c\u00bb \u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d.3. Processor (processor.go)Processor &#8212; \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Factory (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442), Processor \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0441\u0451: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043f\u0430\u043d\u043e\u0432 \u0438 graceful shutdown.\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430type csvEnricherProcessor struct {      logger     *zap.Logger      config     *Config      csvData    []map[string]string  \/\/ \u043c\u0430\u043f\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b    matchIndex map[string]int \/\/ \u0438\u043d\u0434\u0435\u043a\u0441 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e `MatchField`     mu         sync.RWMutex        ticker   *time.Ticker      stopChan chan struct{}  }\u0427\u0442\u043e \u0442\u0443\u0442 \u0435\u0441\u0442\u044c:logger &#8212; \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0432 Collector).config &#8212; \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 Config, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0442\u044c, \u0433\u0434\u0435 \u0438\u0441\u043a\u0430\u0442\u044c CSV, \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0442.\u0434.csvData \u0438 matchIndex &#8212; \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 CSV \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430.mu &#8212; sync.RWMutex \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c (Collector \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e).ticker \u0438 stopChan &#8212; \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CSV.\u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043bProcessor \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f:start() &#8212; \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u044d\u043a\u0433\u0440\u0430\u0443\u043d\u0434-\u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u043b\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 CSV.func (p *csvEnricherProcessor) start(ctx context.Context, host component.Host) error {p.logger.Info(&#171;Starting CSV Enricher Processor&#187;)\/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b &lt;= 0, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u043cif p.config.ReloadInterval &lt;= 0 {&#8230;return nil}p.logger.Info(&#171;Starting background CSV reload loop&#187;,zap.Duration(&#171;interval&#187;, p.config.ReloadInterval))go func() {ticker := time.NewTicker(p.config.ReloadInterval)defer ticker.Stop()for {select {case &lt;-ticker.C:p.logger.Info(&#171;Reloading CSV data&#187;)if err := p.loadCSVData(); err != nil {p.logger.Warn(&#171;Failed to reload CSV data&#187;, zap.Error(err))}case &lt;-ctx.Done():p.logger.Info(&#171;CSV reload context done, stopping reload loop&#187;)return}}}()return nil}shutdown() &#8212; \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u0438\u043a\u0435\u0440\u044b \u0438 \u0447\u0438\u0441\u0442\u0438\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b.func (p *csvEnricherProcessor) shutdown(ctx context.Context) error {      p.logger.Info(&#171;Shutting Down CSV Enricher Processor&#187;)        if p.ticker != nil {         p.ticker.Stop()      }      close(p.stopChan)        return nil  }loadCSVData() &#8212; \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 csv \u0432 \u043c\u0430\u043f\u0443func (p *csvEnricherProcessor) loadCSVData() error {file, err := os.Open(p.config.CSVPath)&#8230;records, err := reader.ReadAll()&#8230;\/\/ headers + \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043f\u043e MatchField }\u0422\u0443\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0442\u0430\u043a\u043e\u0439:\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b.\u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.\u0411\u0435\u0440\u0451\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a (header).\u0421\u0442\u0440\u043e\u0438\u043c map[matchValue] \u2192 \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430.\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0440\u0435\u0439\u0441\u043e\u0432Collector \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0443 \u0431\u0430\u0442\u0447 \u0442\u0440\u0435\u0439\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e processTraces.func (p *csvEnricherProcessor) processTraces(ctx context.Context, td ptrace.Traces) (ptrace.Traces, error) {      p.mu.RLock()      defer p.mu.RUnlock()        resourceSpans := td.ResourceSpans()      for i := 0; i &lt; resourceSpans.Len(); i++ {         resourceSpan := resourceSpans.At(i)           \/\/ enrichment \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 resource         resourceAttrs := resourceSpan.Resource().Attributes()         p.enrichResource(resourceAttrs)      }      return td, nil  }\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0440\u0435\u0441\u0443\u0440\u0441\u0430 (Resource.Attributes), \u0430 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043f\u0430\u043d\u044b.\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a:\u0440\u0435\u0441\u0443\u0440\u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443\/\u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443, \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0442\u044c \u0435\u0433\u043e.\u043c\u0435\u043d\u044c\u0448\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Resource \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u0441\u043f\u0430\u043d\u0430\u043c \u0432\u043d\u0443\u0442\u0440\u0438.\u041b\u043e\u0433\u0438\u043a\u0430 enrichmentfunc (p *csvEnricherProcessor) enrichResource(resourceAttrs pcommon.Map) {matchValue, exists := resourceAttrs.Get(p.config.MatchField)if !exists || matchValue.Type() != pcommon.ValueTypeStr {      return  }&#8230;recordIdx, found := p.matchIndex[matchValue.Str()]&#8230;for _, column := range p.config.EnrichColumns {if value, ok := record[column]; ok {resourceAttrs.PutStr(column, value)}}}\u0415\u0441\u043b\u0438 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u0445 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 MatchField, \u043c\u044b \u0438\u0449\u0435\u043c \u0435\u0433\u043e \u0432 CSV \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u043a\u0430\u043a \u043d\u043e\u0432\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b.\u0418\u0442\u043e\u0433\u043e, Processor:\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (CSV \u2192 \u043f\u0430\u043c\u044f\u0442\u044c \u2192 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u043e\u0438\u0441\u043a);\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c;\u0436\u0438\u0432\u0451\u0442 \u043f\u043e \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u043c\u0443 \u0446\u0438\u043a\u043b\u0443 (start\/shutdown);\u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d (sync.RWMutex);\u0443\u043c\u0435\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb \u0431\u0435\u0437 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 Collector.\u041a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432 Collector\u0427\u0442\u043e\u0431\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u043c \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0435 Collector, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e otelcol\u2011builder. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u0441\u0431\u043e\u0440\u043a\u0443 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438\u041c\u044b \u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0438\u043c Docker Image, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043f\u0438\u0448\u0443, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0437.\u0428\u0430\u0433 1. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 builder-config.yaml\u0412 \u0444\u0430\u0439\u043b\u0435 builder-config.yaml \u0432 \u043a\u043e\u043d\u0435\u0446 \u0431\u043b\u043e\u043a\u0430 processors \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-475406","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/475406","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=475406"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/475406\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=475406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=475406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=475406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}