2 * Copyright 2011 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
36 package gr.grnet.aquarium.util
38 import org.slf4j.Logger
39 import com.ckkloverdos.maybe.{Failed, Just, Maybe}
42 * A logger that keeps track of working context and indentation level.
44 * This is mostly useful in single-threaded debugging sessions.
46 * A sample output follows:
49 [DEBUG] 2012-02-13 12:54:53,653 main - doFullMonthlyBilling(2012-01) BEGIN
50 [DEBUG] 2012-02-13 12:54:53,653 main - findUserStateAtEndOfBillingMonth(2011-12) BEGIN
51 [DEBUG] 2012-02-13 12:54:53,661 main - findUserStateAtEndOfBillingMonth(2011-12) Found 0 out of sync events, will have to (re)compute user state
52 [DEBUG] 2012-02-13 12:54:53,661 main - findUserStateAtEndOfBillingMonth(2011-12) Computing full month billing
53 [DEBUG] 2012-02-13 12:54:53,662 main - doFullMonthlyBilling(2011-12) BEGIN
54 [DEBUG] 2012-02-13 12:54:53,662 main - findUserStateAtEndOfBillingMonth(2011-11) BEGIN
55 [DEBUG] 2012-02-13 12:54:53,663 main - findUserStateAtEndOfBillingMonth(2011-11) Found 0 out of sync events, will have to (re)compute user state
56 [DEBUG] 2012-02-13 12:54:53,663 main - findUserStateAtEndOfBillingMonth(2011-11) Computing full month billing
57 [DEBUG] 2012-02-13 12:54:53,664 main - doFullMonthlyBilling(2011-11) BEGIN
58 [DEBUG] 2012-02-13 12:54:53,664 main - findUserStateAtEndOfBillingMonth(2011-10) BEGIN
59 [DEBUG] 2012-02-13 12:54:53,667 main - findUserStateAtEndOfBillingMonth(2011-10) User did not exist before 2011-11-01 00:00:00.000. Returning UserState(Christos,0,0,false,null,ImplicitlyIssuedResourceEventsSnapshot(Map(),0),List(),List(),LatestResourceEventsSnapshot(Map(),0),0,ActiveStateSnapshot(false,0),CreditSnapshot(0.0,0),AgreementSnapshot(List(Agreement(default,0,-1)),0),RolesSnapshot(List(),0),OwnedResourcesSnapshot(List(),0))
60 [DEBUG] 2012-02-13 12:54:53,668 main - findUserStateAtEndOfBillingMonth(2011-10) END
61 [DEBUG] 2012-02-13 12:54:53,672 main - doFullMonthlyBilling(2011-11) previousResourceEvents = LatestResourceEventsWorker(Map())
62 [DEBUG] 2012-02-13 12:54:53,673 main - doFullMonthlyBilling(2011-11) theImplicitOFFs = ImplicitlyIssuedResourceEventsWorker(Map())
63 [DEBUG] 2012-02-13 12:54:53,680 main - doFullMonthlyBilling(2011-11) resourceEventStore = MemStore(Map(UserState -> 0, WalletEntry -> 0, ResourceEvent -> 5, PolicyEntry -> 0, UserEvent -> 0))
64 [DEBUG] 2012-02-13 12:54:53,681 main - doFullMonthlyBilling(2011-11) Found 0 resource events, starting processing...
65 [DEBUG] 2012-02-13 12:54:53,683 main - doFullMonthlyBilling(2011-11) END
66 [DEBUG] 2012-02-13 12:54:53,683 main - findUserStateAtEndOfBillingMonth(2011-11) END
67 [DEBUG] 2012-02-13 12:54:53,684 main - doFullMonthlyBilling(2011-12) previousResourceEvents = LatestResourceEventsWorker(Map())
68 [DEBUG] 2012-02-13 12:54:53,684 main - doFullMonthlyBilling(2011-12) theImplicitOFFs = ImplicitlyIssuedResourceEventsWorker(Map())
69 [DEBUG] 2012-02-13 12:54:53,685 main - doFullMonthlyBilling(2011-12) resourceEventStore = MemStore(Map(UserState -> 0, WalletEntry -> 0, ResourceEvent -> 5, PolicyEntry -> 0, UserEvent -> 0))
70 [DEBUG] 2012-02-13 12:54:53,686 main - doFullMonthlyBilling(2011-12) Found 0 resource events, starting processing...
71 [DEBUG] 2012-02-13 12:54:53,686 main - doFullMonthlyBilling(2011-12) END
72 [DEBUG] 2012-02-13 12:54:53,687 main - findUserStateAtEndOfBillingMonth(2011-12) END
73 [DEBUG] 2012-02-13 12:54:53,687 main - doFullMonthlyBilling(2012-01) previousResourceEvents = LatestResourceEventsWorker(Map())
74 [DEBUG] 2012-02-13 12:54:53,688 main - doFullMonthlyBilling(2012-01) theImplicitOFFs = ImplicitlyIssuedResourceEventsWorker(Map())
75 [DEBUG] 2012-02-13 12:54:53,688 main - doFullMonthlyBilling(2012-01) resourceEventStore = MemStore(Map(UserState -> 0, WalletEntry -> 0, ResourceEvent -> 5, PolicyEntry -> 0, UserEvent -> 0))
76 [DEBUG] 2012-02-13 12:54:53,689 main - doFullMonthlyBilling(2012-01) Found 4 resource events, starting processing...
77 [DEBUG] 2012-02-13 12:54:53,690 main - doFullMonthlyBilling(2012-01) Processing EVENT(2, [2012-01-01 03:00:00.000], 99.0 [MB/Hr], diskspace::pithos/diskspace/DISK.1, Map(), Christos, pithos)
78 [DEBUG] 2012-02-13 12:54:53,691 main - doFullMonthlyBilling(2012-01) 0 previousResourceEvents
79 [DEBUG] 2012-02-13 12:54:53,691 main - doFullMonthlyBilling(2012-01) 0 theImplicitOFFs
80 [DEBUG] 2012-02-13 12:54:53,694 main - doFullMonthlyBilling(2012-01) Processing: ResourceEvent(2,1325379600000,1325379600000,Christos,pithos,diskspace,pithos/diskspace/DISK.1,1.0,99.0,Map())
81 [DEBUG] 2012-02-13 12:54:53,704 main - doFullMonthlyBilling(2012-01) Processing EVENT(0, [2012-01-02 01:00:00.000], ON, vmtime::synnefo/vmtime/VM.1, Map(), Christos, synnefo)
82 [DEBUG] 2012-02-13 12:54:53,705 main - doFullMonthlyBilling(2012-01) 1 previousResourceEvents
83 [DEBUG] 2012-02-13 12:54:53,708 main - doFullMonthlyBilling(2012-01) EVENT(2, [2012-01-01 03:00:00.000], 99.0 [MB/Hr], diskspace::pithos/diskspace/DISK.1, Map(), Christos, pithos)
84 [DEBUG] 2012-02-13 12:54:53,709 main - doFullMonthlyBilling(2012-01) 0 theImplicitOFFs
85 [DEBUG] 2012-02-13 12:54:53,709 main - doFullMonthlyBilling(2012-01) Ignoring not billable EVENT(0, [2012-01-02 01:00:00.000], ON, vmtime::synnefo/vmtime/VM.1, Map(), Christos, synnefo)
86 [DEBUG] 2012-02-13 12:54:53,711 main - doFullMonthlyBilling(2012-01) Processing EVENT(3, [2012-01-02 04:00:00.000], 23.0 [MB/Hr], diskspace::pithos/diskspace/DISK.1, Map(), Christos, pithos)
87 [DEBUG] 2012-02-13 12:54:53,712 main - doFullMonthlyBilling(2012-01) 2 previousResourceEvents
88 [DEBUG] 2012-02-13 12:54:53,713 main - doFullMonthlyBilling(2012-01) EVENT(0, [2012-01-02 01:00:00.000], ON, vmtime::synnefo/vmtime/VM.1, Map(), Christos, synnefo)
89 [DEBUG] 2012-02-13 12:54:53,714 main - doFullMonthlyBilling(2012-01) EVENT(2, [2012-01-01 03:00:00.000], 99.0 [MB/Hr], diskspace::pithos/diskspace/DISK.1, Map(), Christos, pithos)
90 [DEBUG] 2012-02-13 12:54:53,714 main - doFullMonthlyBilling(2012-01) 0 theImplicitOFFs
91 [DEBUG] 2012-02-13 12:54:53,715 main - doFullMonthlyBilling(2012-01) Processing: ResourceEvent(3,1325469600000,1325469600000,Christos,pithos,diskspace,pithos/diskspace/DISK.1,1.0,23.0,Map())
92 [DEBUG] 2012-02-13 12:54:53,716 main - doFullMonthlyBilling(2012-01) Previous : ResourceEvent(2,1325379600000,1325379600000,Christos,pithos,diskspace,pithos/diskspace/DISK.1,1.0,99.0,Map())
93 [DEBUG] 2012-02-13 12:54:53,718 main - doFullMonthlyBilling(2012-01) Processing EVENT(1, [2012-01-02 10:00:00.000], OFF, vmtime::synnefo/vmtime/VM.1, Map(), Christos, synnefo)
94 [DEBUG] 2012-02-13 12:54:53,719 main - doFullMonthlyBilling(2012-01) 2 previousResourceEvents
95 [DEBUG] 2012-02-13 12:54:53,719 main - doFullMonthlyBilling(2012-01) EVENT(0, [2012-01-02 01:00:00.000], ON, vmtime::synnefo/vmtime/VM.1, Map(), Christos, synnefo)
96 [DEBUG] 2012-02-13 12:54:53,721 main - doFullMonthlyBilling(2012-01) EVENT(3, [2012-01-02 04:00:00.000], 23.0 [MB/Hr], diskspace::pithos/diskspace/DISK.1, Map(), Christos, pithos)
97 [DEBUG] 2012-02-13 12:54:53,721 main - doFullMonthlyBilling(2012-01) 0 theImplicitOFFs
98 [DEBUG] 2012-02-13 12:54:53,722 main - doFullMonthlyBilling(2012-01) Processing: ResourceEvent(1,1325491200000,1325491200000,Christos,synnefo,vmtime,synnefo/vmtime/VM.1,1.0,0.0,Map())
99 [DEBUG] 2012-02-13 12:54:53,735 main - doFullMonthlyBilling(2012-01) Previous : ResourceEvent(0,1325458800000,1325458800000,Christos,synnefo,vmtime,synnefo/vmtime/VM.1,1.0,1.0,Map())
100 [DEBUG] 2012-02-13 12:54:53,736 main - doFullMonthlyBilling(2012-01) END
103 * @author Christos KK Loverdos <loverdos@gmail.com>
105 final class ContextualLogger(val logger: Logger, fmt: String, args: Any*) {
106 val ctx = ContextualLogger.fixCtx(fmt.format(args:_*))
108 private[this] var _nesting = 0
110 private def nestMsg(fmt: String, args: Any*) = {
111 val msg = fmt.format(args: _*)
116 val buffer = new java.lang.StringBuilder(n + msg.size)
118 while(_i < (n * 2)) {
127 def isDebugEnabled = logger.isDebugEnabled
129 def nesting = _nesting
131 def indentAs(other: ContextualLogger): this.type = {
132 _nesting = other.nesting
136 def indent(): this.type = {
137 _nesting = _nesting + 1
141 def unindent(): this.type = {
142 _nesting = _nesting - 1
146 def withIndent[A](f: => A): Unit = {
147 import com.ckkloverdos.maybe.effect
149 effect(f){}{unindent()}
152 def debug(fmt: String, args: Any*): Unit = {
153 if(logger.isDebugEnabled) {
154 val msg = ctx + " " + nestMsg(fmt, args:_*)
159 def info(fmt: String, args: Any*): Unit = {
160 if(logger.isInfoEnabled) {
161 val msg = ctx + " " + nestMsg(fmt, args:_*)
166 def warn(fmt: String, args: Any*): Unit = {
167 if(logger.isWarnEnabled) {
168 val msg = ctx + " " + nestMsg(fmt, args:_*)
173 def error(fmt: String, args: Any*): Unit = {
174 if(logger.isErrorEnabled) {
175 val msg = ctx + " " + nestMsg(fmt, args:_*)
180 def error(t: Throwable, fmt: String, args: Any*): Unit = {
181 if(logger.isErrorEnabled) {
182 val msg = ctx + " " + nestMsg(fmt, args:_*)
187 def error(failed: Failed): Unit = {
188 this.error(failed.exception, "%s", failed.explanation)
191 def begin(): Unit = {
201 def endWith[A : Manifest](f: ⇒A): A = {
210 def debugMap[K, V](name: String, map: scala.collection.Map[K, V], limit: Int = 3): Unit = {
212 if(clog.isDebugEnabled) {
213 if(map.size < limit) {
214 clog.debug("%s = %s", name, map)
216 clog.debug("%s:", name)
219 clog.debug("%s: %s", k, v)
226 def debugSeq[T](name: String, seq: scala.collection.Seq[T], limit: Int = 3): Unit = {
227 if(this.isDebugEnabled) {
228 if(seq.lengthCompare(limit) <= 0) {
229 this.debug("%s = %s", name, seq)
231 this.debug("%s: ", name)
232 this.withIndent(seq.foreach(this.debug("%s", _)))
237 def debugSet[T](name: String, set: scala.collection.Set[T], limit: Int = 3): Unit = {
238 if(this.isDebugEnabled) {
239 if(set.size <= limit) {
240 this.debug("%s = %s", name, set)
242 this.debug("%s: ", name)
243 this.withIndent(set.foreach(this.debug("%s", _)))
250 * Companion object of [[gr.grnet.aquarium.util.ContextualLogger]].
252 * @author Christos KK Loverdos <loverdos@gmail.com>
254 object ContextualLogger {
255 final val MaxCtxLength = 40
256 final val ELLIPSIS = "…" // U+2026
258 def fixCtx(ctx: String): String = {
259 val ctxLen = ctx.length()
260 if(ctxLen == MaxCtxLength) {
262 } else if(ctxLen > MaxCtxLength) {
263 ELLIPSIS + ctx.substring(ctxLen - MaxCtxLength + 1, ctxLen)
265 val buffer = new java.lang.StringBuilder(MaxCtxLength)
266 val prefixLen = MaxCtxLength - ctxLen
268 while(_i < prefixLen) {
277 def fromOther(clogM: Maybe[ContextualLogger], logger: Logger, fmt: String, args: Any*): ContextualLogger = {
280 new ContextualLogger(clog.logger, fmt, args:_*).indentAs(clog)
282 new ContextualLogger(logger, fmt, args:_*)