Aller au contenu

HC2 : Envoi de Logs vers un serveur Syslog (Synology)


MAM78

Messages recommandés

Précision, les push ne sont générés que pour les logs générés par le NAS lui-même pas ceux provenant d'autres sources. Cf. celles que nous générons par le présent module. 

Lien vers le commentaire
Partager sur d’autres sites

Hello,

 

Je viens de vous livrer une nouvelle version de ma fonction d'envoi de message dans la Logs vers un serveur Syslog. Voir 1er Tuto.

 

Elle est constituée de 2 parties :

  • Une scène que l'on appelle depuis nos VD ou nos Scènes pour envoyer les messages. Cette scène appel un VD qui se charge lancer les commandes d'écriture dans la Syslog
  • Un VD qui lance les commandes d'écriture dans la Syslog.

Je suis obligé de construire cette fonction en 2 parties (VD et Scènes) du fait que la commande Net.FUdpSocket() existe uniquement dans les VD et non dans les scènes.

 

Dès que l'un de vous me trouve une solution pour faire la même chose que la fonction Net.FUdpSocket() dans une scène, je fusionnerais les 2 parties.

 

Vous trouverez également un VD DEMO qui vous permet de tester la fonction d'envoi de message dans la Logs vers un serveur Syslog.

Lien vers le commentaire
Partager sur d’autres sites

@Steven comme indiqué dans notre conversation sur ton sujet HC2 - Ajouter du texte dans vos "debug".

 

Je viens de faire le test sur la base de ta suggestion d'utiliser un Label pour tester la fin d'exécution. Mais comme indiquer ça ne fonctionne pas.

 

Tu trouveras ci-joint les 2 VD et la scène utilisés. Si tu regardes dans la log du bouton du VD Message Synology. il y a des messages qui sont mangés ;)

 

Ai-je bien appliqué le principe que tu me suggérais ?

 

Syslog_Message_Demo.vfib.json

 

Syslog_Message.vfib.json

 

le code de ma scène :

--[[
%% properties
%% events
%% globals
--]]
--------------------------------------------------
-- Scene   : Syslog Message
-- Author  : Mam78
-- Version : 0.1
-- Date    : March 2017
--------------------------------------------------
-- Prerequisites for use you need to :
--   install the corresponding VD "Syslog Message"
--   modify below variable vd_id with the number of the corresponding VD "Syslog Message"
--   change the icon of the scene
--------------------------------------------------
-- For use it from a VD or Scene you need call them like this :
--   fibaro:startScene(40, {{sev = "debug"}, {orig= "VD/Scene Name"}, {mess = "SysLog text message"}})
--     first parameter (40) is the number this Scene
--     Sev = the severity (textual) of the message, see the value bilow (not the number)
--     Orig = the nome of the VD ou Scene who call this Scene to indicate the origine of the message
--     mess = Your message
--------------------------------------------------

-----------------------
-- User settings to be changed
-----------------------
local vd_id = 179 -- id number off the corresponding VD "Syslog Message"
local sc_id = 40  -- id off the presence scene
local VG_syslog_message ="syslog_message" -- Variable name if you use Gabal Variable

-----------------------
-- No more change under this
-----------------------

-----------------------
-- number button off used in the corresponding VD "Syslog Message"
-----------------------
local bt_nb = 1

local debug = true -- or true
local Max_Elapsed_Time = 10 -- seconds, used for timeout
local syslog_hostname = ""

-----------------------
-- 8 level off severity
-----------------------
local severity = {
  ["emergency"] = 0,
  ["alert"]     = 1,
  ["critical"]  = 2,
  ["error"]     = 3,
  ["warning"]   = 4,
  ["notice"]    = 5,
  ["info"]      = 6,
  ["debug"]     = 7
}

-----------------------
-- load the args from the scene
-----------------------
local arg_sev = nil
local arg_orig = nil
local arg_mess = nil

local params = fibaro:args()
if (params) then
  
  for k, v in ipairs(params) do
    if (v.sev) then arg_sev = v.sev end
    if (v.orig) then arg_orig = v.orig end
    if (v.mess) then arg_mess = v.mess end
  end
end

var_abort=false
if arg_sev and arg_orig and arg_mess then
  
  -----------------------
  -- this code is for waiting the end of the precedente sending
  -----------------------
  startTime = os.time()  
  local save_scenecount = fibaro:countScenes(sc_id)

  while (fibaro:getValue(vd_id, "ui.Label2.value") == "OUI") do
    fibaro:sleep(2000)  
    if (timeout) then
      -- en cas d attente trop longue, prevoir une sortie
      fibaro:abort()
      var_abort=true
    end
  end
  
--  while true do
--    local elapsedTime = os.difftime(os.time(), startTime or 0)
--   if elapsedTime > Max_Elapsed_Time then
--      if debug then fibaro:debug("Send message scene timeout : "..arg_sev.." ("..severity[arg_sev]..")") end
--      break
--    end 
--    if debug then fibaro:debug("Nbr Scene = "..fibaro:countScenes(sc_id).." Elapsed time : " .. elapsedTime.." : "..arg_sev.." ("..severity[arg_sev]..")") end
--    if fibaro:countScenes(sc_id) < save_scenecount or fibaro:countScenes(sc_id) == 1 then 
--      break 
--    else
--      -- fibaro:sleep(1 * 1000) -- Wait 1 seconds
--    end
--  end

--  if fibaro:countScenes(sc_id) <=1 then

  if not(var_abort) then
  
    -----------------------
  	-- Set the label under process on YES
  	-----------------------
  	fibaro:call(vd_id, "setProperty", "ui.Label2.value", "YES")
    
    if debug then fibaro:debug("Message : "..arg_mess) end
    
    -----------------------
    -- Calculate the priority for the message  
    -----------------------
    local syslog_severity = severity[arg_sev]
    local syslog_facility = 1 -- 1 = user category
    local syslog_priority = syslog_facility*8 + (syslog_severity%8)
    
    -----------------------
    -- Remplace de spaces character by "_" because space is forbidden
    -----------------------
    local syslog_origine = string.gsub(arg_orig, " ", "_") -- Space is forbidden
    local syslog_message = ("<%d>%s %s %s: %s\n"):format (syslog_priority, os.date "%b %d %H:%M:%S", syslog_hostname, syslog_origine , arg_mess)

    -----------------------
    -- Set the Gabal Variable used by the virtual device "Message Syslog"
    -----------------------
    --fibaro:setGlobal(VG_syslog_message, syslog_message)

    -----------------------
    -- Set the label on the virtual device "Message Syslog"
    -----------------------
    fibaro:call(vd_id, "setProperty", "ui.label_1_0.value", syslog_message)
    
    -----------------------
    -- push the button on the virtual device "Message Syslog"
    -----------------------
    fibaro:call(vd_id, "pressButton", bt_nb)
  else
    fibaro:debug("Sortie de la boucle pour timeout")
  end
else
  fibaro:debug("There are missing parameters")
end
-----------------------

 

Modifié par MAM78
Lien vers le commentaire
Partager sur d’autres sites

J'ai pas tout lu, mais du premier coup d'oeil :

 

Attendre : OUI

while (fibaro:getValue(vd_id, "ui.Label2.value") == "OUI") do

Et mettre : YES

fibaro:call(vd_id, "setProperty", "ui.Label2.value", "YES")

Je vois pas comment cela peux fonctionner.

Lien vers le commentaire
Partager sur d’autres sites

et dans la boucle ci-dessous, le "timeout" n'existe pas, c'est à définir :

 

while (fibaro:getValue(vd_id, "ui.Label2.value") == "OUI") do
    fibaro:sleep(2000)  
    if (timeout) then
      -- en cas d attente trop longue, prevoir une sortie
      fibaro:abort()
      var_abort=true
    end
  end

 

Et je ne vois pas quand le label repasse à "NON".

  • Upvote 1
Lien vers le commentaire
Partager sur d’autres sites

J'ai remarqué qu'il y a une erreur dans le VD j'ai mélanger le français et anglais (OUI vs YES) entre le test la boucle à OUI d'attente et la mise à jour de la valeur du label à YES. :(

 

Je vais refaire des tests lorsque je serais à la maison.

Lien vers le commentaire
Partager sur d’autres sites

Décidément quand ça veut pas, ça veut pas :15:

 

J'ai toujours le même problème lorsque la scène est sollicitée plusieurs fois dans un intervalle de temps très court (de l'ordre du centième de seconde).

Les scènes en question détectent en même temps le passage du label à NO et sortent de leur boucle d'attente. Du coup elles sollicitent le VD en quasi simultané et donc, il n'y en qu'une qui envoi son messages, les autres messages qui devaient être envoyés par les autres instances de la scènes sont perdues.

 

J'ai bien tenté de mettre un wait d'une durée aléatoire pour décaler les scènes dans la boucle d'attente en utilisant une fonction du random (voir code ci-dessous). Mais rien à faire ces scènes qui s'exécutent dans un intervalle très court calculent le même x nombre de centièmes de secondes. Cette fonction random n'est pas vraiment aléatoire puisqu'elle retourne la même valeurs pour chacune des scènes lancées en parallèle.

 

math.randomseed(os.time())
local x = math.random(2000,2500)
fibaro:sleep(x)

A ce stade, je ne vois plus de solutions. P....n pourquoi Fibaro n'a pas intégré la fonction Net.FUdpSocket() dans les scènes. :15:

 

Est-ce que l'un des gourous du forum veut bien relevé le chalenge de me trouver une solution ?

Modifié par MAM78
Lien vers le commentaire
Partager sur d’autres sites

Si tu rootes ta box, la solution prend 2s, mais tu ne pourras pas partager ton travail du coup....

 

Pour te donner une idée des possibilités, y'a pas de limite en fait... par exemple avec mes scènes je fais du SSH vers mes serveurs pour les piloter depuis la box domotique, qui ordonnance tous mes backups.

 

Malheureusement, de base, le LUA, les scènes, et la VD, sont beaucoup trop bridées par Fibaro :(

Lien vers le commentaire
Partager sur d’autres sites

  • 3 mois après...
  • 5 mois après...
Citation

J'ai bien tenté de mettre un wait d'une durée aléatoire pour décaler les scènes dans la boucle d'attente en utilisant une fonction du random (voir code ci-dessous). Mais rien à faire ces scènes qui s'exécutent dans un intervalle très court calculent le même x nombre de centièmes de secondes. Cette fonction random n'est pas vraiment aléatoire puisqu'elle retourne la même valeurs pour chacune des scènes lancées en parallèle.

 

Et si tu testes au lancement de la scène le nombre d'instance et que tu fais un fibaro:sleep(nb d'instance) ?

Modifié par OJC
Lien vers le commentaire
Partager sur d’autres sites

Le 3/8/2017 à 01:03, MAM78 a dit :

math.randomseed(os.time())

 

math.randomseed(os.time() + fibaro:countScenes()) 

 

devrait le faire proprement.

 

Le soucis est que os.time() ne prend en compte que les secondes et non pas les centièmes

Lien vers le commentaire
Partager sur d’autres sites

Hello @Steven Pourrais-tu STP m'expliquer en quoi ta proposition corrigera mon problème de messages loupés ?

 

Désolé, mais pour le moment, je ne peux pas faire de tests, mon NAS est en réparation chez Synology. Cf. bug du processeur. 

 

NAS éposé le 2/11. 2 semaines plus tars toujours pas de nouvelle de Grosbill ou de Synology :(

Lien vers le commentaire
Partager sur d’autres sites

Je ne faisais que de répondre à une question sans même regarder le contexte de cette dernière.

 

Au lieu de jouer sur le VD, ce qui ne semble pas fonctionner correctement, voici une proposition qui me semble plus propre.

 

Si j'ai plusieurs instances d'une même scène qui sont appelées trop fréquemment, je les mettrais en attente le temps que la précédente se termine.

Je garanti ainsi un traitement séquentiel.

 

Le code est des plus basique :

while fibaro:countScenes() > 1 do
  fibaro:sleep(100)
end

Cela devrait empiler les instances de scène et les libérer une par une.

 

Fini ta scène par un petit fibaro:sleep(200) pour t'assurer que ton VD a bien eu le temps de transmettre les données.

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

Je vais essayer ça dès que j'aurais reccupéré mon NAS

 

J'ai également demandé sur le fofo quand ils vont nous ajouter Net.FUdpSocket() dans les scènes, ce qui simplifiera grandement

Modifié par MAM78
Lien vers le commentaire
Partager sur d’autres sites

  • 2 ans après...

Bonsoir à tous,

Le topic initial est ancien mais j'en ai eu un vrai besoin et j'ai essayé de faire quelque chose d'équivalent avec les défauts signalés en moins, en particulier la capacité de logger des messages rapprochés de façon la moins intrusive/plus transparente possible pour le code 'envoyeur'...

 

C'est ma première contribution à ce forum, dont j'ai abondamment profité, c'est mon premier retour.

J'espère bénéficier de votre indulgence, au moins sur la forme. (quand j'y pense :j'espère ne pas avoir réinventé ici l'eau tiède d'un autre post?)

Et, en attendant : Bonne Année à tous

 

Le post initial reste valide et une base solide.

Les différences sont:

              # il n'y a pas (plus) besoins de scène complémentaire à la VD.

              # La VD utilise TCP plutôt que UDP pour côser au syno (c'est donc à modifier dans le paramétrage des journaux de synology, cf 1er post de ce sujet, c'est la seule modification de ce côté).

Pourquoi?: UDP n'est pas fait pour ASSURER la réception d'un message et encore moins la date de réception et encore moins l'ordre de réception. C'est fait pour émettre un flux sans se poser de question sur la réception. TCP c'est le contraire :-)

              # L'idée est de stocker rapidement les message à envoyer dans une pile (FIFO)  pour pouvoir s'assurer d'avoir tous les messages à envoyer
              # Les messages empilés sont dépilés par bloc toutes les 3s (c'est la seule solution que j'ai trouvée pour ne pas avoir de conflit read/write, mais je suis à l'écoute..)

 

Vu de l'extérieur:

Les messages à envoyer sont json.encodés dans le champ 'logTemp' de la VD puis 'empilés' en appuyant sur le bouton 'Empil' (voir plus bas code à ajouter), le reste se passe tout seul :

Ils sont dépilés régulièrement (tte les 3s):

  # vers le NAS si leur niveau de sévérité est égal ou dépasse ce qui est indiqué dans le label 'MinLevel',

  # poubellisés sinon.

Le Label MinLevel peut être changé en cliquant sur les bouton '+'  ou '-'.

Cela permet de moduler la charge des journaux selon que l'on est en train de tester quelque chose ou non...

 

Le bouton 'reset' est au fond un bouton de debug. Mais il est recommandé d'appuyer dessus avant de tenter d'envoyer un 1er log.

 

La 'nouvelle' VD se présente ainsi:

image.png.f5d76d3f25bc330d0ed11d56f962974a.png

 

pour envoyer quelque chose au journal, la base est d'ajouter dans la scène/VD où cela est nécessaire le code suivant :

    local vd_id = 175 -- id de VI_SynoLog (à remplacer................)
    msg={sev = "warning", Time=os.time(), orig= "Test Syslog Message", mess = "Text for a warning"}  --évidemment à ajuster au besoin, selon toute logique orig devrait permettre d'identifier la scène ou la VD qui émet le message.
    fibaro:call(vd_id, "setProperty", "logTemp", json.encode(msg))  --La VD utilise intensivement les 'champs' log et logTemp, ne pas les utiliser à autre chose SVP
    fibaro:call(vd_id, "pressButton", 1)

         (voir plus loin pour les pb de synchro)

 

Ce  code 'empile' le message (daté de son heure propre, pas de l'heure d'émission vers le synology) il sera envoyé un peu plus tard, mais il s'agit d'un journal! (journal finalement lu plus tard histoire de comprendre les 'scoops' dont on a été informé par ailleurs :-) on n'est pas sur BFM!)
La pile contient 10 messages (10 message/3secondes)  Il est très simple d'augmenter ou diminuer cette dose dans le code associé au bouton 1

 

Le label 'In' est le nombre de message empilés, le label 'Out' est le nombre de messages envoyés vers le synology (ou filtrés vers la poubelle par 'MinLevel').

Si les deux valeurs sont égales c'est que tout a été traité.

Si In est < Out cékia1bug!!!

 

"plus loin pour les pb de synchro" c'est ici:

Pour les puristes ou ceux qui pensent avoir à envoyer plein de log importants à leur NAS je recommande:

    local vd_id = 175 -- id number of VI_SynoLog (à remplacer................)

    Time= os.time()
    while ((fibaro:getValue(vd_id, "logTemp") ~= "") and (os.difftime(os.time(),Time) < 2)) do
       fibaro:sleep(100)
    end

    msg={sev = "warning", Time=os.time(), orig= "Test Syslog Message", mess = "Text for a warning"}
    fibaro:call(vd_id, "setProperty", "logTemp", json.encode(msg)

    fibaro:call(vd_id, "pressButton", 1)

 

Les très puristes pourraient ajouter un if ((fibaro:getValue(vd_id, "logTemp") ~= "")  avant d'appuyer sur le bouton, dans la pratique les choses vont tellement vite mon brave monsieur...

Dans mon cas j'ai intégré ces lignes dans un code générique d’encapsulation de fibaro:debug, activé si une variable 'severity' est non nulle

 

Installation: charger le vfib (sur une HC2 :-)), Renseigner IP du NAS et Port (514), cliquer sur le bouton 'Reset', envoyer un message de test (le plus simple est de copier un des codes ci dessus dans une scène test)

 

PS1: en cours de fonctionnement le label 'Data' contient le dernier lot de messages envoyés, cela permet de se faire, par sondage, une idée de la nécessité d'augmenter la taille de la fifo.

PS2: J'ai forcé le champ 'host' à HC2 dans dans le bouton 'Send' (2). Rien n’empêche de modifier...

PS3: 'évidement' ce qui est json.encodé par l’émetteur doit être intelligible par ce qui est lu en appuyant sur le bouton 'Send'... Mais le fait de d'encoder json garanti que le reste est étanche aux modifications

 

 

 

image.png

J'ai decouvert 2 bug (lecture de l'IP et timeout pas efficace). c'est corrigé par cette version 0.2

 

 

VI_SynoLog0.2.vfib

Modifié par yves.guern
  • Like 2
Lien vers le commentaire
Partager sur d’autres sites

  • 5 mois après...
×
×
  • Créer...