npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

moesif-nodejs

v3.6.2

Published

Monitoring agent to log API calls to Moesif for deep API analytics

Downloads

9,547

Readme

Moesif Node.js Middleware

NPM

Built For Total Downloads Software License Source Code

Node.js SDK middleware that automatically logs incoming or outgoing API calls and sends to Moesif for API analytics and monitoring. This SDK supports any Node.js framework including Express, Koa, Nest.js, etc.

Source Code on GitHub

Notes

  • Previously, this NPM package was called moesif-express and has been renamed to moesif-nodejs in 3.0 to reflect support for any Node.js app.
  • The library can capture both incoming and outgoing API Calls depending on how you configure the SDK (See examples).
  • To ensure req body is captured, if you use a body parser middleware like body-parser, apply Moesif middleware after it.

How to install

npm install --save moesif-nodejs

How to use

The following shows how import Moesif for an example app using Express

1. Import the module:


// 1. Import Modules
var express = require('express');
var app = express();
var moesif = require('moesif-nodejs');

// 2. Set the options, the only required field is applicationId.
var options = {

  applicationId: 'Your Moesif Application Id',

  logBody: true,

  identifyUser: function (req, res) {
    if (req.user) {
      return req.user.id;
    }
    return undefined;
  },

  getSessionToken: function (req, res) {
    return req.headers['Authorization'];
  }
};

// 3. Initialize the middleware object with options
var moesifMiddleware = moesif(options);


// 4a. Start capturing outgoing API Calls to 3rd parties like Stripe
// Skip this step if you don't want to capture outgoing API calls
moesifMiddleware.startCaptureOutgoing();

// 4b. Use the Moesif middleware to start capturing incoming API Calls
// If you have a body parser middleware, apply Moesif middleware after any body parsers.
// Skip this step if you don't want to capture incoming API calls
app.use(moesifMiddleware);

If you are using babel or newer versions of nodejs, you can using more modern syntax for importing. For example: import moesif from 'moesif-nodejs'; . Or if you are using ESModules, you can try this:

const moesifImported = await import('moesif-nodejs');
const moesif = moesifImported.default;

2. Enter Moesif Application Id

Your Moesif Application Id can be found in the Moesif Portal. After signing up for a Moesif account, your Moesif Application Id will be displayed during the onboarding steps.

You can always find your Moesif Application Id at any time by logging into the Moesif Portal, click on the bottom left menu, and then clicking Installation.

var moesif = require('moesif-nodejs');
const http = require('http');

var options = {
  applicationId: 'Your Application Id',
  logBody: true,
};

var server = http.createServer(function (req, res) {
  moesif(options)(req, res, function () {
    // Callback
  });

  req.on('end', function () {

    res.write(JSON.stringify({
      message: "hello world!",
      id: 2
    }));
    res.end();
  });
});

server.listen(8080);

Configuration options

If you're using Koa framework, you can access the state object via request.state

logBody

Type: Boolean logBody is default to true, set to false to remove logging request and response body to Moesif.

identifyUser

Type: (Request, Response) => String identifyUser is a function that takes express req and res as arguments and returns a userId. This enables Moesif to attribute API requests to individual unique users so you can understand who calling your API. This can be used simultaneously with identifyCompany to track both individual customers and the companies with which they're associated.

var options = {
  identifyUser: function (req, res) {
    // your code here must return the user id as a string. Example Below
    return req.user ? req.user.id : undefined;
  }
}

identifyCompany

Type: (Request, Response) => String identifyCompany is a function that takes express req and res as arguments and returns a companyId. If your business is B2B, this enables Moesif to attribute API requests to specific companies or organizations so you can understand which accounts are calling your API. This can be used simultaneously with identifyUser to track both individual customers and the companies with which they're associated.

var options = {
  identifyCompany: function (req, res) {
    // your code here must return the company id as a string. Example Below
    return req.headers['X-Organization-Id']
  }
}

getSessionToken

Type: (Request, Response) => String getSessionToken a function that takes express req and res arguments and returns a session token (i.e. such as an API key).

var options = {
  getSessionToken: function (req, res) {
    // your code here must return a string. Example Below
    return req.headers['Authorization'];
  }
}

getApiVersion

Type: (Request, Response) => String getApiVersion is a function that takes a express req and res arguments and returns a string to tag requests with a specific version of your API.

var options = {
  getApiVersion: function (req, res) {
    // your code here must return a string. Example Below
    return req.headers['X-Api-Version']
  }
}

getMetadata

Type: (Request, Response) => Object getMetadata is a function that takes a express req and res and returns an object that allows you to add custom metadata that will be associated with the req. The metadata must be a simple javascript object that can be converted to JSON. For example, you may want to save a VM instance_id, a trace_id, or a tenant_id with the request.

var options = {
  getMetadata: function (req, res) {
    // your code here:
    return {
      foo: 'custom data',
      bar: 'another custom data'
    };
  }
}

skip

Type: (Request, Response) => Boolean skip is a function that takes a express req and res arguments and returns true if the event should be skipped (i.e. not logged) The default is shown below and skips requests to the root path "/".

var options = {
  skip: function (req, res) {
    // your code here must return a boolean. Example Below
    if (req.path === '/' || req.path === '/health') {
      // Skip logging traffic to root path or health probe.
      return true;
    }
    return false
  }
}

maskContent

Type: MoesifEventModel => MoesifEventModel maskContent is a function that takes the final Moesif event model (rather than the Express req/res objects) as an argument before being sent to Moesif. With maskContent, you can make modifications to headers or body such as removing certain header or body fields.

import _ from 'lodash';

var options = {
  maskContent: function(event) {
    // remove any field that you don't want to be sent to Moesif.
    const newEvent = _.omit(event, ['request.headers.Authorization', 'event.response.body.sensitive_field'])
    return newEvent;
  }
};

EventModel format:

{
  "request": {
    "time": "2022-08-08T04:45:42.914",
    "uri": "https://api.acmeinc.com/items/83738/reviews/",
    "verb": "POST",
    "api_version": "1.1.0",
    "ip_address": "61.48.220.123",
    "headers": {
      "Host": "api.acmeinc.com",
      "Accept": "*/*",
      "Connection": "Keep-Alive",
      "Content-Type": "application/json",
      "Content-Length": "126",
      "Accept-Encoding": "gzip"
    },
    "body": {
      "items": [
        {
          "direction_type": 1,
          "item_id": "fwdsfrf",
          "liked": false
        },
        {
          "direction_type": 2,
          "item_id": "d43d3f",
          "liked": true
        }
      ]
    }
  },
  "response": {
    "time": "2022-08-08T04:45:42.924",
    "status": 500,
    "headers": {
      "Vary": "Accept-Encoding",
      "Pragma": "no-cache",
      "Expires": "-1",
      "Content-Type": "application/json; charset=utf-8",
      "Cache-Control": "no-cache"
    },
    "body": {
      "Error": "InvalidArgumentException",
      "Message": "Missing field location"
    }
  },
  "user_id": "my_user_id",
  "company_id": "my_company_id",
  "session_token":"end_user_session_token",
  "tags": "tag1, tag2"
}

debug

Type: Boolean Set to true to print debug logs if you're having integration issues.

For more documentation regarding what fields and meaning, see below or the Moesif Node API Documentation.

Name | Required | Description --------- | -------- | ----------- request | true | The object that specifies the request message request.time| true | Timestamp for the request in ISO 8601 format request.uri| true | Full uri such as https://api.com/?query=string including host, query string, etc request.verb| true | HTTP method used, i.e. GET, POST request.api_version| false | API Version you want to tag this request with such as 1.0.0 request.ip_address| false | IP address of the requester, If not set, we use the IP address of your logging API calls. request.headers| true | Headers of the request as a Map<string, string>. Multiple headers with the same key name should be combined together such that the values are joined by a comma. HTTP Header Protocol on w3.org request.body| false | Body of the request in JSON format or Base64 encoded binary data (see transfer_encoding) request.transfer_encoding| false | A string that specifies the transfer encoding of Body being sent to Moesif. If field nonexistent, body assumed to be JSON or text. Only possible value is base64 for sending binary data like protobuf || response | false | The object that specifies the response message, not set implies no response received such as a timeout. response.time| true | Timestamp for the response in ISO 8601 format response.status| true | HTTP status code as number such as 200 or 500 response.ip_address| false | IP address of the responding server response.headers| true | Headers of the response as a Map<string, string>. Multiple headers with the same key name should be combined together such that the values are joined by a comma. HTTP Header Protocol on w3.org response.body| false | Body of the response in JSON format or Base64 encoded binary data (see transfer_encoding) response.transfer_encoding| false | A string that specifies the transfer encoding of Body being sent to Moesif. If field nonexistent, body assumed to be JSON or text. Only possible value is base64 for sending binary data like protobuf || session_token | Recommend | The end user session token such as a JWT or API key, which may or may not be temporary. Moesif will auto-detect the session token automatically if not set. user_id | Recommend | Identifies this API call to a permanent user_id metadata | false | A JSON Object consisting of any custom metadata to be stored with this event.

noAutoHideSensitive

Type: boolean Default 'false'. Before sending any data for analysis, automatically check the data (headers and body) and one way hash strings or numbers that looks like a credit card or password. Turn this option to true if you want to implement your specific maskContent function or you want to send all data to be analyzed.

callback

Type: error => null callback is for internal errors. For example, if there is has been an error sending events to Moesif or network issue, you can use this to see if there is any issues with integration.

disableBatching

Type: boolean Default 'false'. By default, Moesif Express batches the Events. Turn this to true, this if you would like to send the API events one by one.

batchSize

Type: number Default 200. If batching is not disabled, this is the batchSize of API events that will trigger flushing of queue and sending the data to Moesif. If set, must be greater than 1.

batchMaxTime

Type: number in milliseconds Default 2000. If batching is not disabled, this is the maximum wait time (approximately) before triggering flushing of the queue and sending to Moesif. If set, it must be greater than 500 (milliseconds).

retry

Type: number of time to retry if fails to post to Moesif. If set, must be a number between 0 to 3.

requestMaxBodySize

Type: number Default 100000. Maximum request body size in bytes to log when sending the data to Moesif.

responseMaxBodySize

Type: number Default 100000. Maximum response body size in bytes to log when sending the data to Moesif.

Capture Outgoing

If you want to capture all outgoing API calls from your Node.js app to third parties like Stripe or to your own dependencies, call startCaptureOutgoing() to start capturing.

var moesifMiddleware = moesif(options);
moesifMiddleware.startCaptureOutgoing();

This method can be used to capture outgoing API calls even if you are not using the Express Middleware or having any incoming API calls.

The same set of above options is also applied to outgoing API calls, with a few key differences:

For options functions that take req and res as input arguments, the request and response objects passed in are not Express or Node.js req or res objects when the request is outgoing, but Moesif does mock some of the fields for convenience. Only a subset of the Node.js req/res fields are available. Specifically:

  • _mo_mocked: Set to true if it is a mocked request or response object (i.e. outgoing API Call)
  • headers: object, a mapping of header names to header values. Case sensitive
  • url: string. Full request URL.
  • method: string. Method/verb such as GET or POST.
  • statusCode: number. Response HTTP status code
  • getHeader: function. (string) => string. Reads out a header on the request. Name is case insensitive
  • get: function. (string) => string. Reads out a header on the request. Name is case insensitive
  • body: JSON object. The request body as sent to Moesif

Update a Single User

Create or update a user profile in Moesif. The metadata field can be any customer demographic or other info you want to store. Only the userId field is required. This method is a convenient helper that calls the Moesif API lib. For details, visit the Node.js API Reference.

var moesifMiddleware = moesif(options);

// Only userId is required.
// Campaign object is optional, but useful if you want to track ROI of acquisition channels
// See https://www.moesif.com/docs/api#users for campaign schema
// metadata can be any custom object
var user = {
  userId: '12345',
  companyId: '67890', // If set, associate user with a company object
  metadata: {
    email: '[email protected]',
    firstName: 'John',
    lastName: 'Doe',
    title: 'Software Engineer',
    salesInfo: {
        stage: 'Customer',
        lifetimeValue: 24000,
        accountOwner: '[email protected]'
    }
  }
};

moesifMiddleware.updateUser(user, callback);

Update Users in Batch

Similar to updateUser, but used to update a list of users in one batch. Only the userId field is required. This method is a convenient helper that calls the Moesif API lib. For details, visit the Node.js API Reference.

var moesifMiddleware = moesif(options);

// Only userId is required.
// Campaign object is optional, but useful if you want to track ROI of acquisition channels
// See https://www.moesif.com/docs/api#users for campaign schema
// metadata can be any custom object
var user = {
  userId: '12345',
  companyId: '67890', // If set, associate user with a company object
  metadata: {
    email: '[email protected]',
    firstName: 'John',
    lastName: 'Doe',
    title: 'Software Engineer',
    salesInfo: {
        stage: 'Customer',
        lifetimeValue: 24000,
        accountOwner: '[email protected]'
    }
  }
};

var users = [user]

moesifMiddleware.updateUsersBatch(users, callback);

Update a Single Company

Create or update a company profile in Moesif. The metadata field can be any company demographic or other info you want to store. Only the companyId field is required. This method is a convenient helper that calls the Moesif API lib. For details, visit the Node.js API Reference.

var moesifMiddleware = moesif(options);

// Only companyId is required.
// Campaign object is optional, but useful if you want to track ROI of acquisition channels
// See https://www.moesif.com/docs/api#update-a-company for campaign schema
// metadata can be any custom object
var company = {
  companyId: '67890',
  companyDomain: 'acmeinc.com', // If domain is set, Moesif will enrich your profiles with publicly available info
  metadata: {
    orgName: 'Acme, Inc',
    planName: 'Free Plan',
    dealStage: 'Lead',
    mrr: 24000,
    demographics: {
      alexaRanking: 500000,
      employeeCount: 47
    }
  }
};

moesifMiddleware.updateCompany(company, callback);

Update Companies in Batch

Similar to updateCompany, but used to update a list of companies in one batch. Only the companyId field is required. This method is a convenient helper that calls the Moesif API lib. For details, visit the Node.js API Reference.

var moesifMiddleware = moesif(options);

// Only companyId is required.
// Campaign object is optional, but useful if you want to track ROI of acquisition channels
// See https://www.moesif.com/docs/api#update-a-company for campaign schema
// metadata can be any custom object
var company = {
  companyId: '67890',
  companyDomain: 'acmeinc.com', // If domain is set, Moesif will enrich your profiles with publicly available info
  metadata: {
    orgName: 'Acme, Inc',
    planName: 'Free Plan',
    dealStage: 'Lead',
    mrr: 24000,
    demographics: {
      alexaRanking: 500000,
      employeeCount: 47
    }
  }
};

var companies = [company]

moesifMiddleware.updateCompaniesBatch(companies, callback);

Koa Support

The Moesif option handles take a Node.js req and res as arguments. You can also access the Koa state object via req.state. As an example, many Koa auth middleware save the authenticated user on ctx.state.user, so you can access via Moesif options like identifyUser:

  identifyUser: function (req, res) {
    if (req.state && req.state.user) {
      return req.state.user.sub;
    }
    return undefined;
  },

Examples

Other integrations

To view more documentation on integration options, please visit the Integration Options Documentation.