1 /**
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *      http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */

14 package net.logstash.logback.composite.loggingevent;
15
16 import java.io.IOException;
17
18 import net.logstash.logback.argument.StructuredArgument;
19 import net.logstash.logback.composite.AbstractFieldJsonProvider;
20 import net.logstash.logback.composite.FieldNamesAware;
21 import net.logstash.logback.fieldnames.LogstashFieldNames;
22 import ch.qos.logback.classic.spi.ILoggingEvent;
23
24 import com.fasterxml.jackson.core.JsonGenerator;
25
26 /**
27  * Include the logging event's {@link ILoggingEvent#getArgumentArray()} in the JSON output.
28  * <p>
29  *
30  * Arguments that are an instance of {@link StructuredArgument} will be output
31  * as specified by {@link StructuredArgument#writeTo(JsonGenerator)}.
32  * <p>
33  * 
34  * Non-{@link StructuredArgument}s will be omitted unless {@link #includeNonStructuredArguments} is true.
35  * When true, they will be included in the JSON output as separate fields
36  * whose names are {@link #nonStructuredArgumentsFieldPrefix} plus the argument index.
37  * (For example, "arg0").
38  * </p>
39  *
40  * If the fieldName is non-null, then the arguments will be written to that field as a subobject.
41  * Otherwise, the arguments are written inline.
42  */

43 public class ArgumentsJsonProvider extends AbstractFieldJsonProvider<ILoggingEvent> implements FieldNamesAware<LogstashFieldNames> {
44
45     private boolean includeStructuredArguments = true;
46     private boolean includeNonStructuredArguments;
47     private String nonStructuredArgumentsFieldPrefix = "arg";
48
49     @Override
50     public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
51         
52         if (!includeStructuredArguments && !includeNonStructuredArguments) {
53             // Short-circuit if nothing is included
54             return;
55         }
56
57         Object[] args = event.getArgumentArray();
58
59         if (args == null || args.length == 0) {
60             return;
61         }
62
63         boolean hasWrittenFieldName = false;
64         
65         for (int argIndex = 0; argIndex < args.length; argIndex++) {
66
67             Object arg = args[argIndex];
68
69             if (arg instanceof StructuredArgument) {
70                 if (includeStructuredArguments) {
71                     if (!hasWrittenFieldName && getFieldName() != null) {
72                         generator.writeObjectFieldStart(getFieldName());
73                         hasWrittenFieldName = true;
74                     }
75                     StructuredArgument structuredArgument = (StructuredArgument) arg;
76                     structuredArgument.writeTo(generator);
77                 }
78             } else if (includeNonStructuredArguments) {
79                 if (!hasWrittenFieldName && getFieldName() != null) {
80                     generator.writeObjectFieldStart(getFieldName());
81                     hasWrittenFieldName = true;
82                 }
83                 String fieldName = nonStructuredArgumentsFieldPrefix + argIndex;
84                 generator.writeObjectField(fieldName, arg);
85             }
86         }
87
88         if (hasWrittenFieldName) {
89             generator.writeEndObject();
90         }
91     }
92     
93     public boolean isIncludeStructuredArguments() {
94         return includeStructuredArguments;
95     }
96
97     public void setIncludeStructuredArguments(boolean includeStructuredArguments) {
98         this.includeStructuredArguments = includeStructuredArguments;
99     }
100     
101     public boolean isIncludeNonStructuredArguments() {
102         return includeNonStructuredArguments;
103     }
104
105     public void setIncludeNonStructuredArguments(boolean includeNonStructuredArguments) {
106         this.includeNonStructuredArguments = includeNonStructuredArguments;
107     }
108
109     public String getNonStructuredArgumentsFieldPrefix() {
110         return nonStructuredArgumentsFieldPrefix;
111     }
112
113     public void setNonStructuredArgumentsFieldPrefix(String nonStructuredArgumentsFieldPrefix) {
114         this.nonStructuredArgumentsFieldPrefix = nonStructuredArgumentsFieldPrefix;
115     }
116     
117     @Override
118     public void setFieldNames(LogstashFieldNames fieldNames) {
119         setFieldName(fieldNames.getArguments());
120     }
121 }
122