Объединение JSON Instana EUM с JQ в CMD

Я использую Instana для предоставления статистики просмотров на своем сайте. Каждый ежедневный файл выглядит следующим образом:

{
  "items" : [ {
    "name" : "page1.htm",
    "earliestTimestamp" : 1675222177839,
    "cursor" : {
      "@class" : ".IngestionOffsetCursor",
      "ingestionTime" : 1675292168217,
      "offset" : 1
    },
    "metrics" : {
      "uniqueSessions.distinct_count" : [ [ 1675292400000, 4.0 ] ]
    }
  }, {
    "name" : "page2.htm",
    "earliestTimestamp" : 1675260035165,
    "cursor" : {
      "@class" : ".IngestionOffsetCursor",
      "ingestionTime" : 1675292168217,
      "offset" : 2
    },
    "metrics" : {
      "uniqueSessions.distinct_count" : [ [ 1675292400000, 1.0 ] ]
    }
  }, {
    "name" : "page3.htm",
    "earliestTimestamp" : 1675228447118,
    "cursor" : {
      "@class" : ".IngestionOffsetCursor",
      "ingestionTime" : 1675292168217,
      "offset" : 3
    },
    "metrics" : {
      "uniqueSessions.distinct_count" : [ [ 1675292400000, 7.0 ] ]
    }
  } ],
  "canLoadMore" : false,
  "totalHits" : 12,
  "totalRepresentedItemCount" : 12,
  "totalRetainedItemCount" : 12,
  "adjustedTimeframe" : {
    "windowSize" : 86400000,
    "to" : 1675292400000
  }
}

Эти ежедневные файлы следует объединить в один json после фильтрации необходимой информации:

  • URL (от имени)

  • дата (первое значение в «uniqueSessions.distinct_count»)

  • количество посещений страниц: (второе значение в «uniqueSessions.distinct_count»)
    Важно, чтобы это было сделано в CMD, поскольку мне приходится использовать командный файл, поскольку целевому пользователю не разрешено запускать сценарии PowerShell и не иметь доступа к какому-либо другому инструменту CL.

На данный момент мне удалось свести файлы к необходимым элементам данных в виде отдельных объектов JSON, используя: type *.json | jq ".items[] | {url: .name, date: .metrics[][0][0], load: .metrics[][0][1]}"

результат выглядит так:

{
  "url": "page1.htm",
  "date": 1675292400000,
  "load": 4
}
{
  "url": "page1.htm",
  "date": 1675292400000,
  "load": 1
}
{
  "url": "page1.htm",
  "date": 1675292400000,
  "load": 7
}

однако, если я попытаюсь заключить его в квадратные скобки (как предлагают учебники), чтобы получить действительный JSON, я получу один файл с кучей массивов, начинающихся и заканчивающихся там, где они были в исходных файлах.
Я сделал домашнее задание и знаю об этом: объединение нескольких файлов json в один файл json с фильтрами jq на самом деле, я немного поигрался с этим, прежде чем спрашивать. Я подумал, что если бы я мог снова добавить фигурные скобки и корневой узел, это помогло бы, но я не нашел способа, с помощью которого JQ не преминул бы это сделать, отметив, что, скорее всего, ошибка возникает из-за использования кавычек Windows cmd.

Как я могу превратить это в один JSON вместо множества массивов и исходных файлов? Спасибо!

Вы хотите использовать map вместо .[] для сохранения массива? Демо

pmf 17.09.2023 03:01

Спасибо, моя проблема в том, что у меня есть несколько файлов JSON. В JQplay мне удалось получить фильтрацию, как в вашем примере, но только для одного файла. Как только я прочитаю все json-файлы, в целевом файле будет столько же массивов, сколько у меня было исходных файлов. Я видел ваш ответ в stackoverflow.com/questions/70302009/… но он также предназначен для фильтрации одних входных данных (внутри одного массива), тогда как у меня будет по одному в день. Или, может быть, я все еще не понимаю, что здесь делает карта?

Beavis 17.09.2023 03:19

При наличии нескольких входных данных вам потребуется некоторая структура, охватывающая их все. Либо используйте --slurp, который оборачивает их в массив (в котором вы можете использовать map), либо вызывайте для каждого входа в цикле вышестоящего уровня, например reduce. Я добавил ответ, охватывающий оба.

pmf 17.09.2023 03:31
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
3
65
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Для нескольких входных файлов вы можете создать вокруг них еще один массив, используя опцию --slurp (или -s), а затем использовать map:

jq -s 'map(.items[] | {…})' *.json

Демо

Или программно выполнить итерацию (например, используя reduce) по каждому вводу (используя inputs в сочетании с флагом --null-input (или -n):

jq -n 'reduce inputs as {$items} ([]; . + [$items[] | {…}])' *.json

Демо

Спасибо! Использовал первый, работает как часы. (Извините за поздний ответ, некоторое время отсутствовал.)

Beavis 27.09.2023 20:49

Мне жаль. Боюсь, я недостаточно знаю Instana и JQ, чтобы точно понять, что вам нужно... Вы также не показали желаемый конечный выходной файл... Однако я достаточно знаю пакетные файлы!

Чистый пакетный файл ниже обрабатывает все файлы *.json и извлекает «необходимые элементы данных», как показано выше. Это первый шаг к правильному решению, поскольку этот пакетный файл можно изменить любым удобным для вас способом.

@echo off
setlocal

for %%f in (*.json) do (
   set "url = "
   for /F "tokens=2,3 delims=[:,] " %%a in ('findstr "name uniqueSessions" "%%f"') do (
      if not defined url (
         echo "url": %%a
         set "url=%%a"
      ) else (
         echo "date": %%a
         echo "load": %%~Nb
         set "url = "
      )
   )
)

Пример вывода:

"url": "page1.htm"
"date": 1675292400000
"load": 4
"url": "page2.htm"
"date": 1675292400000
"load": 1
"url": "page3.htm"
"date": 1675292400000
"load": 7
"url": "page4.htm"
"date": 1675292400000
"load": 3
"url": "page5.htm"
"date": 1675292400000
"load": 6
"url": "page6.htm"
"date": 1675292400000
"load": 2

Возможно, если вы покажете нам желаемый выходной файл, я смогу завершить решение.

Извините, что вернулся так поздно, некоторое время меня не было на связи. Я добавил это в пакетный файл, но он не дал результатов, которые вы показываете: и «url», и «date» содержат URL-адреса, а «загрузка» остается пустым.

Beavis 27.09.2023 20:47

Это странно, потому что я скопировал те же данные, которые вы разместили выше, и использую их в качестве входных данных, поэтому моя программа выдает такие результаты. Вы сделали то же самое? То есть используйте данные, которые вы разместили выше, а не другие, возможно, другие данные...

Aacini 28.09.2023 01:28

Добавление |jq -s к тому, что у вас уже есть, должно сработать:

type *.json | 
jq ".items[] | {url: .name, date: .metrics[][0][0], load: .metrics[][0][1]}" |
jq -s 

Завершающий jq -s может выполнить перенос массива за вас, если у вас есть такой список объектов json:

§ cat input-malformed.json 
{ "a" : 1,
  "b" : 2 }
{ "a" : 11,
  "b" : 22 }

§ cat input-malformed.json | jq -s
[
  {
    "a": 1,
    "b": 2
  },
  {
    "a": 11,
    "b": 22
  }
]

У меня нет под рукой компьютера с Windows, но работает эквивалент bash в jq версии 1.6 (где a.json и b.json — это копии ваших входных документов JSON):

cat a.json b.json | 
jq ".items[] | {url: .name, date: .metrics[][0][0], load: .metrics[][0][1]}" |
jq -s 

Также попробовал это (после замены части cat на тип *.json), и это дало тот же результат, что и @pmf (который также включил -s), так что ответ на 100% ПРАВИЛЬНЫЙ, но поскольку (а) он ответил ранее, я принял это. Спасибо за внимание!

Beavis 27.09.2023 20:56

Другие вопросы по теме

Переменная powershell не может правильно цитироваться в моем скрипте
Tracert.exe не перенаправляется изнутри schtasks
Ошибка в пакетном скрипте: `отсутствуют операнды` и неправильные вычисления секунд
Bat File не может запустить сценарий powershell без жестко закодированного каталога
Можно ли еще больше сократить эту команду powershell? Я хочу попробовать ускорить это. (Один лайнер отправлен из пакетного скрипта)
Как мы можем создать файл .BAT, который может выключать компьютер через заданное время и показывать оставшееся время при каждой загрузке?
BATCH для удаления и копирования (резервного копирования) определенных папок и подпапок
Как извлечь встроенную ссылку из сохраненного в виде текста html-документа ИЛИ как использовать xidel для извлечения правильной ссылки?
Процент входа в файл .bat не работает с командой powershell
Как запустить исполняемый файл с графическим интерфейсом и консольную программу и завершить консольное приложение в приложении с графическим интерфейсом, закрытом пользователем?