Rotating Access Logs with $date_local

How can I format the $date_local string? I want it to be date only,
like 20141028, and then use it in the filename for access log.

Is that possible? and if not, why? seems like a simple solution to a
problem that many users face and resort to external tools etc.

I’m running Windows if that makes a difference.

TIA


Igal Sapir
Railo Core Developer

Hello!

On Tue, Oct 28, 2014 at 08:39:04AM -0700, Igal @ getRailo.org wrote:

How can I format the $date_local string? I want it to be date only,
like 20141028, and then use it in the filename for access log.

Is that possible? and if not, why? seems like a simple solution to a
problem that many users face and resort to external tools etc.

It is possible - you can use construct appropriate variable, e.g.,
by using map{} and $time_local. (The $date_local won’t work for
you as you won’t be able to set format without SSI.)

On the other hand, it’s not recommended as it implies unneeded
work on each request. It’s better to configure proper log
rotation instead, see:

http://nginx.org/en/docs/control.html#logs

On UNIX systems there are system tools to rotate logs, like
newsyslog or logrotate, and configuring log rotation is as easy as
adding a line to appropriate configuration file. There are likely
something available for Windows, too.


Maxim D.
http://nginx.org/

Hello Maxim,

It is possible - you can use construct appropriate variable, e.g.,
by using map{} and $time_local. (The $date_local won’t work for
you as you won’t be able to set format without SSI.)
Thank you for your prompt reply. I do not have much experience with
nginx configuration so I have a follow up question.

I looked up the docs about map{} at
Module ngx_http_map_module and I tried to
follow the example. I see that $time_local is (in my local time)
“28/Oct/2014:09:30:35 -0700” so I want from that the year, month, and
day. as an experimentation, I tried to add the following:

map $time_local $date {
    ~\w{11}    0;
}

but I get an error that the ‘{’ character is not valid at that
position. so I tried instead

~\w\w\w\w\w\w\w\w\w\w\w    0;

and then nginx starts up but $date is an empty string.

Can you point me in the right direction? and if it’s not too
complicated make a suggestion regarding the regex that I would need
since I must break the $time_local to year, month, and day (or do I need
to create 3 map{} variables for that? now that would be inefficient…)

On the other hand, it’s not recommended as it implies unneeded
work on each request.
With the amount of traffic that I get, and the way that nginx is
handling it, these few added microseconds should not be an issue IMO and
it would be a much easier solution to implement than an external process
that may or may not work properly.

Thanks a lot!


Igal Sapir
Railo Core Developer

On Tue, Oct 28, 2014 at 09:48:32AM -0700, Igal @ getRailo.org wrote:

Hi there,

It is possible - you can use construct appropriate variable, e.g.,
by using map{} and $time_local. (The $date_local won’t work for
you as you won’t be able to set format without SSI.)
Thank you for your prompt reply. I do not have much experience with
nginx configuration so I have a follow up question.

The thread starting at can a map + regex be used to generate variables for YYYY-MM-DD-HH? is not
entirely dissimilar to this one. You may find useful answers there.

The most useful is probably “don’t do that”; but since you want to do
that, you can probably use one “if” or multiple "map"s.

f

Francis D. [email protected]

On 10/28/2014 10:12 AM, Francis D. wrote:

The thread starting at can a map + regex be used to generate variables for YYYY-MM-DD-HH? is not
entirely dissimilar to this one. You may find useful answers there.
The most useful is probably “don’t do that”; but since you want to do
that, you can probably use one “if” or multiple "map"s. f
Thank you for your reply.

You mentioned multiple maps but why can’t it be done with a single one?

I managed to extract the year via

map $time_local $date {
    ~(?P<year>\d\d\d\d)     $year;
}

so this is much progress, but shouldn’t I be able to do something like

    ~(?P<day>\d\d\d)/(?P<month>\w\w\w)/(?P<year>\d\d\d\d)"

$year$month$day;

?

unfortunately that throws an error: unknown “year$month” variable

Thanks


Igal Sapir
Railo Core Developer

On 10/28/2014 10:18 AM, Igal @ getRailo.org wrote:

    ~(?P<day>\d\d\d)/(?P<month>\w\w\w)/(?P<year>\d\d\d\d)"

$year$month$day;

?

unfortunately that throws an error: unknown “year$month” variable

I ended up using 4 maps for now. If you have a better idea (without
resorting to external utilities) I’d love to hear it:

## $time_local is in the format: 28/Oct/2014:11:00:04 -0700
map $time_local $date_year {
    ~^\d\d/\w\w\w/(?P<substr>\d\d\d\d)     $substr;
}

map $time_local $date_month {
    ~^\d\d/(?P<substr>\w\w\w)              $substr;
}

map $time_local $date_day {
    ~^(?P<substr>\d\d)                     $substr;
}

map $date_month $date_month_numeric {
    Jan          1;
    Feb          2;
    Mar          3;
    Apr          4;
    May          5;
    Jun          6;
    Jul          7;
    Aug          8;
    Sep          9;
    Oct         10;
    Nov         11;
    Dec         12;

    default     $date_month;
}

access_log

logs/$host-access-$date_year$date_month_numeric$date_day.log
standard_log_format;


Igal Sapir
Railo Core Developer

rotatelogs.cmd

@echo off
::Parse the time variable into timeStamp
FOR /F “tokens=1-4 delims=/:., " %%J IN (”%time%“) DO SET
timeStamp=%%J%%K%%L
::Parse the date variable into dateStamp, YYYYMMDD
FOR /F “tokens=2-4 delims=/:.- " %%J IN (”%date%”) DO SET
dateStamp=%%L%%K%%J
set datename=%dateStamp%
::Parse the name again and get rid of the spaces
FOR /F “tokens=1-4” %%J IN (“%datename%”) DO SET datename=%%J%%K%%L
IF “%datename%”==“” set datename=EMPTY

cd /d x:\logs
FOR %%G IN (*.log) DO ren “%%G” “%datename%_%%G”

choice /t:y,5
cd /d c:\nginx
runas /savecred /env /user:nginxserviceuser “nginx -s reopen”
choice /t:y,5

cd /d x:\logs
move /y %datename%_. x:\archives\logdata

Posted at Nginx Forum: