Skip to content

Instantly share code, notes, and snippets.

@jaskiratr
Created March 19, 2024 15:41
Show Gist options
  • Save jaskiratr/245fa644afc8a172d9cc073d6b59f1a6 to your computer and use it in GitHub Desktop.
Save jaskiratr/245fa644afc8a172d9cc073d6b59f1a6 to your computer and use it in GitHub Desktop.

Revisions

  1. jaskiratr created this gist Mar 19, 2024.
    85 changes: 85 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    /// <reference types="@fastly/js-compute" />

    import { Logger } from 'fastly:logger';

    addEventListener('fetch', (event) => event.respondWith(handleRequest(event)));

    async function handleRequest(event) {
    const logger = new Logger('my_new_relic_endpoint');

    let logOutput = {
    timestamp: new Date(Date.now()),
    cache_status: 'ERROR',
    client_ip: '127.0.0.1',
    client_device_type: 'Chromebook',
    client_os_name: 'Ubuntu',
    client_os_version: '17.10 (Artful Aardvark)',
    client_browser_name: 'Firefox',
    client_browser_version: '113.0',
    client_as_name: 'zayo bandwidth',
    client_as_number: '1234',
    client_connection_speed: 'broadband',
    client_port: 63850,
    client_rate_bps: 0,
    client_recv_bytes: 74,
    client_requests_count: 1,
    client_resp_body_size_write: 56789,
    client_resp_header_size_write: 1234,
    client_resp_ttfb: 1.342,
    client_rtt_us: 6818,
    content_type: 'text/html; charset=utf-8',
    domain: 'example.com',
    fastly_datacenter: 'HNL',
    fastly_host: 'cache-hnl00001',
    fastly_is_edge: true,
    fastly_region: 'US-Pacific',
    fastly_server: 'cache-hnl00001-HNL',
    host: 'example.com',
    origin_host: 'example.com',
    origin_name: 'n/a',
    request: 'GET',
    request_method: 'GET',
    request_accept_charset: 'utf-8',
    request_accept_language: 'en-US',
    request_referer: '',
    request_user_agent: 'curl/7.68.0',
    resp_status: '200',
    response: 'OK. Testing Log Endpoint',
    service_id: 'U7w1m3BSxe6ldZwPrZtGB3',
    // service_version: '29',
    status: '503',
    time_start: '2023-05-18T23:21:52Z',
    time_end: '2023-05-18T23:21:53Z',
    time_elapsed: 237,
    tls_cipher: 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256',
    tls_version: 'TLS 1.2',
    url: '/',
    user_agent: 'curl/7.68.0',
    user_city: 'san francisco',
    user_country_code: 'US',
    user_continent_code: 'NA',
    user_region: 'CA'
    };
    logger.log(logOutput);

    return new Response(JSON.stringify(logOutput, null, 2), { status: 200 });
    }

    // {

    // "client_ip": "%{req.http.Fastly-Client-IP}V",
    // "geo_country": "%{client.geo.country_name}V",
    // "url": "%{json.escape(req.url)}V",

    // "request_referer": "%{json.escape(req.http.referer)}V",
    // "request_user_agent": "%{json.escape(req.http.User-Agent)}V",
    // "fastly_is_edge": %{if(fastly.ff.visits_this_service == 0, "true", "false")}V,
    // "response_state": "%{json.escape(fastly_info.state)}V",
    // "response_status": %{resp.status}V,
    // "response_reason": %{if(resp.response, "%22"+json.escape(resp.response)+"%22", "null")}V,
    // "response_body_size": %{resp.body_bytes_written}V,
    // "request_method": "%{json.escape(req.method)}V",
    // "request_protocol": "%{json.escape(req.proto)}V",
    // "fastly_server": "%{json.escape(server.identity)}V",
    // "host": "%{if(req.http.Fastly-Orig-Host, req.http.Fastly-Orig-Host, req.http.Host)}V"
    // }
    52 changes: 52 additions & 0 deletions main.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    //! Compute logging demo
    use fastly::http::{header, Method, StatusCode};
    use fastly::{mime, Error, Request, Response};
    use serde_json::json;
    #[fastly::main]
    fn main(req: Request) -> Result<Response, Error> {
    // Filter request methods...
    match req.get_method() {
    // Allow GET and HEAD requests.
    &Method::GET | &Method::HEAD => (),
    // Deny anything else.
    _ => {
    return Ok(Response::from_status(StatusCode::METHOD_NOT_ALLOWED)
    .with_header(header::ALLOW, "GET, HEAD")
    .with_body_text_plain("This method is not allowed\n"))
    }
    };
    // Pattern match on the path...
    match req.get_path() {
    // If request is to the `/` path...
    "/" => {
    // Initialize the logger with the one endpoint
    // Notice we are echoing to stdout, so we don't need separate println! for log-tailing
    log_fastly::Logger::builder()
    .max_level(log::LevelFilter::Info)
    .default_endpoint("my_endpoint")
    .echo_stdout(true)
    .init();
    // Get some request data to log
    let ts = chrono::Utc::now();
    let record = json!({
    "timestamp": ts.format("%F %T%.6f %Z").to_string(),
    "trace_id": std::env::var("FASTLY_TRACE_ID").unwrap_or_else(|_| String::new()),
    "client_ip": req.get_client_ip_addr().unwrap().to_string(),
    "host": req.get_header_str("Host"),
    "request_method": req.get_method_str(),
    "url": req.get_url_str(),
    });
    // Send the logs
    // note we didn't specify a target so it goes to `my_endpoint`, which we set as the default
    // We could have also specified the target log::info!(target: "my_endpoint", "{}", record.to_string())
    log::info!("{}", record.to_string());
    // Send a default synthetic response.
    Ok(Response::from_status(StatusCode::OK)
    .with_content_type(mime::TEXT_HTML_UTF_8)
    .with_body(include_str!("welcome-to-compute.html")))
    }
    // Catch all other requests and return a 404.
    _ => Ok(Response::from_status(StatusCode::NOT_FOUND)
    .with_body_text_plain("The page you requested could not be found\n")),
    }
    }