You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by sz...@apache.org on 2020/08/26 09:26:50 UTC

[nifi-minifi-cpp] branch main updated: MINIFICPP-1327 Add timezone information as attribute to flowfiles crated by CWEL

This is an automated email from the ASF dual-hosted git repository.

szaszm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 75e93e2  MINIFICPP-1327 Add timezone information as attribute to flowfiles crated by CWEL
75e93e2 is described below

commit 75e93e29705d249e3b4d77699ac03375d0b5b335
Author: Arpad Boda <ab...@apache.org>
AuthorDate: Wed Aug 26 11:25:12 2020 +0200

    MINIFICPP-1327 Add timezone information as attribute to flowfiles crated by CWEL
    
    Co-authored-by: Ferenc Gerlits <fg...@users.noreply.github.com>
    Signed-off-by: Marton Szasz <sz...@gmail.com>
    
    This closes #867
---
 .../windows-event-log/ConsumeWindowsEventLog.cpp   | 37 ++++++++++++++++++++++
 .../windows-event-log/ConsumeWindowsEventLog.h     |  4 +++
 .../tests/ConsumeWindowsEventLogTests.cpp          |  4 +++
 3 files changed, 45 insertions(+)

diff --git a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp
index 70f4d08..3d88a20 100644
--- a/extensions/windows-event-log/ConsumeWindowsEventLog.cpp
+++ b/extensions/windows-event-log/ConsumeWindowsEventLog.cpp
@@ -372,6 +372,8 @@ void ConsumeWindowsEventLog::onTrigger(const std::shared_ptr<core::ProcessContex
     return;
   }
 
+  refreshTimeZoneData();
+
   logger_->log_trace("Enumerating the events in the result set after the bookmarked event.");
   while (true) {
     EVT_HANDLE hEvent{};
@@ -610,6 +612,37 @@ bool ConsumeWindowsEventLog::createEventRender(EVT_HANDLE hEvent, EventRender& e
   return true;
 }
 
+void ConsumeWindowsEventLog::refreshTimeZoneData() {
+  DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
+  auto ret = GetDynamicTimeZoneInformation(&tzinfo);
+  std::wstring tzstr;
+  long tzbias = 0;
+  bool dst = false;
+  switch (ret) {
+    case TIME_ZONE_ID_UNKNOWN:
+      logger_->log_error("Failed to get timezone information!");
+      return;  // Don't update members in case we cannot get data
+    case TIME_ZONE_ID_DAYLIGHT:
+      tzstr = tzinfo.DaylightName;
+      dst = true;
+      // [[fallthrough]];
+    case TIME_ZONE_ID_STANDARD:
+      tzstr = tzstr.empty() ? tzinfo.StandardName : tzstr;  // Use standard timezome name in case there is no daylight name or in case it's not DST
+      tzbias = tzinfo.Bias + (dst ? tzinfo.DaylightBias : tzinfo.StandardBias);
+      break;
+  }
+
+  tzbias *= -1;  // WinApi specifies UTC = localtime + bias, but we need offset from UTC
+  std::stringstream tzoffset;
+  tzoffset << (tzbias >= 0 ? '+' : '-') << std::setfill('0') << std::setw(2) << std::abs(tzbias) / 60
+      << ":" << std::setfill('0') << std::setw(2) << std::abs(tzbias) % 60;
+
+  timezone_name_ = wel::to_string(tzstr.c_str());
+  timezone_offset_ = tzoffset.str();
+
+  logger_->log_trace("Timezone name: %s, offset: %s", timezone_name_, timezone_offset_);
+}
+
 void ConsumeWindowsEventLog::putEventRenderFlowFileToSession(const EventRender& eventRender, core::ProcessSession& session)
 {
   struct WriteCallback : public OutputStreamCallback {
@@ -635,6 +668,8 @@ void ConsumeWindowsEventLog::putEventRenderFlowFileToSession(const EventRender&
       }
     }
     session.putAttribute(flowFile, FlowAttributeKey(MIME_TYPE), "application/xml");
+    session.putAttribute(flowFile, "Timezone name", timezone_name_);
+    session.putAttribute(flowFile, "Timezone offset", timezone_offset_);
     session.getProvenanceReporter()->receive(flowFile, provenanceUri_, getUUIDStr(), "Consume windows event logs", 0);
     session.transfer(flowFile, Success);
   }
@@ -645,6 +680,8 @@ void ConsumeWindowsEventLog::putEventRenderFlowFileToSession(const EventRender&
 
     session.write(flowFile, &WriteCallback(eventRender.rendered_text_));
     session.putAttribute(flowFile, FlowAttributeKey(MIME_TYPE), "text/plain");
+    session.putAttribute(flowFile, "Timezone name", timezone_name_);
+    session.putAttribute(flowFile, "Timezone offset", timezone_offset_);
     session.getProvenanceReporter()->receive(flowFile, provenanceUri_, getUUIDStr(), "Consume windows event logs", 0);
     session.transfer(flowFile, Success);
   }
diff --git a/extensions/windows-event-log/ConsumeWindowsEventLog.h b/extensions/windows-event-log/ConsumeWindowsEventLog.h
index dd6948b..0972f49 100644
--- a/extensions/windows-event-log/ConsumeWindowsEventLog.h
+++ b/extensions/windows-event-log/ConsumeWindowsEventLog.h
@@ -101,6 +101,7 @@ public:
   
 
 protected:
+  void refreshTimeZoneData();
   void putEventRenderFlowFileToSession(const EventRender& eventRender, core::ProcessSession& session);
   wel::WindowsEventLogHandler getEventLogHandler(const std::string & name);
   bool insertHeaderName(wel::METADATA_NAMES &header, const std::string &key, const std::string &value);
@@ -138,6 +139,9 @@ private:
   std::mutex onTriggerMutex_;
   std::unordered_map<std::string, std::string> xmlPercentageItemsResolutions_;
   HMODULE hMsobjsDll_{};
+
+  std::string timezone_name_;
+  std::string timezone_offset_;  // Represented as UTC offset in (+|-)HH:MM format, like +02:00
 };
 
 REGISTER_RESOURCE(ConsumeWindowsEventLog, "Windows Event Log Subscribe Callback to receive FlowFiles from Events on Windows.");
diff --git a/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp b/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp
index 8ea45fb..aa62e37 100644
--- a/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp
+++ b/extensions/windows-event-log/tests/ConsumeWindowsEventLogTests.cpp
@@ -143,6 +143,10 @@ TEST_CASE("ConsumeWindowsEventLog can consume new events", "[onTrigger]") {
     test_controller.runSession(test_plan);
     REQUIRE(LogTestController::getInstance().contains("processed 1 Events"));
     REQUIRE(LogTestController::getInstance().contains("<EventData><Data>Event one</Data></EventData>"));
+
+    // make sure timezone attributes are present
+    REQUIRE(LogTestController::getInstance().contains("key:Timezone offset value:"));
+    REQUIRE(LogTestController::getInstance().contains("key:Timezone name value:"));
   }
 
   SECTION("Read two events") {