{"action":"created","issue":{"url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/1371","repository_url":"https://api.github.com/repos/census-instrumentation/opencensus-java","labels_url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/1371/labels{/name}","comments_url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/1371/comments","events_url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/1371/events","html_url":"https://github.com/census-instrumentation/opencensus-java/pull/1371","id":351454275,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA5MDQzNzMw","number":1371,"title":"Start adding log correlation for Log4j.","user":{"login":"sebright","id":19807615,"node_id":"MDQ6VXNlcjE5ODA3NjE1","avatar_url":"https://avatars0.githubusercontent.com/u/19807615?v=4","gravatar_id":"","url":"https://api.github.com/users/sebright","html_url":"https://github.com/sebright","followers_url":"https://api.github.com/users/sebright/followers","following_url":"https://api.github.com/users/sebright/following{/other_user}","gists_url":"https://api.github.com/users/sebright/gists{/gist_id}","starred_url":"https://api.github.com/users/sebright/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebright/subscriptions","organizations_url":"https://api.github.com/users/sebright/orgs","repos_url":"https://api.github.com/users/sebright/repos","events_url":"https://api.github.com/users/sebright/events{/privacy}","received_events_url":"https://api.github.com/users/sebright/received_events","type":"User","site_admin":false},"labels":[{"id":616301408,"node_id":"MDU6TGFiZWw2MTYzMDE0MDg=","url":"https://api.github.com/repos/census-instrumentation/opencensus-java/labels/cla:%20yes","name":"cla: yes","color":"0e8a16","default":false},{"id":566180166,"node_id":"MDU6TGFiZWw1NjYxODAxNjY=","url":"https://api.github.com/repos/census-instrumentation/opencensus-java/labels/tracing","name":"tracing","color":"006b75","default":false}],"state":"closed","locked":false,"assignee":{"login":"g-easy","id":29616524,"node_id":"MDQ6VXNlcjI5NjE2NTI0","avatar_url":"https://avatars1.githubusercontent.com/u/29616524?v=4","gravatar_id":"","url":"https://api.github.com/users/g-easy","html_url":"https://github.com/g-easy","followers_url":"https://api.github.com/users/g-easy/followers","following_url":"https://api.github.com/users/g-easy/following{/other_user}","gists_url":"https://api.github.com/users/g-easy/gists{/gist_id}","starred_url":"https://api.github.com/users/g-easy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/g-easy/subscriptions","organizations_url":"https://api.github.com/users/g-easy/orgs","repos_url":"https://api.github.com/users/g-easy/repos","events_url":"https://api.github.com/users/g-easy/events{/privacy}","received_events_url":"https://api.github.com/users/g-easy/received_events","type":"User","site_admin":false},"assignees":[{"login":"g-easy","id":29616524,"node_id":"MDQ6VXNlcjI5NjE2NTI0","avatar_url":"https://avatars1.githubusercontent.com/u/29616524?v=4","gravatar_id":"","url":"https://api.github.com/users/g-easy","html_url":"https://github.com/g-easy","followers_url":"https://api.github.com/users/g-easy/followers","following_url":"https://api.github.com/users/g-easy/following{/other_user}","gists_url":"https://api.github.com/users/g-easy/gists{/gist_id}","starred_url":"https://api.github.com/users/g-easy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/g-easy/subscriptions","organizations_url":"https://api.github.com/users/g-easy/orgs","repos_url":"https://api.github.com/users/g-easy/repos","events_url":"https://api.github.com/users/g-easy/events{/privacy}","received_events_url":"https://api.github.com/users/g-easy/received_events","type":"User","site_admin":false}],"milestone":null,"comments":8,"created_at":"2018-08-17T04:37:56Z","updated_at":"2018-08-27T16:51:00Z","closed_at":"2018-08-27T16:49:06Z","author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/census-instrumentation/opencensus-java/pulls/1371","html_url":"https://github.com/census-instrumentation/opencensus-java/pull/1371","diff_url":"https://github.com/census-instrumentation/opencensus-java/pull/1371.diff","patch_url":"https://github.com/census-instrumentation/opencensus-java/pull/1371.patch"},"body":"This commit takes the approach of implementing Log4j's ContextDataInjector.  It\r\ninserts three keys into each log event: \"`openCensusTraceId`\", \"`openCensusSpanId`\",\r\nand \"`openCensusTraceSampled`\".  The tracing data can be accessed with\r\nLogEvent.getContextData() or included in a layout.  See\r\nhttps://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/ContextDataInjector.html.\r\n\r\nHere is an example of a pattern layout that includes all three tracing fields\r\nand a log entry that could be produced by the layout:\r\n\r\nPattern layout:\r\n\"`%d{HH:mm:ss.SSS} [%t] traceId=%X{openCensusTraceId} spanId=%X{openCensusSpanId} sampled=%X{openCensusTraceSampled} %-5level %logger{36} - %msg%n`\"\r\n\r\nLog entry:\r\n\"`20:45:52.929 [main] traceId=0af7a7bef890695f1c5e85a8e7290164 spanId=d3f07c467ec2fbb2 sampled=true WARN  io.opencensus.contrib.logcorrelation.log4j.demo.OpenCensusLog4jLogCorrelationDemo - my log message`\"\r\n\r\nThe ContextDataInjector implementation must be specified with a system property,\r\ni.e.,\r\n\"`-Dlog4j2.contextDataInjector=io.opencensus.contrib.logcorrelation.log4j.OpenCensusTraceContextDataInjector`\".\r\n\r\nThe system property\r\n\"`io.opencensus.contrib.logcorrelation.log4j.OpenCensusTraceContextDataInjector.spanSelection`\"\r\ncontrols whether tracing data is added to all spans, no spans, or only sampled spans.\r\n\r\n_________________________________________________________________________\r\n\r\nI got the initial idea from https://github.com/census-instrumentation/opencensus-specs/issues/130#issuecomment-405427214.\r\n\r\nI opened a PR to ask for feedback on the high level approach, so it's not complete.  I'm not sure that implementing ContextDataInjector is the best solution.  The main issues that I encountered are:\r\n\r\n- There can only be one ContextDataInjector implementation.  It would be better to implement a class that only inserts new context keys and could coexist with other classes that insert other keys.  I also looked at implementing PatternConverter, but PatternConverter.format probably doesn't run in the same thread that logs the message.\r\n- It's difficult to wrap the default ContextDataInjector.  For example, the method that Log4j calls to get the default is private: https://github.com/apache/logging-log4j2/blob/99c40d3edfd8643cc542c25df59d11a212581076/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataInjectorFactory.java#L82\r\n- The ContextDataInjector interface is complex, so it may be difficult to test all Log4j configurations that could affect it.  For example, it needs to add Log4j configuration properties to its result and handle different implementations of the ThreadContextMap.\r\n- I'm not sure if this is an issue, but I noticed while testing that the ContextDataInjector can't be changed after initialization, because it is stored in a LogEventFactory that is stored in a static variable that is only set in a static initialization block.  It is not affected by configuration reloads.\r\n\r\n/cc @g-easy @adriancole @rghetia "},"comment":{"url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/comments/416291146","html_url":"https://github.com/census-instrumentation/opencensus-java/pull/1371#issuecomment-416291146","issue_url":"https://api.github.com/repos/census-instrumentation/opencensus-java/issues/1371","id":416291146,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNjI5MTE0Ng==","user":{"login":"sebright","id":19807615,"node_id":"MDQ6VXNlcjE5ODA3NjE1","avatar_url":"https://avatars0.githubusercontent.com/u/19807615?v=4","gravatar_id":"","url":"https://api.github.com/users/sebright","html_url":"https://github.com/sebright","followers_url":"https://api.github.com/users/sebright/followers","following_url":"https://api.github.com/users/sebright/following{/other_user}","gists_url":"https://api.github.com/users/sebright/gists{/gist_id}","starred_url":"https://api.github.com/users/sebright/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebright/subscriptions","organizations_url":"https://api.github.com/users/sebright/orgs","repos_url":"https://api.github.com/users/sebright/repos","events_url":"https://api.github.com/users/sebright/events{/privacy}","received_events_url":"https://api.github.com/users/sebright/received_events","type":"User","site_admin":false},"created_at":"2018-08-27T16:51:00Z","updated_at":"2018-08-27T16:51:00Z","author_association":"MEMBER","body":"@adriancole @g-easy @rghetia Thanks for the review!"}}
{"actor":{"display_login":"sebright"}}