Skip to content
Merged
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
1 change: 1 addition & 0 deletions ci/rat-regex.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,5 @@ port\.h
^protocol_binary.h$
^override.css$
^catch[.]hpp$
^configuru.hpp$
^yamlcpp$
81 changes: 81 additions & 0 deletions plugins/experimental/fastcgi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# AtsFastcgi -- a FastCGI plugin implementation for Apache Traffic Server.

This plugin was presented at the ATS Euro-Tour summit in Cork [1]. Its current state
should be considered alpha, the plugin has seen 0 production mileage.

[1] Slides: https://docs.google.com/presentation/d/1kJ3hxbmflh8z4jsquPskeb1xNrLXHAYI2-OQXwwftZU/edit

## Install

```bash
cd src

ATS_SRC="/home/oschaaf/trafficserver"
ATS_EXEC="/usr/local"
make ATS_SRC="$ATS_SRC" ATS_EXEC="$ATS_EXEC"
sudo make ATS_SRC="$ATS_SRC" ATS_EXEC="$ATS_EXEC" install
```


## CONFIG

Add to plugin.config:
```
# For possible settings, see below
ats_mod_fcgi.so /usr/local/etc/trafficserver/fcgi.config
```

## Starting CGI

```
sudo apt-get install php-cgi
php-cgi -b 60000
```

## Running ATS

```
sudo traffic_server -T .*cgi.*
```

## Requesting a php page


```
curl 127.0.0.1/test.php
```

## Config php:

Default directory where php looks for scripts is "/var/www/html/
Simple test page that dump php info:

```
oschaaf@ats-fastcgi:/var/www/html⟫ cat test.php

<?php
// Show all information, defaults to INFO_ALL
phpinfo();
// Show just the module information.
// phpinfo(8) yields identical results.
phpinfo(INFO_MODULES);
?>
```

## Settings

```
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.enabled INT 1
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.hostname STRING localhost
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.server_ip STRING 127.0.0.1
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.server_port STRING 60000
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.include STRING etc/trafficserver/fastcgi.config
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.document_root STRING /var/www/
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.html STRING index.php
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.min_connections INT 2
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.max_connections INT 16
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.max_requests INT 1000
ats_mod_fcgi.config:CONFIG proxy.config.http.fcgi.host.request_queue_size INT 250
```

### Old/stale docs: https://github.com/We-Amp/AtsFastcgi/wiki/Building-ATS-FCGI-from-Source
54 changes: 54 additions & 0 deletions plugins/experimental/fastcgi/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#Please update below required files/directories inorder to work this make file
# 1. ATS_SRC --either set or export env variable path to traffic server src directory
# 2. ATS_EXEC --either set or export env variable path to traffic server exec directory


ifndef ATS_SRC
$(error ATS_SRC is not set)
endif

ifndef ATS_EXEC
$(error ATS_EXEC is not set)
endif

MOD_FCGI_DIR=$(CURDIR)
TRAFFIC_SERVER_SRC_DIR=$(ATS_SRC)
TRAFFIC_SERVER_EXEC_DIR=$(ATS_EXEC)

TSXS?=$(TRAFFIC_SERVER_EXEC_DIR)/bin/tsxs
OBJ_FILES=server_intercept.cc fcgi_config.cc ats_fcgi_client.cc server.cc connection_pool.cc request_queue.cc server_connection.cc

TRAFFIC_SERVER_EXEC_CONF_DIR=$(TRAFFIC_SERVER_EXEC_DIR)/etc/trafficserver/
PLUGIN_CONF_FILES=$(MOD_FCGI_DIR)/config/ats_fastcgi.config

LDLIB_DIR=-L $(TRAFFIC_SERVER_EXEC_DIR)/lib/
LDLIB=-latscppapi

INC=-I $(MOD_FCGI_DIR)\
-I $(TRAFFIC_SERVER_SRC_DIR)/lib\
-I $(TRAFFIC_SERVER_SRC_DIR)/lib/cppapi/include/
COPY_CONFIG = $(shell sudo cp -R '$(PLUGIN_CONF_FILES)' '$(TRAFFIC_SERVER_EXEC_CONF_DIR)')

all:
$(TSXS) -o ats_fastcgi.so -c ats_fastcgi.cc $(LDLIB_DIR) $(LDLIB) $(INC) $(OBJ_FILES)
install:
$(TSXS) -v -i -o ats_fastcgi.so
echo copying config files to ats_fascgi config dir..... $(COPY_CONFIG)
clean:
rm -f *.lo *.so
239 changes: 239 additions & 0 deletions plugins/experimental/fastcgi/src/Profiler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <thread>
#include <mutex>
#include <vector>
#include <string>
#include <chrono>
#include <sys/types.h>
#include <unistd.h>

namespace ats_plugin
{
// A macro to disallow the copy constructor and operator= functions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this better as either an inherited class or using something like

TypeName(const TypeName&) = delete;

// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(TypeName &) = delete; \
void operator=(TypeName) = delete;

// A single profile, stores data of a taken profile
class Profile
{
public:
// Computes the start time and sets the thread id
// The duration of the profiles is in microseconds
void
ComputeStartTime()
{
this->start_time_ =
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
this->thread_id_ = std::hash<std::thread::id>()(std::this_thread::get_id());
this->process_id_ = getpid();
}

// Computes the end time
void
ComputeEndTime()
{
this->end_time_ =
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}

// Gettors
std::size_t
start_time() const
{
return this->start_time_;
}
std::size_t
end_time() const
{
return this->end_time_;
}
std::size_t
thread_id() const
{
return this->thread_id_;
}

std::size_t
process_id() const
{
return this->process_id_;
}
std::size_t
object_id() const
{
return this->object_id_;
}
void
set_object_id(std::size_t objId)
{
object_id_ = objId;
}
const std::string &
task_name() const
{
return this->task_name_;
}

// Settors
void
set_task_name(const std::string &task_name)
{
this->task_name_ = task_name;
}

const std::string &
obj_stage() const
{
return this->obj_stage_;
}
void
set_obj_stage(const std::string &obj_stage)
{
this->obj_stage_ = obj_stage;
}

private:
// The time the profile started
std::chrono::high_resolution_clock::rep start_time_;

// The time the profile ended
std::chrono::high_resolution_clock::rep end_time_;

// The id of the thread
std::size_t thread_id_;
std::size_t process_id_;

std::size_t object_id_;
// The name of the task of the profile
std::string task_name_;
std::string obj_stage_;
};

// Keeps tracks of the taken profiles and saves the data to a JSON.
// In order to take profiles use the embedded class profile taker
// The duration is in microseconds
class Profiler
{
public:
// The storage of profiles
typedef std::vector<Profile> ProfileContainer;

// Empty constructor
Profiler() : record_enabled_(false) {}
// Submits a new profile
void
SubmitProfile(const Profile &profile)
{
// Ignore if not enabled
if (!this->record_enabled_)
return;
std::unique_lock<std::mutex> lock(this->profiles_mutex_);
this->profiles_.push_back(profile);
}

// Removes all the profiles
void
Clear()
{
std::unique_lock<std::mutex> lock(this->profiles_mutex_);
this->profiles_.clear();
}

// Gettors
bool
record_enabled() const
{
return this->record_enabled_;
}
const ProfileContainer &
profiles() const
{
return this->profiles_;
}

void
printProfileLength()
{
std::cout << "Profile Length: " << this->profiles_.size() << std::endl;
}
// Settors
void
set_record_enabled(bool enabled)
{
this->record_enabled_ = enabled;
if (!this->record_enabled_)
this->Clear();
}

private:
// The profiles
ProfileContainer profiles_;

// If true, enabled
bool record_enabled_;

// The mutex for safe access
mutable std::mutex profiles_mutex_;

// DISALLOW_COPY_AND_ASSIGN(Profiler);
};

// Takes a profile during its life time
class ProfileTaker
{
public:
// Initializes a profile
ProfileTaker(Profiler *owner, const std::string &task_name, std::size_t objId, const std::string &phase) : owner_(owner)
{
profile_.ComputeStartTime();
profile_.set_task_name(task_name);
profile_.set_obj_stage(phase);
profile_.set_object_id(objId);
}

// Releases a profile and submits it
~ProfileTaker()
{
// profile_.ComputeEndTime();
owner_->SubmitProfile(this->profile_);
// profile_.set_task_name(this->profile_.task_name());
// profile_.set_obj_stage("E");
Profile endProf;
endProf.ComputeStartTime();
endProf.set_obj_stage("E");
endProf.set_task_name(this->profile_.task_name());
endProf.set_object_id(this->profile_.object_id());
owner_->SubmitProfile(endProf);
}

private:
// The profile to take care of
Profile profile_;

// The owner profiler
Profiler *owner_;

// DISALLOW_COPY_AND_ASSIGN(ProfileTaker);
};
} // namespace ats_plugin
Loading