Stockage de logs datés
2 participants
Page 1 sur 1
Stockage de logs datés
à l'origine, je voulais juste transmettre une suggestion à arc13 pour son programme Player detector : http://forum.computercraft.fr/t394-programme-player-detector-v0-7-6
Mais quitte à présenter l'astuce, autant la mettre à disposition de tout le monde.
Dans la plupart des programmes, les fichiers "logs" sont des journaux qui permettent de garder une trace de l’exécution, ce qui a marché, ou pas, et quand, voire par qui, etc.
Le format standard est un fichier texte brut, un ligne par log. Elle commence par la date et l'heure, suivi de tout le détail nécessaire.
Le format de la date est précis et très utile, il suit cette norme : YYYY-MM-DD hhss par exemple "2016-09-04 23:39:44"
C'est assez utile pour trier ou rechercher. Inscrit de cette manière, les dates s'ordonne de fait par ordre chronologique, du plus ancien au plus récent. Car il n'est pas très recommandé de stocker toutes les logs dans un même fichier. Plus le temps passe et plus il risque de devenir volumineux. L'écriture des logs en est potentiellement ralentie, et leur consultation est plus contraignante.
La première astuce est donc d’attribuer la date du jour dans le nom de fichier. Et comme ce format de date est pratique, les différents fichiers de logs seront de fait trié de par leur nom.
Malheureusement le World Interface (Life is peripheral) qui fournit facilement la date et l'heure IRL ne suit pas ce format. (1)
Voici donc une fonction qui traduit une date/heure du format "Sun Sep 04 23:39:44 CEST 2016" au format "2016-09-04 23:39:44"
- le jour : "2016-09-04"
- l'heure courante : "23" (string)
- l'heure précise : "23:39:44"
Je trouve ça plus pratique dans le contexte de génération de log files. Le jour pouvant servir de nom de fichier, la date et l'heure précise de préfixe à la ligne de log.
Dans le cas de logs conséquente, l'heure courante peut servir pour diminuer le volume des fichiers en augmentant leur nombre. C'est à dire, employer la date + heure courante comme nom de fichier.
C'est une bonne astuce de stocker les logs sur un support amovible, comme un floppy disk, si le programme qui génère les logs est une boucle infinie. Vous n'aurez pas à interrompre ce programme pour pouvoir consulter les logs. Vous pourrez également remplacer une disquette pleine par une disquette neuve, et stocker ça dans un coffre ou reformater la disquette pour vous en resservir.
Le volume d'une disquette est limité. Si c'est insuffisant, sachez que vous pouvez mettre un computer dans le Disk Drive à la place. Leur capacité de stockage est plus élevée. Il me semble qu'elle est de 900000 sur un Advanced Computer. Pour que ça marche vous devrez initialiser le computer. Posez le par terre, attribuez lui un label, créez un fichier (n'importe quoi) et supprimez ce fichier ensuite.
J'ai remarqué que d'enregistrer les logs à la volée (l'accès et l'écriture des fichiers) ralentissait de beaucoup la boucle principale de mon programme (rythmé par os.pullEvent).
J’accumule donc les logs dans une table "buffer", enregistre le tout à intervalle régulier et vide le buffer ensuite.
J'utilise beaucoup la fonction string.format(), et je vous la recommande, car outre le fait qu'elle permet d'économiser beaucoup de guillemets et doubles points pour insérer des variables, elle effectue également une vérification du type.
Plus d'infos ici : http://www.luteus.biz/Download/LoriotPro_Doc/LUA/LUA_Training_FR/LUA_Fonction_Chaine.html#Lua_Fonction_chaine_5
Voici ma fonction qui enregistre les logs dans un fichier :
Notez cette ligne, car elle fait tout le travail :
Si le fichier path n'existe pas, le paramètre sera "w" (write) qui initialise le fichier et l'écrit du début.
Si le fichier path existe déjà, le paramètre sera "a" (append). Cette option fait que ce qu'on y écrira s'ajoutera à la suite du contenu déjà présent dans ce fichier.
Dans ma boucle principale, j'ai un timer spécifique, pour enregistrer les logs à intervalle régulier indépendamment de la cadence de mon programme.
Par exemple, la boucle peut être cadencé à un tour par seconde, et les logs enregistrées toutes les 60 secondes.
Réf(1) :
Date au format ISO 8601 : 2004-02-12T15:19:21+00:00
Mais quitte à présenter l'astuce, autant la mettre à disposition de tout le monde.
Dans la plupart des programmes, les fichiers "logs" sont des journaux qui permettent de garder une trace de l’exécution, ce qui a marché, ou pas, et quand, voire par qui, etc.
Le format standard est un fichier texte brut, un ligne par log. Elle commence par la date et l'heure, suivi de tout le détail nécessaire.
Le format de la date est précis et très utile, il suit cette norme : YYYY-MM-DD hhss par exemple "2016-09-04 23:39:44"
C'est assez utile pour trier ou rechercher. Inscrit de cette manière, les dates s'ordonne de fait par ordre chronologique, du plus ancien au plus récent. Car il n'est pas très recommandé de stocker toutes les logs dans un même fichier. Plus le temps passe et plus il risque de devenir volumineux. L'écriture des logs en est potentiellement ralentie, et leur consultation est plus contraignante.
La première astuce est donc d’attribuer la date du jour dans le nom de fichier. Et comme ce format de date est pratique, les différents fichiers de logs seront de fait trié de par leur nom.
Malheureusement le World Interface (Life is peripheral) qui fournit facilement la date et l'heure IRL ne suit pas ce format. (1)
Voici donc une fonction qui traduit une date/heure du format "Sun Sep 04 23:39:44 CEST 2016" au format "2016-09-04 23:39:44"
- Code:
local monthNum = {["Jan"]="01",["Feb"]="02",["Mar"]="03",["Apr"]="04",["May"]="05",["Jun"]="06",["Jul"]="07",["Aug"]="08",["Sep"]="09",["Oct"]="10",["Nov"]="11",["Dec"]="12"}
local function dateConv(str)
local month,day,h,m,s,year = string.match(str, "%a+ (%a+) (%d+) (%d+):(%d+):(%d+) CEST (%d+)")
return string.format("%s-%s-%s",tostring(year),monthNum[month],tostring(day)),tostring(h),string.format("%s:%s:%s",tostring(h),tostring(m),tostring(s))
end
- le jour : "2016-09-04"
- l'heure courante : "23" (string)
- l'heure précise : "23:39:44"
Je trouve ça plus pratique dans le contexte de génération de log files. Le jour pouvant servir de nom de fichier, la date et l'heure précise de préfixe à la ligne de log.
Dans le cas de logs conséquente, l'heure courante peut servir pour diminuer le volume des fichiers en augmentant leur nombre. C'est à dire, employer la date + heure courante comme nom de fichier.
C'est une bonne astuce de stocker les logs sur un support amovible, comme un floppy disk, si le programme qui génère les logs est une boucle infinie. Vous n'aurez pas à interrompre ce programme pour pouvoir consulter les logs. Vous pourrez également remplacer une disquette pleine par une disquette neuve, et stocker ça dans un coffre ou reformater la disquette pour vous en resservir.
Le volume d'une disquette est limité. Si c'est insuffisant, sachez que vous pouvez mettre un computer dans le Disk Drive à la place. Leur capacité de stockage est plus élevée. Il me semble qu'elle est de 900000 sur un Advanced Computer. Pour que ça marche vous devrez initialiser le computer. Posez le par terre, attribuez lui un label, créez un fichier (n'importe quoi) et supprimez ce fichier ensuite.
J'ai remarqué que d'enregistrer les logs à la volée (l'accès et l'écriture des fichiers) ralentissait de beaucoup la boucle principale de mon programme (rythmé par os.pullEvent).
J’accumule donc les logs dans une table "buffer", enregistre le tout à intervalle régulier et vide le buffer ensuite.
- Code:
local logBuffer = {}
local function addLog(k,v,t)
local _d,_,_t = dateConv(wi.getRealDate())
logBuffer[#logBuffer+1] = string.format(
"%s_%s|%s:%s|%s",
_d,_t,
v and "200" or "403", k,
type(t)=="table" and textutils.serializeJSON(t) or tostring(t)
)
end
J'utilise beaucoup la fonction string.format(), et je vous la recommande, car outre le fait qu'elle permet d'économiser beaucoup de guillemets et doubles points pour insérer des variables, elle effectue également une vérification du type.
Plus d'infos ici : http://www.luteus.biz/Download/LoriotPro_Doc/LUA/LUA_Training_FR/LUA_Fonction_Chaine.html#Lua_Fonction_chaine_5
Voici ma fonction qui enregistre les logs dans un fichier :
- Code:
local root = "disk" -- ou peripheral.call("drive_123","getMountPath")
local function saveLog()
local _d,_h = dateConv(wi.getRealDate())
local path = "/"..root.."/".._d.."_".._h
local fh = fs.open(path, fs.exists(path) and "a" or "w")
fh.write(table.concat(logBuffer, "\n").."\n")
fh.close()
logBuffer={}
end
Notez cette ligne, car elle fait tout le travail :
- Code:
local fh = fs.open(path, fs.exists(path) and "a" or "w")
Si le fichier path n'existe pas, le paramètre sera "w" (write) qui initialise le fichier et l'écrit du début.
Si le fichier path existe déjà, le paramètre sera "a" (append). Cette option fait que ce qu'on y écrira s'ajoutera à la suite du contenu déjà présent dans ce fichier.
Dans ma boucle principale, j'ai un timer spécifique, pour enregistrer les logs à intervalle régulier indépendamment de la cadence de mon programme.
Par exemple, la boucle peut être cadencé à un tour par seconde, et les logs enregistrées toutes les 60 secondes.
- Code:
local timerTick = os.startTimer(1)
local timerSaveLog = os.startTimer(60)
while true do
local e, p1,p2,p3,p4,p5 = _pullEventRaw()
if e=="event au pif" then
process() -- Processus principal
elseif e=="timer" and p1==timerTick then
--rythme du programme
term.setCursorPos(1,1)
term.clearLine()
term.write(os.clock()
timerTick = os.startTimer(1)
elseif e=="timer" and p1==timerSaveLog then
--L'heure est venue d'enregistrer les logs
if #logBuffer>0 then
saveLog()
end
timerSaveLog = os.startTimer(60)
end
end
Réf(1) :
Date au format ISO 8601 : 2004-02-12T15:19:21+00:00
Dernière édition par skypop le Lun 3 Oct - 3:22, édité 2 fois (Raison : Erreur dans le code)
skypop- Messages : 95
Date d'inscription : 25/07/2016
Re: Stockage de logs datés
Désolé, j'avais l'intention de le mentionner, et puis j'ai zappé..
skypop- Messages : 95
Date d'inscription : 25/07/2016
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum