Настройка тега уведомления для функции Azure

Я использую функцию Azure для приема сообщений из концентратора событий и отправки уведомлений через концентратор уведомлений Azure. Работает отлично! Теперь я хотел посмотреть, могу ли я добавлять теги к этим сообщениям, чтобы разрешить пользователям таргетинг с помощью этих тегов.

Выходные данные для концентратора уведомлений имеют параметр «выражение тега», который вы можете настроить. Но это похоже на статичный текст. Вместо этого мне нужно динамически устанавливать эти теги на основе сообщения, полученного от концентратора событий. Я не уверен, можно ли как-нибудь поместить туда динамический контент?

Я также обнаружил, что конструктор объекта GcmNotification, который я использую, имеет перегрузку, которая позволяет использовать строку тега. Но когда я пытаюсь это сделать, я получаю предупреждение во время компиляции о том, что это устарело, и когда функция запускается, она показывает ошибку, потому что свойство Tag должно быть пустым.

Так что я не понимаю, а) возможно ли это вообще и б) как это сделать, когда это возможно. Любые идеи?

Обновление: как было предложено, я попытался создать объект POCO для сопоставления с моей входной строкой. Строка выглядит следующим образом:

[{"deviceid":"repsaj-neptune-win10pi","readingtype":"temperature1","reading":22.031614503139451,"threshold":23.0,"time":"2016-06-22T09:38:54.1900000Z"}]

Объект POCO:

public class RuleMessage
{
    public string deviceid;
    public string readingtype;
    public object reading;
    public double threshold;
    public DateTime time;
}

Для функции я теперь попробовал как RuleMessage[], так и List<RuleMessage> в качестве типов параметров, но функция жалуется, что не может преобразовать ввод:

2016-06-24T18: 25: 16.830 Исключение при выполнении функции: Functions.submerged-function-ruleout. Microsoft.Azure.WebJobs.Host: параметр привязки исключения 'inputMessage'. Microsoft.Azure.WebJobs.Host: параметры привязки к сложным объектам (например, «RuleMessage») используют сериализацию Json.NET. 1. Свяжите тип параметра как «строка» вместо «RuleMessage», чтобы получить необработанные значения и избежать десериализации JSON, или 2. Измените полезную нагрузку очереди на допустимый json. Ошибка синтаксического анализатора JSON: невозможно десериализовать текущий массив JSON (например, [1,2,3]) в тип 'Submission # 0 + RuleMessage', потому что для этого типа требуется объект JSON (например, {"name": "value"}) для десериализовать правильно. Чтобы исправить эту ошибку, либо измените JSON на объект JSON (например, {"name": "value"}), либо измените десериализованный тип на массив или тип, реализующий интерфейс коллекции (например, ICollection, IList), например List, который может десериализоваться из массива JSON. JsonArrayAttribute также можно добавить к типу, чтобы заставить его десериализоваться из массива JSON.

Код функции:

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Azure.NotificationHubs;

public static void Run(List<RuleMessage> inputEventMessage, string inputBlob, out Notification notification, out string outputBlob, TraceWriter log)
{
    if (inputEventMessage == null || inputEventMessage.Count != 1)
    {
        log.Info($"The inputEventMessage array was null or didn't contain exactly one item.");

        notification = null;
        outputBlob = inputBlob;

        return;
    }

    log.Info($"C# Event Hub trigger function processed a message: {inputEventMessage[0]}"); 

    if (String.IsNullOrEmpty(inputBlob))
        inputBlob = DateTime.MinValue.ToString();

    DateTime lastEvent = DateTime.Parse(inputBlob);
    TimeSpan duration = DateTime.Now - lastEvent;

    if (duration.TotalMinutes >= 0) {
        notification = GetGcmMessage(inputMessage.First()); 
        log.Info($"Sending notification message: {notification.Body}");
        outputBlob = DateTime.Now.ToString();
    } 
    else {
        log.Info($"Not sending notification message because of timer ({(int)duration.TotalMinutes} minutes ago).");

        notification = null;
        outputBlob = inputBlob;
    }
}

private static Notification GetGcmMessage(RuleMessage input)
{
    string message;

    if (input.readingtype == "leakage")
        message = String.Format("[FUNCTION GCM] Leakage detected! Sensor {0} has detected a possible leak.", input.reading);
    else
        message = String.Format("[FUNCTION GCM] Sensor {0} is reading {1:0.0}, threshold is {2:0.0}.", input.readingtype, input.reading, input.threshold);

    message = "{\"data\":{\"message\":\""+message+"\"}}";

    return new GcmNotification(message);
}

public class RuleMessage
{
    public string deviceid;
    public string readingtype;
    public object reading;
    public double threshold;
    public DateTime time;
}

Обновление 28-6-2016: мне не удалось заставить его работать, переключив вывод ASA на строку, разделенную так, чтобы он больше не генерировал массив JSON. Это темп. исправить, потому что привязка функции теперь не работает, как только в выходных данных появляется более одной строки (что может случиться).

В любом случае, теперь я приступил к установке tagExpression, согласно инструкции, которую я изменил на:

{
  "type": "notificationHub",
  "name": "notification",
  "hubName": "repsaj-neptune-notifications",
  "connection": "repsaj-neptune-notifications_NOTIFICATIONHUB",
  "direction": "out",
  "tagExpression": "deviceId:{deviceid}"
}

Где {deviceid} равно свойству deviceid в моем POCO RuleMessage. К сожалению, это не работает, когда я вызываю функцию, которую он выводит:

Исключение при выполнении функции: Functions.submerged-function-ruleout. Microsoft.Azure.WebJobs.Host: параметр привязки исключения «уведомление». Microsoft.Azure.WebJobs.Host: нет значения для именованного параметра deviceid.

Что неверно, я точно знаю, что свойство было установлено, поскольку я зарегистрировал его в окне вывода. Я также пробовал что-то вроде {inputEventMessage.deviceid}, но это тоже не работает (так как я не понимал, как среда выполнения отображает {deviceid} на правильный объект ввода, когда их больше одного.


person Jasper    schedule 24.06.2016    source источник


Ответы (1)


Свойство привязки tagExpression поддерживает параметры привязки, поступающие из свойств ввода триггера. Например, предположим, что ваше входящее событие концентратора событий имеет свойства A и B. Вы можете использовать эти свойства в своем tagExpression, используя синтаксис скобок, например: My Tag {A}-{B}.

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

person mathewc    schedule 24.06.2016
comment
Хорошо, но что, если мое входное сообщение представляет собой строку, содержащую строку в формате json, из которой я хочу использовать одно конкретное свойство? - person Jasper; 24.06.2016
comment
В случае функции Node.js, если телом события является JSON, вы можете ссылаться на эти свойства в своем выражении привязки. Если вы используете C #, вам следует определить класс POCO, который сопоставляется с вводом, после чего вы можете ссылаться на эти свойства POCO в выражении привязки. Попробуйте :) - person mathewc; 24.06.2016
comment
Поделитесь, пожалуйста, определением вашей функции. Похоже, ваша функция сопоставлена ​​с одноэлементным RuleMessage, но вы отправляете ввод массива. Попробуйте отправить объект JSON, а не массив. - person mathewc; 24.06.2016
comment
Я тоже добавлю тело функции. Я бы изменил ввод, но он исходит от концентратора событий, который получает ввод из потоковой аналитики. Я понятия не имею, что мне нужно изменить, где переключить тип. - person Jasper; 24.06.2016
comment
Попробуйте изменить тип параметра на RuleMessage []. Различные типы параметров привязки подробно описаны здесь в вики. - person mathewc; 24.06.2016
comment
Тогда у нас может быть ошибка в привязке массива (я зарегистрировал выпуск, чтобы отследить это). Попробуйте изменить свою функцию, чтобы привязать ее к одному RuleMessage, и в поле Run портала вы можете протестировать, отправив JSON для одного экземпляра. - person mathewc; 24.06.2016
comment
Кажется, так. Когда он меняет его на один объект и вводит соответствующий json, он работает. Переключение обратно на массив, и он снова терпит неудачу (также с ручным вводом). Есть идеи, могу ли я заставить ASA или концентратор событий выводить один элемент вместо массива? - person Jasper; 24.06.2016
comment
Позвольте нам продолжить это обсуждение в чате. - person Jasper; 24.06.2016
comment
Среда выполнения функций будет обрабатывать сопоставление потока событий с вашей функцией одноэлементным способом. Никаких изменений с этой стороны не требуется. - person mathewc; 24.06.2016
comment
Итак, на самом деле событие должно было быть одноэлементным, но эта часть работает некорректно? - person Jasper; 24.06.2016
comment
После всего этого кажется, что вы разблокированы (используйте одноэлементный параметр). Кроме того, я думаю, что мой первоначальный ответ ответил на ваш первоначальный вопрос, подробно описывая, как использовать параметры привязки в tagExpression. Если да, отметьте это как ответ, спасибо :) - person mathewc; 25.06.2016
comment
Эмм нет. Если вы предполагаете, что теперь работает одноэлементный параметр; это не так, если вход также не является одним объектом json, а не массивом. Среда выполнения выбирает / получает массив из концентратора событий, и он не анализируется на (несколько) синглтонов. Так что на данный момент он работает только вручную. - person Jasper; 25.06.2016
comment
Связывание триггера Singleton EventHub в C # мне подходит. У меня есть другая функция, использующая привязку вывода EventHub для перекачки нескольких сообщений в мой концентратор, и моя запущенная функция обрабатывает их. Если это не работает для вас, я предлагаю вам либо создать новый вопрос SO для этой проблемы, либо зарегистрировать проблему в нашем репозитории. - person mathewc; 25.06.2016
comment
Странно, но обратите внимание, что это входная привязка концентратора событий, возможно, она отличается. В любом случае моя строка, представляющая собой массив из 1 элемента, не анализируется до 1 элемента, вместо этого функция получает массив. И поэтому жалуется, что не может разобрать это на синглтон. Создаю вопрос в гитхабе. - person Jasper; 25.06.2016