精华内容
参与话题
问答
  • access.log

    2019-05-19 21:30:17
    nginx服务器访问日志,记录网站运营中比如空间的运营情况,被访问请求的记录。通过网站日志可以清楚的得知用户在什么IP、什么时间、用什么操作系统、什么浏览器、什么分辨率显示器的情况下访问了你网站的哪个页面,...
  • 资源一access.log

    2018-01-07 21:21:13
    资源一access.log资源一access.log资源一access.log资源一access.log
  • 日志-apache的access_log与error_log

    万次阅读 2017-02-17 20:47:28
    1. access_log 访问日志 access_log为访问日志,记录所有对apache服务器进行请求的访问,它的位置和内容由CustomLog指令控制,LogFormat指令可以用来简化该日志的内容和格式  2. error_log 错误日志 error_log为错误...
    1. access_log 访问日志
    access_log为访问日志,记录所有对apache服务器进行请求的访问,它的位置和内容由CustomLog指令控制,LogFormat指令可以用来简化该日志的内容和格式 

    2. error_log 错误日志
    error_log为错误日志,记录下任何错误的处理请求,它的位置和内容由ErrorLog指令控制,通常服务器出现什么错误,首先对它进行查阅,是一个最重要的日志文件


    通过apache配置文件,找到日志存放地址:
    find / -name "httpd.conf"
    找到配置文件地址,打开它,在里边找到apache的【访问日志】与【错误日志】存放地址

    sudo vi /private/etc/apache2/httpd.conf



    我的存放地址分别在:
    /private/var/log/apache2/error_log
    /private/var/log/apache2/access_log


    一。查看apache错误日志
    tail -f -30  "/private/var/log/apache2/error_log"

    [Fri Jan 13 14:32:52 2017] [error] [client 127.0.0.1] client denied by server configuration: /export/home/live/ap/htdocs/test
    第一项是错误发生的日期和时间;
    第二项是错误的严重性,LogLevel指令使只有高于指定严重性级别的错误才会被记录;
    第三项是导致错误的IP地址;
    此后是信息本身,在此例中,服务器拒绝了这个客户的访问。服务器在记录被访问文件时,用的是文件系统路径,而不是Web路径。
    错误日志中会包含类似上述例子的多种类型的信息。此外,CGI脚本中任何输出到stderr(标准错误)的信息会作为调试信息原封不动地记录到错误日志中。



    二。同样的,在apache配置文件里找到access_log存放地址
    tail -f -30  "/private/var/log/apache2/access_log"


    看一条典型的access_log的日志记录:
    61.155.149.20 - - [13/Jan/2017:15:42:47 +0800] "GET /category/db/ HTTP/1.1" 200 23225

    1).61.155.149.20 
    这是一个请求到apache服务器的客户端ip,默认的情况下,第一项信息只是远程主机的ip地址,但我们如果需要apache查出主机的名字,可以将 HostnameLookups设置为on,不推荐使用,会大大降低网站速度。

    2). - 
    这一项是空白,使用"-"来代替,用于记录浏览者的标识,对于大多数浏览器,这项都是空。

    3). - 
    也为空,记录浏览者进行身份验证时提供的名字,大多数这项也为空。

    4). [13/Jan/2017:15:42:47 +0800]
    第四项是记录请求的时间,格式为[day/month/year:hour:minute:second zone],最后的+0800表示服务器所处的时区为东八区

    5). "GET /category/db/ HTTP/1.1" 
    这一项最有用,首先,它告诉我们的服务器收到的是一个GET请求,其次,是客户端请求的资源路径,第三,客户端使用的协议时HTTP/1.1,整个格式为"%m %U%q %H",即"请求方法/访问路径/协议"

    6). 200 
    这是一个状态码,由服务器端发送回客户端,它告诉我们客户端的请求是否成功,或者是重定向,或者是碰到了什么样的错误,这项值为200,表示服务器已经成 功的响应了客户端的请求,一般来说,这项值以2开头的表示请求成功,以3开头的表示重定向,以4开头的标示客户端存在某些的错误,以5开头的标示服务器端 存在某些错误。

    7).23225 
    这项表示服务器向客户端发送了多少的字节,在日志分析统计的时侯,把这些字节加起来就可以得知服务器在某点时间内总的发送数据量是多少


    本文叙述的是apache下的两种日志访问nginx日志请点击

    php错误日志:检测php运行时或用户自记录错误日志:http://blog.csdn.net/ty_hf/article/details/55505262
    mysql慢日志:记录mysql服务器中影响性能的SQL:http://blog.csdn.net/ty_hf/article/details/55504172

    本文地址:http://blog.csdn.net/ty_hf/article/details/55504719

    展开全文
  • access.log日志记录与关闭

    万次阅读 2018-11-28 12:05:38
    服务器上日志access.log继续所有客户端请求的信息,不像error.log错误日志仅仅记录服务器报错信息, 有时由于服务器上的项目网页请求频繁(请求多),导致日志access.log容量增大,这时如果服务器容量足够大,那么...

    服务器上日志access.log继续所有客户端请求的信息,不像error.log错误日志仅仅记录服务器报错信息,
    有时由于服务器上的项目网页请求频繁(请求多),导致日志access.log容量增大,这时如果服务器容量足够大,那么服务器正常运行可能短期不会受到影响,但长期来看,还是需要定时去清理日志,此时,我们有两种方法来解决这个问题。
    1.设置定时脚本,对日志进行定时请清空。(建议选取用户访问少的时间进行清理)

      * 1 * * *  echo "" > /home/wwwlog/access.log   #每日凌晨1点清空日志


    2.关闭日志记录(此处只需关闭access.log日志,error.log最好开启,以便服务器出问题是及时通过错误日志查找原因)

    案例1

    案例2

     

    展开全文
  • Apache服务器access_log日志详解

    千次阅读 2018-05-22 11:29:21
    访问日志中会记录服务器...通用日志格式(Common Log Format)组合日志格式(Combined Log Format)多文件访问日志(条件日志此处不作介绍)Common Log Format:LogFormat "%h %l %u %t "%r" %>s ...


    访问日志中会记录服务器所处理的所有请求,其文件名和位置取决于CustomLog指令,LogFormat指令可以简化日志的内容。
    如何配置服务器的访问日志?
    通用日志格式(Common Log Format)组合日志格式(Combined Log Format)多文件访问日志(条件日志此处不作介绍)
    Common Log Format:
    LogFormat "%h %l %u %t "%r" %>s %b" common
    CustomLog logs/access_log common
    它定义了一种特定的记录格式字符串,并给它起了个别名叫 common,其中的"%"指示服务器用某种信息替换,其他字符则不作替换。引号(")必须加反斜杠转义,以避免被解释为字符串的结束。格式字符串还可以包含特殊的控制符,如换行符"n" 、制表符"t"。

    CustomLog
    指令建立一个使用指定别名的新日志文件,除非其文件名是以斜杠开头的绝对路径,否则其路径就是相对于ServerRoot的相对路径。

    上述配置是一种被称为通用日志格式(CLF)的记录格式,它被许多不同的Web服务器所采用,并被许多日志分析程序所识别,它产生的记录形如:
    127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
    记录的各部分说明如下:
    127.0.0.1(%h)
    这是发送请求到服务器的客户的IP地址。如果HostnameLookups设为On,则服务器会尝试解析这个IP地址的主机名并替换此处的IP地址,但并不推荐这样做,因为它会显著拖慢服务器,最好是用一个日志后续处理器来判断主机名,比如logresolve。如果客户和服务器之间存在代理,那么记录中的这个IP地址就是那个代理的IP地址,而不是客户机的真实IP地址。
    -(%l)
    这是由客户端identd进程判断的RFC1413身份(identity),输出中的符号"-"表示此处的信息无效。除非在严格控制的内部网络中,此信息通常很不可靠,不应该被使用。只有在将IdentityCheck指令设为On时,Apache才会试图得到这项信息。
    frank(%u)
    这是HTTP认证系统得到的访问该网页的客户标识(userid),环境变量REMOTE_USER会被设为该值并提供给CGI脚本。如果状态码是401,表示客户未通过认证,则此值没有意义。如果网页没有设置密码保护,则此项将是"-"。
    [10/Oct/2000:13:55:36 -0700](%t)
    这是服务器完成请求处理时的时间,其格式是:
    [日/月/年:时:分:秒 时区]
    日= 2数字
    月= 3字母
    年= 4数字
    时= 2数字
    分= 2数字
    秒= 2数字
    时区= (+|-)4数字
    可以在格式字符串中使用%{format}t来改变时间的输出形式,其中的format与C标准库中的strftime()用法相同。
    "GET /apache_pb.gif HTTP/1.0"("%r")
    引号中是客户端发出的包含许多有用信息的请求行。可以看出,该客户的动作是GET,请求的资源是/apache_pb.gif,使用的协议是HTTP/1.0。另外,还可以记录其他信息,如:格式字符串"%m %U %q %H"会记录动作(方法)、路径、查询字符串、协议,其输出和"%r"一样。
    200(%>s)
    这是服务器返回给客户端的状态码。这个信息非常有价值,因为它指示了请求的结果,或者是被成功响应了(以2开头),或者被重定向了(以3开头),或者出错了(以4开头),或者产生了服务器端错误(以5开头)。完整的状态码列表参见HTTP规范(RFC2616第10章)。
    2326(%b)
    最后这项是返回给客户端的不包括响应头的字节数。如果没有信息返回,则此项应该是"-",如果希望记录为"0"的形式,就应该用%B。
    Combined Log Format:
    LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"" combined
    CustomLog log/access_log combined
    这种格式与通用日志格式类似,但是多了两个 %{header}i 项,其中的header可以是任何请求头。这种格式的记录形如:
    127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"
    其中,多出来的项是:
    "http://www.example.com/start.html" ("%{Referer}i")
    "Referer"请求头。此项指明了该请求是被从哪个网页提交过来的,这个网页应该包含有/apache_pb.gif或者其连接。
    "Mozilla/4.08 [en] (Win98; I ;Nav)" ("%{User-agent}i")
    "User-Agent"请求头。此项是客户端提供的浏览器识别信息。
    多文件访问日志
    可以简单地在配置文件中用多个CustomLog指令来建立多文件访问日志。如下例,既记录基本的CLF信息,又记录提交网页和浏览器的信息,最后两行CustomLog示范了如何模拟ReferLog和AgentLog指令的效果。
    LogFormat "%h %l %u %t "%r" %>s %b" common
    CustomLog logs/access_log common
    CustomLog logs/referer_log "%{Referer}i -> %U"
    CustomLog logs/agent_log "%{User-agent}i"
    此例也说明了,记录格式可以直接由CustomLog指定,而并不一定要用LogFormat起一个别名(相当于上面第一二行组合,即:CustomLog logs/access_log "%h %l %u %t "%r" %>s %b")。
    这里需要提到的是 关于多个虚拟机之间的日记记录管理:
    如果服务器配有若干虚拟主机,那么还有几个控制日志文件的功能。首先,可以把日志指令放在<VirtualHost>段之外,让它们与主服务器使用同一个访问日志和错误日志来记录所有的请求和错误,但是这样就不能方便的获得每个虚拟主机的信息了。
    如果把CustomLog或ErrorLog指令放在<VirtualHost>段内,所有对这个虚拟主机的请求和错误信息会被记录在其私有的日志文件中,那些没有在<VirtualHost>段内使用日志指令的虚拟主机将仍然和主服务器使用同一个日志。这种方法对虚拟主机较少的服务器很有用,但虚拟主机非常多时,就会带来管理上的困难,还经常会产生文件描述符短缺的问题。
    对于访问日志,有一个很好的折衷方案,在同一个访问日志文件中记录对所有主机的访问,而每条记录都注明虚拟主机的信息,日后再把记录拆开存入不同的文件。例如:
    LogFormat "%v %l %u %t "%r" %>s %b" comonvhost
    CustomLog logs/access_log comonvhost
    %v用来附加虚拟主机的信息。
    有个split-logfile程序可以根据不同的虚拟主机信息对日志进行拆分,并将结果存入不同的文件。

    展开全文
  • 本文将详细分析Dubbo accesslog实现原理。    AccessLogFilter概述 过滤器作用 记录调用日志。 使用场景 记录服务提供者端调用日志。 阻断条件 非阻断过滤器。    接下来源码分析accesslog参数...

       谈到服务调用日志,大家恐怕第一想到就是如果开启了这个参数,会影响性能。那真实的情况是怎么样了?性能损耗到底有多大呢?在实践中我们如何使用该功能呢?本文将详细分析Dubbo accesslog实现原理。
       AccessLogFilter概述

    • 过滤器作用
      记录调用日志。
    • 使用场景
      记录服务提供者端调用日志。
    • 阻断条件
      非阻断过滤器。

       接下来源码分析accesslog参数的实现原理。
    这里写图片描述
    1、核心字段说明

    • LOG_MAX_BUFFER:积累最大的日志容量,默认为5000条,如果积压在队列中的待处理日志超过该值,则直接丢弃。
    • LOG_OUTPUT_INTERVAL:日志写出的调度频率,默认为5s。
    • ConcurrentMap< String, Set< String>> logQueue:日志容器。
    • ScheduledExecutorService logScheduled:写出日志调度器,默认为2个线程,线程名称为:Dubbo-Access-Log。

    2、invoke方法源码分析
       AccessLogFilter#invoke

    public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
            try {
                String accesslog = invoker.getUrl().getParameter(Constants.ACCESS_LOG_KEY);    
                if (ConfigUtils.isNotEmpty(accesslog)) {    // @1                                                       
                    RpcContext context = RpcContext.getContext();
                    String serviceName = invoker.getInterface().getName();
                    String version = invoker.getUrl().getParameter(Constants.VERSION_KEY);
                    String group = invoker.getUrl().getParameter(Constants.GROUP_KEY);
                    StringBuilder sn = new StringBuilder();         // @2 start
                    sn.append("[").append(new SimpleDateFormat(MESSAGE_DATE_FORMAT).format(new Date())).append("] 
                           ").append(context.getRemoteHost()).append(":").append(context.getRemotePort())
                            .append(" -> ").append(context.getLocalHost()).append(":").append(context.getLocalPort())
                            .append(" - ");
                    if (null != group && group.length() > 0) {
                        sn.append(group).append("/");
                    }
                    sn.append(serviceName);
                    if (null != version && version.length() > 0) {
                        sn.append(":").append(version);
                    }
                    sn.append(" ");
                    sn.append(inv.getMethodName());
                    sn.append("(");
                    Class<?>[] types = inv.getParameterTypes();
                    if (types != null && types.length > 0) {
                        boolean first = true;
                        for (Class<?> type : types) {
                            if (first) {
                                first = false;
                            } else {
                                sn.append(",");
                            }
                            sn.append(type.getName());
                        }
                    }
                    sn.append(") ");
                    Object[] args = inv.getArguments();
                    if (args != null && args.length > 0) {
                        sn.append(JSON.toJSONString(args));
                    }
                    String msg = sn.toString();
                    if (ConfigUtils.isDefault(accesslog)) {         // @2
                        LoggerFactory.getLogger(ACCESS_LOG_KEY + "." + invoker.getInterface().getName()).info(msg);
                    } else {
                        log(accesslog, msg);                              // @3
                    }
                }
            } catch (Throwable t) {
                logger.warn("Exception in AcessLogFilter of service(" + invoker + " -> " + inv + ")", t);
            }
            return invoker.invoke(inv);                                 // @4
        }
    

       代码@1:首先从服务提供者URL中获取accesslog参数,如果存在该参数并且不为空,则进入服务调用日志,如果未配置,则直接进入下一个过滤器。
       代码@2:组装服务调用日志,其内容:
    [服务调用时间,精确到时分秒] + 消费者IP:消费者PORT + --> 服务提供者IP:服务提供者端口 + “服务提供者group/”(可选) + serviceName(interface name) + “:version”(可选) + methodName( + 参数类型列表)+ 参数值(json格式的字符串) 。
       代码@3:如果accesslog=“true”,则使用info级别的日志输出;如果是配置的是日志路径的话,则异步写入文件。
       接下来分析一下log方法,写入日志文件的具体实现:
       AccessLogFilter#log

    private void log(String accesslog, String logmessage) {
            init();     														// @1
            Set<String> logSet = logQueue.get(accesslog);                                            // @2 start
            if (logSet == null) {
                logQueue.putIfAbsent(accesslog, new ConcurrentHashSet<String>());
                logSet = logQueue.get(accesslog);
            }
            if (logSet.size() < LOG_MAX_BUFFER) {                                                   // @2 end
                logSet.add(logmessage);
            }
        }
    

       代码@1:授权通过init方法启动定时任务,已间隔5s,延迟5s后执行第一次调度,具体的任务实现为LogTask。

    private void init() {
            if (logFuture == null) {
                synchronized (logScheduled) {
                    if (logFuture == null) {
                        logFuture = logScheduled.scheduleWithFixedDelay(new LogTask(), LOG_OUTPUT_INTERVAL, LOG_OUTPUT_INTERVAL, 
                               TimeUnit.MILLISECONDS);
                    }
                }
            }
        }
    

       代码@2:以文件路径名accesslog为键,从logQueue中获取,如果当前处理的长度大于LOG_MAX_BUFFER固定为5000条,则丢弃。由于存储日志的容器为ConcurrentHashSet,则日志记录是乱序的。
       具体异步记录日志的任务实现为AccessLogFilter$LogTask。

    private class LogTask implements Runnable {
            @Override
            public void run() {
                try {
                    if (logQueue != null && logQueue.size() > 0) {
                        for (Map.Entry<String, Set<String>> entry : logQueue.entrySet()) {
                            try {
                                String accesslog = entry.getKey();
                                Set<String> logSet = entry.getValue();
                                File file = new File(accesslog);              
                                File dir = file.getParentFile();  
                                if (null != dir && !dir.exists()) {
                                    dir.mkdirs();
                                }     // @1
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Append log to " + accesslog);
                                }
                                if (file.exists()) {    // @2
                                    String now = new SimpleDateFormat(FILE_DATE_FORMAT).format(new Date());
                                    String last = new SimpleDateFormat(FILE_DATE_FORMAT).format(new Date(file.lastModified()));
                                    if (!now.equals(last)) {
                                        File archive = new File(file.getAbsolutePath() + "." + last);
                                        file.renameTo(archive);
                                    }
                                }
                                FileWriter writer = new FileWriter(file, true);
                                try {
                                    for (Iterator<String> iterator = logSet.iterator();
                                         iterator.hasNext();
                                         iterator.remove()) {
                                        writer.write(iterator.next());
                                        writer.write("\r\n");
                                    }
                                    writer.flush();
                                } finally {
                                    writer.close();
                                }
                            } catch (Exception e) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
    

       代码@1:从这里可以看出accesslog配置的是具体的日志文件全路径,例如d:/logs/accesslog.log。
       代码@2:如果文件存在,则需要判断该文件的最后修改时间与当前日期是否相同,如果不同,则首先将文件重新命名为前一天的日期,然后再创建一个新的accesslog文件,也就是accesslog文件的布局是一天一个文件。

       accesslog 调用日志记录就分析到这里,我们思考一下开启该参数对服务提供者的性能影响。
       1、accesslog=“true”,其实现为通过log4j等日志组件,使用info级别将调用日志输出,该方法对服务调用者的影响还是比较大,不建议这样使用。
       2、accesslog=“日志文件路径”,该方式,dubbo使用的是异步记录日志的方式,开启额外的信息,主要是需要组织日志内容,耗费一定的CPU资源,但对服务的响应整体性能损耗还是不会起到恶劣的影响。默认情况下,还是不建议开启,但是如果线上服务器有BUG,需要通过调用日志来拍错的话,也可以在不重启服务提供者的情况下开启,开启方法利用Dubbo的配置覆盖机制,该部分的内容详情请参考作者的另一篇博客:源码分析Dubbo配置规则机制(override协议):https://blog.csdn.net/prestigeding/article/details/80795708 。


    欢迎加笔者微信号(dingwpmz),加群探讨,笔者优质专栏目录:
    1、源码分析RocketMQ专栏(40篇+)
    2、源码分析Sentinel专栏(12篇+)
    3、源码分析Dubbo专栏(28篇+)
    4、源码分析Mybatis专栏
    5、源码分析Netty专栏(18篇+)
    6、源码分析JUC专栏
    7、源码分析Elasticjob专栏
    8、Elasticsearch专栏(20篇+)
    9、源码分析MyCat专栏

    展开全文
  • Springboot项目配置 access log日志文件

    千次阅读 2018-01-19 16:22:30
    原文地址:https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#howto-configure-accesslogs73.6 Configure Access LoggingAccess logs can be configured for Tomcat and Undertow via ...
  • tomcat Access Log 统计相应时间

    万次阅读 2012-08-10 14:16:39
    Access Log Valve用来创建日志文件,格式与标准的web server日志文件相同。可以使用用日志分析工具对日志进行分析,跟踪页面点击次数、用户会话的活动等。Access Log Valve的很多配置和行为特性与File Logger相同,...
  • 为什么80%的码农都做不了架构师?>>> ...
  • resin access log 格式

    千次阅读 2011-08-30 10:37:24
    The access log formatting variables follow the Apache variables:     %b result content length %D time taken to complet
  • 以前spring项目是扔到tomcat里面去部署的,我们可以直接去tomcat放access日志的地方查看,现在springboot项目,tomcat是内嵌到框架里面的,这时候我们就需要在项目的配置文件application.yml里面来配置tomcat的日志...
  • springboot中配置tomcat的access log

    千次阅读 2018-01-19 16:10:41
    在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP、线程号、访问url、返回状态码、...在Spring boot中使用了内嵌的tomcat,可以通过server.tomcat.accesslog配置tomcat 的access日志,
  • tomcat Access Log 统计相应时间

    千次阅读 2015-02-04 13:53:24
    Access Log Valve用来创建日志文件,格式与标准的web server日志文件相同。可以使用用日志分析工具对日志进行分析,跟踪页面点击次数、用户会话的活动等。Access Log Valve的很多配置和行为特性与File Logger相同,...
  • server: port: 8083 tomcat: max-connections: 500 max-threads: 500 accesslog: enabled: true directory: logs/access/ prefix: access_log suffix: .log file-date-format: .yyyy-MM-dd ...
  • Tomcat的access log的设置

    万次阅读 2011-11-28 16:40:53
    Tomcat中默认的情况下,access log是没有设置的。在server.xml文件中配置如下。 <!-- Access log processes all example. Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache
  • springboot中配置tomcat的access log

    千次阅读 2018-08-15 15:11:39
    在tomcat的access中打印出请求的情况可以帮助我们...在Spring boot中使用了内嵌的tomcat,可以通过server.tomcat.accesslog配置tomcat 的access日志,这里就以Spring boot 1.5.3为例。 server.tomcat.accesslog....
  • Tomcat中的Access Log,缺省存放在logs目录下。这个目录会越来越大,如果访问量大的话,很快就会把硬盘挤满。 解决的方法有两种: 不要记录Access Log:注释掉server.xml中的配置项把Access log存放到其他地方,...
  • 在 gunicorn 的配置文件中,有 accesslog 和 errorlog 两项,分别用来记录接口的访问历史和服务启动以及错误消息。 假设有部分配置文件如下: loglevel = 'info' accesslog = "log/gunicorn_access.log" errorlog = ...
  • JBoss Access log的配置

    千次阅读 2013-08-15 15:48:14
    JBoss Access log的配置 在做WEB应用时,有时候希望能够记录用户的访问,分析访问用户的地域以及用户访问行为,JBoss提供了一种方式能够很方便的记录用户的访问日志,但是默认情况下这个功能是没有启用的,下面讲述...
  • Tomcat中默认的情况下,access log是没有设置的。在server.xml文件中配置如下。 [html] view plain copy  print?  Documentation at: /docs/config/valve.html -->     Valve classNam

空空如也

1 2 3 4 5 ... 20
收藏数 375,142
精华内容 150,056
关键字:

accesslog