Skip to content

Commit

Permalink
[#4737] Refactor Mongodb plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
emeroad authored and RoySRose committed Nov 6, 2018
1 parent 0a436af commit 7b53afb
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 48 deletions.
6 changes: 6 additions & 0 deletions plugins/mongodb/pom.xml
Expand Up @@ -53,5 +53,11 @@
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
<version>${fastxml.jackson-jdk6.version}</version>
</dependency>
</dependencies>
</project>
Expand Up @@ -19,18 +19,22 @@
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.common.util.StringStringValue;
import org.bson.BsonDocument;
import org.bson.BsonDocumentWriter;
import org.bson.BsonWriter;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.json.JsonWriter;

import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* @author Roy Kim
*/
public class MongoUtil {
public final class MongoUtil {

public static final char SEPARATOR = ',';
public static final String SEPARATOR = ",";
private static MongoWriteConcernMapper mongoWriteConcernMapper = new MongoWriteConcernMapper();

private MongoUtil() {
Expand All @@ -52,7 +56,7 @@ public static void recordParsedBson(SpanEventRecorder recorder, StringStringValu
}
}

private static Map<String, ?> getBsonKeyValueMap(Bson bson) {
private static Map<String, ?> getBsonKeyValueMap(Object bson) {
if (bson instanceof BasicDBObject) {
return (BasicDBObject) bson;
} else if (bson instanceof BsonDocument) {
Expand All @@ -79,58 +83,51 @@ public static StringStringValue parseBson(Object[] args, boolean traceBsonBindVa
if (args == null) {
return null;
}
BsonDocument toSend = new BsonDocument();


StringBuilder parsedBson = new StringBuilder();
StringBuilder parameter = new StringBuilder(32);
final List<String> parsedBson = new ArrayList<String>(2);
final List<String> parameter = new ArrayList<String>(2);

for (Object arg : args) {
if (arg instanceof Bson) {

final Map<String, ?> map = getBsonKeyValueMap((Bson) arg);

if (map == null) {
continue;
}
BsonDocumentWriter writer = new BsonDocumentWriter(toSend);
writer.writeStartDocument();

for (Map.Entry<String, ?> entry : map.entrySet()) {
final Map<String, ?> map = getBsonKeyValueMap(arg);
if (map == null) {
continue;
}

writer.writeName(entry.getKey());
writer.writeString("?");
final Writer writer = new StringWriter();
final BsonWriter bsonWriter = new JsonWriter(writer);

if (traceBsonBindValue) {
bsonWriter.writeStartDocument();
for (Map.Entry<String, ?> entry : map.entrySet()) {

appendOutputSeparator(parameter);
if (entry.getValue() instanceof String) {
parameter.append("\"");
parameter.append(entry.getValue());
parameter.append("\"");
} else {
parameter.append(entry.getValue());
}
}
}
writer.writeEndDocument();
bsonWriter.writeName(entry.getKey());
bsonWriter.writeString("?");

if (parsedBson.length() != 0) {
parsedBson.append(",");
if (traceBsonBindValue) {
final Object value = entry.getValue();
String strValue = toStringValue(value);
parameter.add(strValue);
}
parsedBson.append(writer.getDocument().toString());
}
}
bsonWriter.writeEndDocument();
bsonWriter.flush();
String documentString = writer.toString();

parsedBson.add(documentString);

return new StringStringValue(parsedBson.toString(), parameter.toString());
}
String parsedBsonString = StringJoiner.join(parsedBson, SEPARATOR);
String parameterString = StringJoiner.join(parameter, SEPARATOR);
return new StringStringValue(parsedBsonString, parameterString);
}

private static void appendOutputSeparator(StringBuilder output) {
if (output.length() == 0) {
// first parameter
return;

private static String toStringValue(Object value) {
if (value instanceof String) {
return (String) value;
} else {
return String.valueOf(value);
}
output.append(SEPARATOR);
}
}

Expand Up @@ -31,25 +31,30 @@

public class MongoWriteConcernMapper {

private Map<WriteConcern, String> writeConcernMap;
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final Map<WriteConcern, String> writeConcernMap;

public MongoWriteConcernMapper() {
writeConcernMap = buildWriteConcern();
}

writeConcernMap = new HashMap<WriteConcern, String>();
private Map<WriteConcern, String> buildWriteConcern() {
Map<WriteConcern, String> writeConcernMap = new HashMap<WriteConcern, String>();
for (final Field f : WriteConcern.class.getFields()) {
if (Modifier.isStatic(f.getModifiers())
&& f.getType().equals(WriteConcern.class)
&& f.getAnnotation(Deprecated.class) == null) {

String value = f.getName();
try {
writeConcernMap.put((WriteConcern) f.get(null), value);
WriteConcern key = (WriteConcern) f.get(null);
writeConcernMap.put(key, value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
PLogger logger = PLoggerFactory.getLogger(this.getClass());
logger.warn("WriteConcern access error Caused by:" + e.getMessage(), e);
}
}
}
return writeConcernMap;
}

public String getName(WriteConcern writeConcern) {
Expand Down
@@ -0,0 +1,80 @@
/*
* Copyright 2018 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.plugin.mongo;

import com.navercorp.pinpoint.common.util.StringUtils;

import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;

/**
* @author Woonduk Kang(emeroad)
*/
public final class StringJoiner {

private StringJoiner() {
}

public static String join(final Collection<String> collection, final String separator) {
if (collection == null) {
return null;
}
final int size = collection.size();
if (size == 0) {
return "";
}
if (size == 1) {
final Iterator<String> iterator = collection.iterator();
if (iterator.hasNext()) {
return iterator.next();
} else {
throw new ConcurrentModificationException("size:" + collection.size());
}
}

final int bufferSize = getBufferSize(collection, separator);

final StringBuilder builder = new StringBuilder(bufferSize);
final Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
builder.append(iterator.next());
if (!iterator.hasNext()) {
break;
}
builder.append(separator);
}

return builder.toString();
}

private static int getBufferSize(Collection<String> collection, String separator) {
int bufferSize = 0;

final Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
// null == "null"
bufferSize += StringUtils.getLength(value, 4);
if (!iterator.hasNext()) {
break;
}
bufferSize += separator.length();
}
return bufferSize;
}
}
@@ -0,0 +1,76 @@
/*
* Copyright 2018 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.plugin.mongo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.navercorp.pinpoint.common.util.StringStringValue;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;
import java.util.Map;


/**
* @author Woonduk Kang(emeroad)
*/
public class MongoUtilTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

private final ObjectMapper objectMapper = new ObjectMapper();


@Test
public void parseBson() throws IOException {
BasicDBObject query = new BasicDBObject();
query.put("query1", new BasicDBObject("$gt", 1));

StringStringValue stringStringValue = MongoUtil.parseBson(new Object[]{query}, true);

List list = objectMapper.readValue("[" + stringStringValue.getStringValue1()+"]", List.class);
Assert.assertEquals(list.size(), 1);
Map<String, ?> query1Map = (Map<String, ?>) list.get(0);
Assert.assertEquals(query1Map.get("query1"), "?");
}

@Test
public void parsedBson2() throws IOException {
BasicDBObject query = new BasicDBObject();
query.put("query1", new BasicDBObject("$gt", 1));

BasicDBObject query2 = new BasicDBObject();
query2.put("query2", new BasicDBObject("$gt", 2));

StringStringValue stringStringValue = MongoUtil.parseBson(new Object[]{query, query2}, true);
logger.debug("{}", stringStringValue);

List list = objectMapper.readValue("[" + stringStringValue.getStringValue1()+"]", List.class);
logger.debug("list:{}", stringStringValue.getStringValue1());
logger.debug("list:{}", list);

Assert.assertEquals(list.size(), 2);
Map<String, ?> query1Map = (Map<String, ?>) list.get(0);
Assert.assertEquals(query1Map.get("query1"), "?");

Map<String, ?> query2Map = (Map<String, ?>) list.get(1);
Assert.assertEquals(query2Map.get("query2"), "?");
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 2018 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.plugin.mongo;

import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

/**
* @author Woonduk Kang(emeroad)
*/
public class StringJoinerTest {

@Test
public void join1() {
List<String> stringList = new ArrayList<String>();
stringList.add("abc");

String join = StringJoiner.join(stringList, ",");
Assert.assertEquals(join, "abc");

}

@Test
public void join2() {
List<String> stringList = new ArrayList<String>();
stringList.add("abc");
stringList.add("bcd");

String join = StringJoiner.join(stringList, ",");
Assert.assertEquals(join, "abc,bcd");

}

@Test
public void join3() {
List<String> stringList = new ArrayList<String>();
stringList.add("abc");
stringList.add("bcd");
stringList.add("f");

String join = StringJoiner.join(stringList, ",");
Assert.assertEquals(join, "abc,bcd,f");

}
}

0 comments on commit 7b53afb

Please sign in to comment.