Skip to content

Commit

Permalink
Remove meteorhacks:meteorx dependency.
Browse files Browse the repository at this point in the history
This commit brings the relevant bits of meteorhacks:meteorx into the
mdg:meteor-apm-agent package, so that various issues can be fixed without
forking or continuing to maintain meteorhacks:meteorx.

Related:
meteor/meteor#10337 (comment)
meteorhacks/meteorx#8
meteorhacks/meteorx#9
abecks/meteor-fast-render#25
  • Loading branch information
benjamn committed Nov 30, 2018
1 parent 5a780b3 commit 0e2861d
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 55 deletions.
9 changes: 7 additions & 2 deletions lib/hijack/db.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
MongoConnection,
MongoCursor,
} from "./meteorx.js";

// This hijack is important to make sure, collections created before
// we hijack dbOps, even gets tracked.
// Meteor does not simply expose MongoConnection object to the client
Expand Down Expand Up @@ -26,7 +31,7 @@ MongoInternals.RemoteCollectionDriver.prototype.open = function open(name) {
};

hijackDBOps = function hijackDBOps() {
var mongoConnectionProto = MeteorX.MongoConnection.prototype;
var mongoConnectionProto = MongoConnection.prototype;
//findOne is handled by find - so no need to track it
//upsert is handles by update
['find', 'update', 'remove', 'insert', '_ensureIndex', '_dropIndex'].forEach(function(func) {
Expand Down Expand Up @@ -94,7 +99,7 @@ hijackDBOps = function hijackDBOps() {
};
});

var cursorProto = MeteorX.MongoCursor.prototype;
var cursorProto = MongoCursor.prototype;
['forEach', 'map', 'fetch', 'count', 'observeChanges', 'observe', 'rewind'].forEach(function(type) {
var originalFunc = cursorProto[type];
cursorProto[type] = function() {
Expand Down
35 changes: 22 additions & 13 deletions lib/hijack/instrument.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import {
MongoOplogDriver,
MongoPollingDriver,
Multiplexer,
Server,
Session,
Subscription,
} from "./meteorx.js";

var logger = Npm.require('debug')('kadira:hijack:instrument');

var instrumented = false;
Expand All @@ -9,22 +18,22 @@ Kadira._startInstrumenting = function(callback) {

instrumented = true;
wrapStringifyDDP()
MeteorX.onReady(function() {
//instrumenting session
wrapServer(MeteorX.Server.prototype);
wrapSession(MeteorX.Session.prototype);
wrapSubscription(MeteorX.Subscription.prototype);

if(MeteorX.MongoOplogDriver) {
wrapOplogObserveDriver(MeteorX.MongoOplogDriver.prototype);
Meteor.startup(async function () {
wrapServer(Server.prototype);

wrapSession(Session.prototype);
wrapSubscription(Subscription.prototype);

if (MongoOplogDriver) {
wrapOplogObserveDriver(MongoOplogDriver.prototype);
}

if(MeteorX.MongoPollingDriver) {
wrapPollingObserveDriver(MeteorX.MongoPollingDriver.prototype);
if (MongoPollingDriver) {
wrapPollingObserveDriver(MongoPollingDriver.prototype);
}

if(MeteorX.Multiplexer) {
wrapMultiplexer(MeteorX.Multiplexer.prototype);
if (Multiplexer) {
wrapMultiplexer(Multiplexer.prototype);
}

wrapForCountingObservers();
Expand All @@ -40,4 +49,4 @@ Kadira._startInstrumenting = function(callback) {
// Otherwise, CPU profile can't see all our custom labeling
Kadira._startInstrumenting(function() {
console.log('Kadira: completed instrumenting the app')
});
});
100 changes: 100 additions & 0 deletions lib/hijack/meteorx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Various tricks for accessing "private" Meteor APIs borrowed from the
// now-unmaintained meteorhacks:meteorx package.

export const Server = Meteor.server.constructor;

function getSession() {
const fakeSocket = {
send() {},
close() {},
headers: []
};

const server = Meteor.default_server;

server._handleConnect(fakeSocket, {
msg: "connect",
version: "pre1",
support: ["pre1"]
});

const session = fakeSocket._meteorSession;

server._removeSession(session);

return session;
}

const session = getSession();
export const Session = session.constructor;

const collection = new Mongo.Collection("__dummy_coll_" + Random.id());
collection.findOne();
const cursor = collection.find();
export const MongoCursor = cursor.constructor;

function getMultiplexer(cursor) {
const handle = cursor.observeChanges({
added() {}
});
handle.stop();
return handle._multiplexer;
}

export const Multiplexer = getMultiplexer(cursor).constructor;

export const MongoConnection =
MongoInternals.defaultRemoteCollectionDriver().mongo.constructor;

function getSubscription(session) {
const subId = Random.id();

session._startSubscription(function () {
this.ready();
}, subId, [], "__dummy_pub_" + Random.id());

const subscription = session._namedSubs instanceof Map
? session._namedSubs.get(subId)
: session._namedSubs[subId];

session._stopSubscription(subId);

return subscription;
}

export const Subscription = getSubscription(session).constructor;

function getObserverDriver(cursor) {
const multiplexer = getMultiplexer(cursor);
return multiplexer && multiplexer._observeDriver || null;
}

function getMongoOplogDriver() {
const driver = getObserverDriver(cursor);
let MongoOplogDriver = driver && driver.constructor || null;
if (MongoOplogDriver &&
typeof MongoOplogDriver.cursorSupported !== "function") {
return null;
}
return MongoOplogDriver;
}

export const MongoOplogDriver = getMongoOplogDriver();

function getMongoPollingDriver() {
const cursor = collection.find({}, {
limit: 20,
_disableOplog: true,
});

const driver = getObserverDriver(cursor);

// verify observer driver is a polling driver
if (driver && typeof driver.constructor.cursorSupported === "undefined") {
return driver.constructor;
}

return null;
}

export const MongoPollingDriver = getMongoPollingDriver();
67 changes: 37 additions & 30 deletions lib/hijack/set_labels.js
Original file line number Diff line number Diff line change
@@ -1,91 +1,98 @@
import {
Session,
Multiplexer,
MongoConnection,
MongoCursor,
} from "./meteorx.js";

setLabels = function () {
// name Session.prototype.send
var originalSend = MeteorX.Session.prototype.send;
MeteorX.Session.prototype.send = function kadira_Session_send (msg) {
var originalSend = Session.prototype.send;
Session.prototype.send = function kadira_Session_send (msg) {
return originalSend.call(this, msg);
}

// name Multiplexer initial adds
var originalSendAdds = MeteorX.Multiplexer.prototype._sendAdds;
MeteorX.Multiplexer.prototype._sendAdds = function kadira_Multiplexer_sendAdds (handle) {
var originalSendAdds = Multiplexer.prototype._sendAdds;
Multiplexer.prototype._sendAdds = function kadira_Multiplexer_sendAdds (handle) {
return originalSendAdds.call(this, handle);
}

// name MongoConnection insert
var originalMongoInsert = MeteorX.MongoConnection.prototype._insert;
MeteorX.MongoConnection.prototype._insert = function kadira_MongoConnection_insert (coll, doc, cb) {
var originalMongoInsert = MongoConnection.prototype._insert;
MongoConnection.prototype._insert = function kadira_MongoConnection_insert (coll, doc, cb) {
return originalMongoInsert.call(this, coll, doc, cb);
}

// name MongoConnection update
var originalMongoUpdate = MeteorX.MongoConnection.prototype._update;
MeteorX.MongoConnection.prototype._update = function kadira_MongoConnection_update (coll, selector, mod, options, cb) {
var originalMongoUpdate = MongoConnection.prototype._update;
MongoConnection.prototype._update = function kadira_MongoConnection_update (coll, selector, mod, options, cb) {
return originalMongoUpdate.call(this, coll, selector, mod, options, cb);
}

// name MongoConnection remove
var originalMongoRemove = MeteorX.MongoConnection.prototype._remove;
MeteorX.MongoConnection.prototype._remove = function kadira_MongoConnection_remove (coll, selector, cb) {
var originalMongoRemove = MongoConnection.prototype._remove;
MongoConnection.prototype._remove = function kadira_MongoConnection_remove (coll, selector, cb) {
return originalMongoRemove.call(this, coll, selector, cb);
}

// name Pubsub added
var originalPubsubAdded = MeteorX.Session.prototype.sendAdded;
MeteorX.Session.prototype.sendAdded = function kadira_Session_sendAdded (coll, id, fields) {
var originalPubsubAdded = Session.prototype.sendAdded;
Session.prototype.sendAdded = function kadira_Session_sendAdded (coll, id, fields) {
return originalPubsubAdded.call(this, coll, id, fields);
}

// name Pubsub changed
var originalPubsubChanged = MeteorX.Session.prototype.sendChanged;
MeteorX.Session.prototype.sendChanged = function kadira_Session_sendChanged (coll, id, fields) {
var originalPubsubChanged = Session.prototype.sendChanged;
Session.prototype.sendChanged = function kadira_Session_sendChanged (coll, id, fields) {
return originalPubsubChanged.call(this, coll, id, fields);
}

// name Pubsub removed
var originalPubsubRemoved = MeteorX.Session.prototype.sendRemoved;
MeteorX.Session.prototype.sendRemoved = function kadira_Session_sendRemoved (coll, id) {
var originalPubsubRemoved = Session.prototype.sendRemoved;
Session.prototype.sendRemoved = function kadira_Session_sendRemoved (coll, id) {
return originalPubsubRemoved.call(this, coll, id);
}

// name MongoCursor forEach
var originalCursorForEach = MeteorX.MongoCursor.prototype.forEach;
MeteorX.MongoCursor.prototype.forEach = function kadira_Cursor_forEach () {
var originalCursorForEach = MongoCursor.prototype.forEach;
MongoCursor.prototype.forEach = function kadira_Cursor_forEach () {
return originalCursorForEach.apply(this, arguments);
}

// name MongoCursor map
var originalCursorMap = MeteorX.MongoCursor.prototype.map;
MeteorX.MongoCursor.prototype.map = function kadira_Cursor_map () {
var originalCursorMap = MongoCursor.prototype.map;
MongoCursor.prototype.map = function kadira_Cursor_map () {
return originalCursorMap.apply(this, arguments);
}

// name MongoCursor fetch
var originalCursorFetch = MeteorX.MongoCursor.prototype.fetch;
MeteorX.MongoCursor.prototype.fetch = function kadira_Cursor_fetch () {
var originalCursorFetch = MongoCursor.prototype.fetch;
MongoCursor.prototype.fetch = function kadira_Cursor_fetch () {
return originalCursorFetch.apply(this, arguments);
}

// name MongoCursor count
var originalCursorCount = MeteorX.MongoCursor.prototype.count;
MeteorX.MongoCursor.prototype.count = function kadira_Cursor_count () {
var originalCursorCount = MongoCursor.prototype.count;
MongoCursor.prototype.count = function kadira_Cursor_count () {
return originalCursorCount.apply(this, arguments);
}

// name MongoCursor observeChanges
var originalCursorObserveChanges = MeteorX.MongoCursor.prototype.observeChanges;
MeteorX.MongoCursor.prototype.observeChanges = function kadira_Cursor_observeChanges () {
var originalCursorObserveChanges = MongoCursor.prototype.observeChanges;
MongoCursor.prototype.observeChanges = function kadira_Cursor_observeChanges () {
return originalCursorObserveChanges.apply(this, arguments);
}

// name MongoCursor observe
var originalCursorObserve = MeteorX.MongoCursor.prototype.observe;
MeteorX.MongoCursor.prototype.observe = function kadira_Cursor_observe () {
var originalCursorObserve = MongoCursor.prototype.observe;
MongoCursor.prototype.observe = function kadira_Cursor_observe () {
return originalCursorObserve.apply(this, arguments);
}

// name MongoCursor rewind
var originalCursorRewind = MeteorX.MongoCursor.prototype.rewind;
MeteorX.MongoCursor.prototype.rewind = function kadira_Cursor_rewind () {
var originalCursorRewind = MongoCursor.prototype.rewind;
MongoCursor.prototype.rewind = function kadira_Cursor_rewind () {
return originalCursorRewind.apply(this, arguments);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/hijack/wrap_observers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { MongoConnection } from "./meteorx.js";

wrapOplogObserveDriver = function(proto) {
// Track the polled documents. This is reflect to the RAM size and
// for the CPU usage directly
Expand Down Expand Up @@ -156,7 +158,7 @@ wrapMultiplexer = function(proto) {

wrapForCountingObservers = function() {
// to count observers
var mongoConnectionProto = MeteorX.MongoConnection.prototype;
var mongoConnectionProto = MongoConnection.prototype;
var originalObserveChanges = mongoConnectionProto._observeChanges;
mongoConnectionProto._observeChanges = function(cursorDescription, ordered, callbacks) {
var ret = originalObserveChanges.call(this, cursorDescription, ordered, callbacks);
Expand Down Expand Up @@ -211,4 +213,4 @@ wrapForCountingObservers = function() {

return ret;
}
};
};
15 changes: 12 additions & 3 deletions package.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,23 @@ Package.on_test(function(api) {
function configurePackage(api) {
if(api.versionsFrom) {
api.versionsFrom('[email protected]');
api.use('meteorhacks:[email protected]', ['server']);
api.use('meteorhacks:[email protected]', {weak: true});
}

api.use([
'minimongo', 'livedata', 'mongo-livedata', 'ejson', 'ddp-common',
'underscore', 'http', 'email', 'random'
'ecmascript',
'mongo',
'minimongo',
'livedata',
'mongo-livedata',
'ejson',
'ddp-common',
'underscore',
'http',
'email',
'random',
], ['server']);

api.use(['underscore', 'random', 'http', 'localstorage'], ['client']);

// common before
Expand Down
Loading

0 comments on commit 0e2861d

Please sign in to comment.