Skip to content

Add “Query Logs” Action to New Relic Component #16968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions components/new_relic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,38 @@

The New Relic API offers powerful capabilities for monitoring, alerting, and analyzing the performance of your web applications and infrastructure. By using the API within Pipedream, you can automate and orchestrate a vast array of operations that revolve around your application's health and data insights. This can range from triggering workflows based on New Relic alerts, to syncing performance data with other tools, or even automating responses to specific incidents.

# Available Actions

- **New Deployment**: Create a new deployment mark in New Relic. Useful for tracking releases and correlating them with application performance or incidents.
- **Query Logs**: Query logs from New Relic using NRQL (New Relic Query Language). This action allows you to fetch and analyze log data directly from New Relic, enabling advanced monitoring and troubleshooting workflows.

# Example Use Cases

- **Automated Incident Response**: When New Relic detects an anomaly or a performance issue, it can trigger a Pipedream workflow that automatically posts a message to a Slack channel, alerting the relevant team. The workflow could also create a ticket in Jira, ensuring that the incident is tracked and managed properly.

- **Performance Metrics to Data Warehouse**: Set up a Pipedream workflow that periodically fetches performance metrics from New Relic and inserts this data into a Google BigQuery data warehouse. This allows for advanced analysis alongside other business metrics, giving a more comprehensive view of how application performance impacts the overall business.

- **Dynamic Configuration Updates**: If New Relic reports that a service is experiencing high traffic, a Pipedream workflow can interact with other APIs, such as a feature flagging service like LaunchDarkly, to dynamically adjust application features or throttle user access to maintain service stability.

- **Log Analysis and Alerting**: Use the Query Logs action to search for error patterns or specific events in your New Relic logs. For example, you can run an NRQL query like `SELECT * FROM Log WHERE message LIKE '%error%' LIMIT 10` to find recent error logs and trigger downstream actions or notifications.

# Query Logs Action Usage

To use the Query Logs action, provide:
- **Account ID**: Your New Relic account ID.
- **NRQL Query**: The NRQL query to run against your logs (e.g., `SELECT * FROM Log WHERE message LIKE '%timeout%' LIMIT 5`).

The action will return the results of your query, which can be used in subsequent steps of your Pipedream workflow.

## NRQL Query Limitations & Best Practices

- **Query Time Limits**: NRQL queries have a maximum execution time (typically 60 seconds). Complex or unoptimized queries may time out. Break up large queries or use more specific filters to avoid timeouts.
- **Result Size Limits**: The maximum number of results returned per query is limited (e.g., 1,000 records per page). Use pagination (handled automatically by this action) to retrieve large result sets.
- **Data Retention**: Log data retention in New Relic depends on your account and plan. Queries outside the retention window will return no results.
- **Query Optimization Tips**:
- Use `LIMIT` to restrict the number of results and improve performance.
- Filter with `WHERE` clauses to narrow down the dataset (e.g., by log level, service, or time).
- Use time windows (e.g., `SINCE 1 hour ago`) to avoid scanning unnecessary data.
- Avoid `SELECT *` in production workflows; select only the fields you need.
- Test your NRQL queries in the New Relic Query Builder before using them in automation.
- **API Rate Limits**: Excessive querying may be subject to New Relic API rate limits. Monitor your usage and optimize queries to avoid hitting these limits.
103 changes: 103 additions & 0 deletions components/new_relic/actions/query-logs/query-logs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { axios } from "@pipedream/platform";
import app from "../../new_relic.app.mjs";

/**
* Query logs from New Relic using NRQL, supporting pagination via nextCursor and robust error handling.
*/
function sanitizeNrql(nrql) {
// Remove dangerous characters and trim whitespace
return nrql.replace(/[;`$\\]/g, "").trim();
}

function isValidNrql(nrql) {
// Basic validation: must start with SELECT, not empty, and not contain forbidden patterns
const forbidden = /[;`$\\]/;
return (
typeof nrql === "string" &&
nrql.trim().length > 0 &&
/^SELECT\s+/i.test(nrql.trim()) &&
!forbidden.test(nrql)
);
}

export default {
name: "Query Logs",
description: "Query logs from New Relic using NRQL. Supports pagination for large result sets and includes comprehensive error handling.",
key: "new_relic-query-logs",
version: "0.0.5",
type: "action",
props: {
app,
accountId: {
type: "string",
label: "Account ID",
},
nrql: {
type: "string",
label: "NRQL Query",
description: "The NRQL query to run against logs. Example: `SELECT * FROM Log WHERE message LIKE '%error%' LIMIT 1000`",
},
},
async run({ $ }) {
try {
// Validate accountId is a numeric string
if (!/^\d+$/.test(this.accountId)) {
throw new Error("Account ID must be a numeric string");
}
// Validate and sanitize NRQL
if (!isValidNrql(this.nrql)) {
throw new Error("Invalid NRQL query. Must start with SELECT and not contain forbidden characters.");
}
const safeNrql = sanitizeNrql(this.nrql);

const url = `https://api.newrelic.com/graphql`;
const headers = this.app._getHeaders();
let allResults = [];
let nextCursor = null;

do {
const query = `
query($accountId: Int!, $nrql: String!, $nextCursor: String) {
actor {
account(id: $accountId) {
nrql(query: $nrql, nextCursor: $nextCursor) {
results
nextCursor
}
}
}
}
`;
const variables = {
accountId: parseInt(this.accountId, 10),
nrql: safeNrql,
nextCursor,
};
const response = await axios(this, {
method: "POST",
url,
headers,
data: { query, variables },
});

// Handle GraphQL errors
if (response.data.errors) {
throw new Error(`GraphQL errors: ${JSON.stringify(response.data.errors)}`);
}

const nrqlData = response.data?.data?.actor?.account?.nrql;
if (!nrqlData) {
throw new Error("Invalid response structure from New Relic API");
}

if (nrqlData.results) allResults.push(...nrqlData.results);
nextCursor = nrqlData.nextCursor;
} while (nextCursor);

$.export("$summary", `Queried logs with NRQL: ${safeNrql}. Total results: ${allResults.length}`);
return allResults;
} catch (error) {
throw new Error(`Failed to query New Relic logs: ${error.message}`);
}
},
};