Skip to content

Commit

Permalink
Issue #23: structured context.
Browse files Browse the repository at this point in the history
  • Loading branch information
fgm committed Sep 21, 2017
1 parent 860254b commit 13f5f64
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 111 deletions.
12 changes: 12 additions & 0 deletions doc/dic_example/filog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,34 @@ services:

filog.client.sender.console:
class: 'ConsoleSender'
public: false

filog.client.sender.meteor_http_client:
class: 'MeteorHttpClientSender'
public: false

filog.client.processor.browser:
class: 'BrowserProcessor',
public: false

filog.client.processor.routing:
class: 'RoutingProcessor'
public: false

filog.client.processor.meteor_user:
class: 'MeteorUserProcessor'
arguments: ['@Meteor']
public: false

filog.client.sender:
class: 'TeeSender'
arguments: ['@filog.client.sender.console', '@filog.client.meteor_http_client']
public: false

filog.client.strategy:
class: 'TrivialStrategy'
arguments: ['@filog.client.sender']
public: false

logger.client:
class: 'ClientLogger'
Expand All @@ -50,22 +57,27 @@ services:
filog.server.sender.mongo:
class: 'MongodbSender'
arguments: ['@Mongo', '%filog.mongo.collection%']
public: false

filog.server.sender.syslog:
class: 'SyslogSender'
arguments: [ '%filog.syslog.facility%', null, null, null, [ depth: '%filog.syslog.depth%' ] ]
public: false

filog.server.sender:
class: 'TeeSender'
arguments: ['@filog.server.sender.mongo', '@filog.server.sender.syslog']
public: false

filog.server.strategy:
class: 'TrivialStrategy'
arguments: ['@filog.server.sender', '@Webapp']
public: false

filog.server.processor.meteor_user:
class: 'MeteorUserProcessor'
arguments: ['@Meteor']
public: false

logger.server:
class: 'ServerLogger'
Expand Down
111 changes: 58 additions & 53 deletions doc/logger.dot
Original file line number Diff line number Diff line change
@@ -1,88 +1,92 @@
digraph logger {
rankdir = LR;
node [ shape="octagon", color="#c0c0c0" ];
Client;
Server;
Client [ label="Client app"];
Server [ label="Server app"];

node [ shape="record", color="#c0c0c0" ];

subgraph cluster_loggers {
label = "Loggers\nProvide a way for the application to emit messages";

ClientLogger;
Logger [ label="<label>Logger|<processors>\{ProcessorBase[]\} processors|<strategy>\{StrategyBase\} strategy|<constructor>construct(strategy)|log(level, msg, ctx)|debug(msg, ctx)|info(msg, ctx)|warn(msg, ctx)|error(msg, ctx)|<levelName>levelName(level): string"];
ServerLogger;
}

subgraph cluster_processors {
label = "Processors\nModify messages";
BrowserProcessor;
MeteorUserProcessor;
ProcessorBase;

BrowserProcessor;
MeteorUserProcessor;
ProcessorBase [ label="<label>ProcessorBase|process(Object context): Object|getTrustedKeys(): String[]"];
RoutingProcessor;
}

subgraph cluster_senders {
label = "Senders\nTransmit messages somewhere";

ConsoleSender [ label="ConsoleSender\nDisplays on console" ];
MeteorClientHttpSender [ label="MeteorClientHttpSender\nPOSTs to Meteor server" ];
MongodbSender [ label="MongodbSender\nStores in MongoDB" ];
NullSender [ label="NullSender\nDrops everything." ];
SenderBase;
MeteorClientHttpSender [ label="MeteorClientHttpSender\n[C]POSTs to Meteor server" ];
MongodbSender [ label="MongodbSender\n[S]Stores in MongoDB" ];
NullSender [ label="NullSender\nDrops everything" ];
SyslogSender [ label="SyslogSender\n[C] Local syslog" ];
SenderBase [ label="<label>SenderBase|constructor(ProcessorBase[] processors)|send(level, message, context): context" ];
}

subgraph cluster_strategies {
label = "Strategies\nConfigure message sending and processing";

LeveledStrategy [ label="<label>LeveledStrategy|<constructor>construct(init = true)" ];
StrategyBase [ label="<label>StrategyBase|<constructor>construct(low, mid, high, minLow, maxHigh)|<customize>customizeLogger()|<select>selectSenders(level, msg, ctx)" ];
}

subgraph cluster_loggers {
label = "Loggers\nProvide a way for the application to emit messages";

ClientLogger;
Logger [ label="<label>Logger|<processors>\{ProcessorBase[]\} processors|<strategy>\{StrategyBase\} strategy|<constructor>construct(strategy)|log(level, msg, ctx)|debug(msg, ctx)|info(msg, ctx)|warn(msg, ctx)|error(msg, ctx)"];
ServerLogger;

LeveledStrategy [ label="<label>LeveledStrategy" ];
StrategyBase [ label="<label>StrategyBase|<constructor>constructor(init = true)|<customize>customizeLogger(logger)|<customizeSenders>customizeSenders(processorKeys = []|<select>selectSenders(level, msg, ctx))" ];
TrivialStrategy [ label="<label>TrivialStrategy" ];
}
LogLevel [ label="LogLevel\nLevel names and values" ];

LogLevel [ label="<label>LogLevel\nLevel names and values|<names>Names" ];

// Misc relations
// Instantiation.
edge [ color="#2030c0:#2030c0:#2030c0" ];
edge [ color="#2030c0:#80a0ff:#2030c0" ];
Client -> ClientLogger;
Client -> ProcessorBase;
Client -> SenderBase;
Client -> StrategyBase;

Server -> ProcessorBase:s;
Server -> SenderBase;
Server -> ServerLogger;
Server -> StrategyBase;

// Inheritance
edge [ color="#ffbb88::invis:#ffbb88" ];

BrowserProcessor -> ProcessorBase;
MeteorUserProcessor -> ProcessorBase;
RoutingProcessor -> ProcessorBase;

ConsoleSender -> SenderBase;
MeteorClientHttpSender -> SenderBase;
MongodbSender -> SenderBase;
NullSender -> SenderBase;

LeveledStrategy -> StrategyBase;

edge [ color="#ff6633:#ffbb88:#ff6633" ];

BrowserProcessor -> ProcessorBase:label;
MeteorUserProcessor -> ProcessorBase:label;
RoutingProcessor -> ProcessorBase:label;

ConsoleSender -> SenderBase:label;
MeteorClientHttpSender -> SenderBase:label;
MongodbSender -> SenderBase:label;
NullSender -> SenderBase:label;
SyslogSender -> SenderBase:label;

LeveledStrategy -> StrategyBase:label;
TrivialStrategy -> StrategyBase:label;

ClientLogger -> Logger:label;
ServerLogger -> Logger:label;

// Dependency.
// Dependency.
edge [ color="#c0c0c0" ];
// ClientLogger -> LogLevel;
// ServerLogger -> LogLevel;
ClientLogger -> LogLevel;
ServerLogger -> LogLevel;

// ConsoleSender -> LogLevel;
// LeveledStrategy -> LogLevel;
// Logger -> LogLevel;
ConsoleSender -> LogLevel:names;
LeveledStrategy -> LogLevel:label;
Logger:levelName -> LogLevel:names;
Logger:processors -> ProcessorBase;
Logger:strategy -> StrategyBase:label;

LeveledStrategy:constructor -> SenderBase;
StrategyBase -> Logger:label;
StrategyBase:constructor -> SenderBase;
Expand All @@ -94,13 +98,14 @@ digraph logger {
// Mutates
edge [ color="red" ];
StrategyBase:customize -> Logger:label;
StrategyBase:customizeSenders -> SenderBase:label;

subgraph cluster_caption {
subgraph cluster_caption {
label = "Legend";
rank = sink;
style = invis;
node [shape=plaintext]

key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
<tr><td align="right" port="i1">constructs</td></tr>
<tr><td align="right" port="i2">inherits</td></tr>
Expand All @@ -116,7 +121,7 @@ digraph logger {
<tr><td port="i5">&nbsp;</td></tr>
</table>>]
key:i1:e -> key2:i1:w [color="#2030c0:#2030c0:#2030c0"];
key:i2:e -> key2:i2:w [color="#ffbb88:invis:#ffbb88"];
key:i2:e -> key2:i2:w [color="#ff6633:#ffbb88:#ff6633"];
key:i3:e -> key2:i3:w [color=limegreen];
key:i4:e -> key2:i4:w [color=red];
key:i5:e -> key2:i5:w [color="#c0c0c0"];
Expand Down
19 changes: 15 additions & 4 deletions src/Logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,27 @@ const Logger = class {
/**
* @constructor
*
* The forced 'timestamp' processorKey is needed because it is forcefully
* inserted during Logger.log().
*
* @see Logger#log
*
* @param {StrategyBase} strategy
* The sender selection strategy to apply.
* @param {ProcessorBase[]} processors
* An array of processor instances.
*
* @property {StrategyBase} strategy
*/
constructor(strategy, processors = []) {
this.processors = processors;
this.processorKeys = processors.reduce((accu, processor) => {
return [...accu, ...processor.getTrustedKeys()];
}, ['timestamp']);
this.strategy = strategy;
this.tk = TraceKit;
this.strategy.customizeLogger(this);
this.strategy.customizeSenders(this.processorKeys);
}

/**
Expand Down Expand Up @@ -163,17 +174,17 @@ const Logger = class {
throw new InvalidArgumentException("The level argument to log() must be an RFC5424 level.");
}

const cloned = Object.assign({}, rawContext);
const context = cooked
? this.processors.reduce(this.processorReducer, rawContext)
: rawContext;
? this.processors.reduce(this.processorReducer, cloned)
: cloned;

// A timestamp is required, so insert it forcefully.
context.timestamp = { log: Date.now() };

const senders = this.strategy.selectSenders(level, message, context);
console.log("senders", senders);
senders.forEach(sender => {
sender.send(level, message, context, this.formatOptions);
sender.send(level, message, context);
});
}

Expand Down
5 changes: 2 additions & 3 deletions src/Senders/MongodbSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const MongodbSender = class extends SenderBase {
* Optional : The options used to format the message (default to { depth: 5 }).
*/
constructor(processors = [], mongo, collection = "logger", formatOptions = null) {
console.log("Monfo sender", processors);
super(processors);
if (collection instanceof mongo.Collection) {
this.store = collection;
Expand Down Expand Up @@ -81,8 +80,8 @@ const MongodbSender = class extends SenderBase {
let cloned = Object.assign({}, context);
let trusted = {};
this.processorKeys.forEach((value, index) => {
trusted[index] = cloned[index];
delete cloned[index];
trusted[value] = cloned[value];
delete cloned[value];
});
const result = Object.assign(trusted, {
serialized: JSON.stringify(cloned)
Expand Down
13 changes: 6 additions & 7 deletions src/Senders/SenderBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@ const SenderBase = class {
this.processorKeys = processors.reduce((accu, processor) => {
return [...accu, ...processor.getTrustedKeys()];
}, []);
console.log("SBC", processors, this.processorKeys);
}

/**
* Getter.
*
* @returns {ProcessorBase[]}
* The array of processors for this sender.
* @returns {String[]}
* The array of processor keys for this sender.
*/
getProcessors() {
return this.processors;
getProcessorKeys() {
return this.processorKeys;
}

/**
Expand Down Expand Up @@ -76,8 +75,8 @@ const SenderBase = class {
* long-term storage, to ease searching on them: it is up to the sender to
* decide how to handle them.
*
* @param {Array} keys
* An array of strings.
* @param {string[]} keys
* An array of keys.
*
* @returns {void}
*/
Expand Down
1 change: 0 additions & 1 deletion src/Senders/SyslogSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const SyslogSender = class extends SenderBase {
* Optional : The options used to format the message (default to { depth: 5 }).
*/
constructor(processors = [], ident = null, syslogOptions = null, syslogFacility = null, syslog = null, formatOptions = null) {
console.log("syslog sender", processors);
super(processors);
const programName = path.basename(process.argv[1]);
const actualIdent = ident || programName;
Expand Down
18 changes: 17 additions & 1 deletion src/Senders/TeeSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const TeeSender = class extends SenderBase {
* An array of senders to which to send the input.
*/
constructor(processors = [], senders) {
console.log("Tee sender", processors);
super(processors);
this.senders = senders;
}
Expand All @@ -30,6 +29,23 @@ const TeeSender = class extends SenderBase {
this.senders.map(sender => sender.send(level, message, processedContext));
return processedContext;
}

/**
* {@inheritDoc}
*
* The tee sender needs to propagate the keys it receives to its children.
*
* @param {string[]} processorKeys
* An array of keys.
*
* @returns {void}
*/
setProcessorKeys(processorKeys) {
this.processorKeys = processorKeys;
this.senders.forEach((sender) => {
sender.setProcessorKeys([...new Set([...sender.getProcessorKeys(), ...processorKeys])]);
});
}
};

export default TeeSender;
Loading

0 comments on commit 13f5f64

Please sign in to comment.