Skip to main content

Oil & gas — emissions & flaring (ESG)

The problem. Methane and routine flaring are now under hard scrutiny — from regulators with reporting mandates and penalties, and from investors tracking ESG performance. An operator has to measure flare volumes and methane, report them accurately, and catch excess flaring before it becomes a violation or a headline. The data exists across every platform; the job is turning it into auditable monthly numbers and timely alerts.

What we solve here is verifiable emissions reporting and early detection of excess flaring.

Set up demo data

New workspace? Run this once (Python) to create the platform's flare-volume series with a month of daily readings, so the monthly roll-up in step 1 has data. Safe to re-run.

import datahub_sdk, numpy as np, pandas as pd

client = datahub_sdk.DataHubClient.from_env()

client.timeseries.create([datahub_sdk.TimeSeries(
external_id="platform_north_flare_volume_m3", name="North platform flare volume", unit="m3", value_type="float")])
idx = pd.date_range(end=pd.Timestamp.now(tz="UTC"), periods=30, freq="1d")
client.timeseries.insert_from_lists(
timestamps=idx, values=np.random.uniform(3000, 5000, 30), ts="platform_north_flare_volume_m3")

1. Roll emissions up for reporting

Flare volume and methane rate are series per site. Monthly totals — and a CO₂-equivalent from them — are the numbers the regulatory submission and the ESG dashboard are built on. See Query & aggregate.

var filter = new RetrieveFilter();
filter.setExternalId("platform_north_flare_volume_m3");
filter.setStart(ZonedDateTime.now().minusDays(30));
filter.setEnd(ZonedDateTime.now());
filter.setAggregates(List.of("sum"));
filter.setGranularity("1d");

var request = new DataRetriever<RetrieveFilter>();
request.setItems(List.of(filter));

double monthly = client.timeseries().retrieve(request).getItems().get(0)
.getDatapoints().stream().mapToDouble(p -> Double.parseDouble(p.getValue())).sum();

2. Catch excess flaring early

When a site's daily flaring crosses its permitted rate, raise a flaring_exceedance event — with the volume and limit in metadata — so the operator corrects and the compliance team has a dated record. See Turn readings into events.

EventModel exceedance = new EventModel();
exceedance.setExternalId("flaring_exceedance_north_" + System.currentTimeMillis());
exceedance.setType("flaring_exceedance");
exceedance.setStatus("open");
exceedance.setMetadata(Map.of("site", "platform_north", "flared_m3", "142000", "permit_m3", "120000"));
exceedance.setEventTime(ZonedDateTime.now());
client.events().create(List.of(exceedance));

See the result

Print the month's total and chart the daily flaring — the bar chart is what the ESG dashboard shows:

import matplotlib.pyplot as plt

rf = datahub_sdk.RetrieveFilter(ts="platform_north_flare_volume_m3",
start=pd.Timestamp.now(tz="UTC") - pd.Timedelta(days=30), end=pd.Timestamp.now(tz="UTC"),
aggregates=["sum"], granularity="1d")
daily = [dp.sum for dp in client.timeseries.retrieve_datapoints(rf)[0].get_datapoints()]
print(f"monthly flaring: {sum(daily):,.0f} m³") # ~120,000 m³
plt.bar(range(len(daily)), daily); plt.title("North platform — daily flaring (m³)"); plt.show()

See also