bool k8s_event_handler::handle_component(const Json::Value& json, const msg_data* data) { if(m_event_filter) { if(m_state) { if(data) { if((data->m_reason == k8s_component::COMPONENT_ADDED) || (data->m_reason == k8s_component::COMPONENT_MODIFIED)) { g_logger.log("K8s EVENT: handling event.", sinsp_logger::SEV_TRACE); const Json::Value& involved_object = json["involvedObject"]; if(!involved_object.isNull()) { bool is_aggregate = (get_json_string(json , "message").find("events with common reason combined") != std::string::npos); time_t last_ts = get_epoch_utc_seconds(get_json_string(json , "lastTimestamp")); time_t now_ts = get_epoch_utc_seconds_now(); g_logger.log("K8s EVENT: lastTimestamp=" + std::to_string(last_ts) + ", now_ts=" + std::to_string(now_ts), sinsp_logger::SEV_TRACE); if(((last_ts > 0) && (now_ts > 0)) && // we got good timestamps !is_aggregate && // not an aggregated cached event ((now_ts - last_ts) < 10)) // event not older than 10 seconds { const Json::Value& kind = involved_object["kind"]; const Json::Value& event_reason = json["reason"]; g_logger.log("K8s EVENT: involved object and event reason found:" + kind.asString() + '/' + event_reason.asString(), sinsp_logger::SEV_TRACE); if(!kind.isNull() && kind.isConvertibleTo(Json::stringValue) && !event_reason.isNull() && event_reason.isConvertibleTo(Json::stringValue)) { bool is_allowed = m_event_filter->allows_all(); std::string type = kind.asString(); if(!is_allowed && !type.empty()) { std::string reason = event_reason.asString(); is_allowed = m_event_filter->allows_all(type); if(!is_allowed && !reason.empty()) { is_allowed = m_event_filter->has(type, reason); } } if(is_allowed) { k8s_events& evts = m_state->get_events(); if(evts.size() < sinsp_user_event::max_events_per_cycle()) { k8s_event_t& evt = m_state->add_component<k8s_events, k8s_event_t>(evts, data->m_name, data->m_uid, data->m_namespace); m_state->update_event(evt, json); m_event_limit_exceeded = false; if(g_logger.get_severity() >= sinsp_logger::SEV_DEBUG) { g_logger.log("K8s EVENT: added event [" + data->m_name + "]. " "Queued events count=" + std::to_string(evts.size()), sinsp_logger::SEV_DEBUG); } } else if(!m_event_limit_exceeded) // only get in here once per cycle, to send event overflow warning { sinsp_user_event::emit_event_overflow("Kubernetes", get_machine_id()); m_event_limit_exceeded = true; return false; } else // event limit exceeded and overflow logged, nothing to do { return false; } } else // event not allowed by filter, ignore { if(g_logger.get_severity() >= sinsp_logger::SEV_TRACE) { g_logger.log("K8s EVENT: filter does not allow {\"" + type + "\", \"{" + event_reason.asString() + "\"} }", sinsp_logger::SEV_TRACE); g_logger.log(m_event_filter->to_string(), sinsp_logger::SEV_TRACE); } m_event_ignored = true; return false; } } else { g_logger.log("K8s EVENT: event type or involvedObject kind not found.", sinsp_logger::SEV_ERROR); if(g_logger.get_severity() >= sinsp_logger::SEV_TRACE) { g_logger.log(Json::FastWriter().write(json), sinsp_logger::SEV_TRACE); } return false; } } else // old event, ignore { g_logger.log("K8s EVENT: old event, ignoring: " ", lastTimestamp=" + std::to_string(last_ts) + ", now_ts=" + std::to_string(now_ts), sinsp_logger::SEV_DEBUG); m_event_ignored = true; return false; } } else { g_logger.log("K8s EVENT: involvedObject not found.", sinsp_logger::SEV_ERROR); g_logger.log(Json::FastWriter().write(json), sinsp_logger::SEV_TRACE); return false; } } else // not ADDED or MODIFIED event, ignore { m_event_ignored = true; return false; } } else { g_logger.log("K8s EVENT: msg data is null.", sinsp_logger::SEV_ERROR); g_logger.log(Json::FastWriter().write(json), sinsp_logger::SEV_TRACE); return false; } } else { g_logger.log("K8s EVENT: state is null.", sinsp_logger::SEV_ERROR); return false; } } else { g_logger.log("K8s EVENT: no filter, K8s events disabled.", sinsp_logger::SEV_TRACE); return false; } return true; }
void k8s_event_t::update(const Json::Value& item, k8s_state_t& state) { #ifndef _WIN32 time_t epoch_time_s = 0; string event_name; string description; severity_t severity = sinsp_logger::SEV_EVT_INFORMATION; string scope; tag_map_t tags; const Json::Value& obj = item["involvedObject"]; //g_logger.log(Json::FastWriter().write(item), sinsp_logger::SEV_TRACE); if(!obj.isNull()) { std::string sev = get_json_string(item, "type"); // currently, only "Normal" and "Warning" severity = sinsp_logger::SEV_EVT_INFORMATION; if(sev == "Warning") { severity = sinsp_logger::SEV_EVT_WARNING; } g_logger.log("K8s EVENT : \ncomponent name = " + get_json_string(obj, "name") + "\nuid = " + get_json_string(obj, "uid") + "\ntype = " + get_json_string(obj, "kind") + "\nseverity = " + get_json_string(item, "type") + " (" + std::to_string(severity) + ')', sinsp_logger::SEV_TRACE); } else { g_logger.log("K8s event: cannot get involved object (null)", sinsp_logger::SEV_ERROR); } std::string ts = get_json_string(item , "lastTimestamp"); if(!ts.empty()) { if((epoch_time_s = get_epoch_utc_seconds(ts)) == (time_t) -1) { g_logger.log("K8s event: cannot convert [" + ts + "] to epoch timestamp", sinsp_logger::SEV_ERROR); } g_logger.log("K8s EVENT update: time:" + std::to_string(epoch_time_s), sinsp_logger::SEV_DEBUG); } else { g_logger.log("K8s event: cannot convert time (null, empty or not string)", sinsp_logger::SEV_ERROR); } event_name = get_json_string(item , "reason"); const auto& translation = m_name_translation.find(event_name); if(translation != m_name_translation.end()) { event_name = translation->second; } description = get_json_string(item, "message"); g_logger.log("K8s EVENT message:" + description, sinsp_logger::SEV_DEBUG); string component_uid = get_json_string(obj, "uid"); if(!component_uid.empty()) { std::string t; const k8s_component* comp = state.get_component(component_uid, &t); if(comp && !t.empty()) { std::string node_name = comp->get_node_name(); if(!node_name.empty()) { if(scope.length()) { scope.append(" and "); } scope.append("kubernetes.node.name=").append(node_name); } if(scope.length()) { scope.append(" and "); } scope.append("kubernetes.").append(t).append(".name=").append(comp->get_name()); const std::string& ns = get_namespace(); if(!ns.empty()) { scope.append(" and kubernetes.namespace.name=").append(ns); } /* no labels for now for(const auto& label : comp->get_labels()) { tags[label.first] = label.second; g_logger.log("EVENT label: [" + label.first + ':' + label.second + ']', sinsp_logger::SEV_DEBUG); scope.append(" and kubernetes.").append(t).append(".label.").append(label.first).append(1, '=').append(label.second); }*/ } else { g_logger.log("K8s event: cannot obtain component (UID not found: [" + component_uid + "])", sinsp_logger::SEV_ERROR); } } else { g_logger.log("K8s event: cannot obtain tags (UID not retrieved)", sinsp_logger::SEV_ERROR); } tags["source"] = "kubernetes"; g_logger.log(sinsp_user_event::to_string(epoch_time_s, std::move(event_name), std::move(description), std::move(scope), std::move(tags)), severity); // TODO: sysdig capture? #endif // _WIN32 }