diff --git a/.changeset/sharp-kings-help.md b/.changeset/sharp-kings-help.md new file mode 100644 index 00000000..897ee731 --- /dev/null +++ b/.changeset/sharp-kings-help.md @@ -0,0 +1,6 @@ +--- +'@hyperdx/api': patch +'@hyperdx/app': patch +--- + +feat: parse legacy k8s v1 cluster events diff --git a/docker/ingestor/core.toml b/docker/ingestor/core.toml index bd51d5df..6a0d02ba 100644 --- a/docker/ingestor/core.toml +++ b/docker/ingestor/core.toml @@ -464,31 +464,41 @@ if .hdx_platform == "vector-internal" { } # extract k8s event metadata - if .b.object.apiVersion == "events.k8s.io/v1" && .b.object.kind == "Event" { + # TODO: should we check "k8s.event.name" instead? + if .b."k8s.resource.name" == "events" && .b.object.kind == "Event" { # set severity if is_nullish(.b.level) && (.b.object.type == "Warning" || .b.object.type == "Normal") { .b.level = .b.object.type } + + # check event format (cluster legacy v1 vs v1 events) + _targetObject = {} + if .b.object.apiVersion == "events.k8s.io/v1" && is_object(.b.object.regarding) { + _targetObject = .b.object.regarding + .b._hdx_body = .b.object.note + } else if .b.object.apiVersion == "v1" && is_object(.b.object.involvedObject) { + _targetObject = .b.object.involvedObject + .b._hdx_body = .b.object.message + } + # transform the attributes so that the log events use the k8s.* semantic conventions # ref: https://docs.honeycomb.io/integrations/kubernetes/kubernetes-events/ - if .b.object.regarding.kind == "Pod" { - .b."k8s.pod.name" = .b.object.regarding.name - .b."k8s.pod.uid" = .b.object.regarding.uid - .b."k8s.namespace.name" = .b.object.regarding.namespace - } else if .b.object.regarding.kind == "Node" { - .b."k8s.node.name" = .b.object.regarding.name - .b."k8s.node.uid" = .b.object.regarding.uid - } else if .b.object.regarding.kind == "Job" { - .b."k8s.job.name" = .b.object.regarding.name - .b."k8s.job.uid" = .b.object.regarding.uid - .b."k8s.namespace.name" = .b.object.regarding.namespace - } else if .b.object.regarding.kind == "CronJob" { - .b."k8s.cronjob.name" = .b.object.regarding.name - .b."k8s.cronjob.uid" = .b.object.regarding.uid - .b."k8s.namespace.name" = .b.object.regarding.namespace + if _targetObject.kind == "Pod" { + .b."k8s.pod.name" = _targetObject.name + .b."k8s.pod.uid" = _targetObject.uid + .b."k8s.namespace.name" = _targetObject.namespace + } else if _targetObject.kind == "Node" { + .b."k8s.node.name" = _targetObject.name + .b."k8s.node.uid" = _targetObject.uid + } else if _targetObject.kind == "Job" { + .b."k8s.job.name" = _targetObject.name + .b."k8s.job.uid" = _targetObject.uid + .b."k8s.namespace.name" = _targetObject.namespace + } else if _targetObject.kind == "CronJob" { + .b."k8s.cronjob.name" = _targetObject.name + .b."k8s.cronjob.uid" = _targetObject.uid + .b."k8s.namespace.name" = _targetObject.namespace } - # set main message - .b._hdx_body = .b.object.note } # set severity after merging structured message (to avoid conflict) diff --git a/packages/api/src/clickhouse/searchQueryParser.ts b/packages/api/src/clickhouse/searchQueryParser.ts index 7148484f..0d86670b 100644 --- a/packages/api/src/clickhouse/searchQueryParser.ts +++ b/packages/api/src/clickhouse/searchQueryParser.ts @@ -54,6 +54,11 @@ const customColumnMap: { [level: string]: string } = { userEmail: '_user_email', userId: '_user_id', userName: '_user_name', + // TODO: eventually we might want to materialize these fields + 'object.regarding.kind': + "coalesce(_string_attributes['object.regarding.kind'], _string_attributes['object.involvedObject.kind'])", + 'object.regarding.name': + "coalesce(_string_attributes['object.regarding.name'], _string_attributes['object.involvedObject.name'])", }; export const customColumnMapType: { [property: string]: 'string' | 'number' | 'bool';